本篇文章更新時間:2021/01/29
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~
如果本站內容對你有幫助,歡迎使用 BFX Pay 加密貨幣 或 新台幣 贊助支持。
續上篇 [HAProxy] 建立 WordPress 負載平衡 Load balancing 架構筆記 把憑證處理的部分拆到這篇來集中。
環境一樣是 Ubuntu 20.04 Server
+ 套件安裝的 HA-Proxy version 2.0.13-2ubuntu0.1 2020/09/08
關於憑證的作業,這塊 完全不推薦使用 Let's Encrypt
來作業,但玩票性質還是可以用它來試試!
會說不推薦的原因主要是高流量的網站經不起停機,使用 Let's Encrypt 有驗證網域的階段,這會導致服務中斷,如果你網站流量經常性高負載,隨意切服務導致客戶消費體驗中斷,可能就是一大筆錢的流失。所以憑證部分會建議購買一組用,能切換指向 IP 前就設定好新主機/架構,無痛切換。
Let's Encrypt 自動續約
新版本的 Let's Encrypt 安裝方式改透過 snapd
套件處理,安裝方式如下:
apt install snapd
snap install core; snap refresh core
snap install --classic certbot
HAProxy 設定開啟服務來接收驗證的操作:
frontend frontend-http
bind :80
bind :::80
mode http
# ACL for detecting Let's Encrypt validtion requests
acl is_certbot path_beg /.well-known/acme-challenge/
use_backend backend-certbot if is_certbot
# Contains certbot stand-alone webserver
backend backend-certbot
mode http
server certbot 127.0.0.1:9080
確認設定無誤後重新載入 HAProxy 設定。
然後使用 Let's Encrypt 這邊要請求新的授權指令為:
certbot certonly --standalone --preferred-challenges http --http-01-address 127.0.0.1 --http-01-port 9080 -d mydomain.com --email [email protected] --agree-tos --non-interactive
如果網域有指向正確到這台 HAProxy 主機的話,這時候 certbot
會開啟一個驗證服務在 9080
Port,剛好給 HAProxy 接收轉發,完成驗證!
完成驗證會取得憑證檔案在 /etc/letsencrypt/live/
,搭配下方 Shell Script ( /etc/haproxy/prepareLetsEncryptCertificates.sh
)組裝憑證串給 HAProxy 使用:
#!/bin/bash
# Loop through all Let's Encrypt certificates
for CERTIFICATE in `find /etc/letsencrypt/live/* -type d`; do
CERTIFICATE=`basename $CERTIFICATE`
# Combine certificate and private key to single file
cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /etc/haproxy/ssl/$CERTIFICATE.pem
done
使用前先建立一個目錄存放: mkdir /etc/haproxy/ssl
執行這隻 Shell Script
chmod +x /etc/haproxy/prepareLetsEncryptCertificates.sh
sh /etc/haproxy/prepareLetsEncryptCertificates.sh
如此一來就完成憑證串接的任務,可以準備重新載入 HAProxy 使用了。
自動續約的部分如下:
建立 Shell Script 檔案: /etc/haproxy/renewLetsEncryptCertificates.sh
#!/bin/bash
certbot renew --standalone --preferred-challenges http --http-01-address 127.0.0.1 --http-01-port 9080 --post-hook "/etc/haproxy/prepareLetsEncryptCertificates.sh && systemctl reload haproxy.service" --quiet
記得賦予執行權限: chmod +x /etc/haproxy/renewLetsEncryptCertificates.sh
最後掛載 Cron job 定期續約。
0 0 * * * /bin/sh /etc/haproxy/renewLetsEncryptCertificates.sh
最後才補上 HAProxy 設定讀取憑證開始使用
frontend frontend-https
bind :443 ssl crt /etc/haproxy/ssl/
bind :::443 ssl crt /etc/haproxy/ssl/
mode http
# ACL for detecting Let's Encrypt validtion requests
acl is_certbot path_beg /.well-known/acme-challenge/
use_backend backend-certbot if is_certbot
default_backend backend-web
這部分文獻參考 LET’S ENCRYPT WITH HAPROXY。 一次全上文獻裡的 HAProxy 設定會出錯,要注意有先後順序,也就是先要開啟的是 HTTP 服務與 certbot 服務來做驗證,最後才是補上 HTTPS 的服務設定。
default-dh-param 預設加密長度問題
主要是使用預設DH金鑰的檔案長度已經過時了,會出現錯誤訊息:
Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.
解決辦法就是不要用預設的,自己產生過:
openssl dhparam -out /etc/haproxy/dhparams.pem 2048
調整 HAProxy 設定 vi /etc/haproxy/haproxy.cfg
在 ssl-default-server-ciphers PROFILE=SYSTEM
這行後補上 ssl-dh-param-file /etc/haproxy/dhparams.pem
這行,存擋重啟,完成!
參考:HAproxy SSL/TLS Warning: Setting tune.ssl.default-dh-param to 1024 by default
憑證串接順序
由於不推薦使用 Let's Encrypt 作為高流量的網站上線使用,所以如果是自己買過的憑證,就要把他串起來餵給 HAProxy 使用。
串接順序是:
-----BEGIN PRIVATE KEY-----
[Your private key 私鑰]
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
[Your certificate 憑證]
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
[Intermediate#1 certificate 中繼憑證A]
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
[Intermediate#2 certificate 中繼憑證B]
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
[Root certificate 根憑證]
-----END CERTIFICATE-----
參考:HAProxy and Intermediate SSL Certificate Issue
HAProxy 設定使用 SNI 分流方法
伺服器名稱指示(英語:Server Name Indication,縮寫:SNI) 這情況常見在單一主機多網站代管,且每個網站又有 HTTPS 憑證需求的時候。
憑證部分 HAProxy 可以掃目錄的方式處理,不用指定 pem
檔案,但設定上要使用 ssl_fc_sni
關鍵字補上判斷網域來轉請求。
詳細參考設定:
frontend ft_test
mode http
bind 0.0.0.0:443 ssl crt /etc/haproxy/ssl/
use_backend bk_cert1 if { ssl_fc_sni my.example1.com } # content switching based on SNI
use_backend bk_cert2 if { ssl_fc_sni my.example2.org } # content switching based on SNI
backend bk_cert1
mode http
server srv1 :80
backend bk_cert2
mode http
server srv2 :80
參考:Configure multiple SSL certificates in Haproxy
後記
憑證部分會處理到的常見操作應該就這些了吧!至少目前還沒碰到過其他需求,等碰到再補吧~ 有錯也歡迎留言或來信告知。