HAProxy 輕鬆整合 SSL/TLS Client Certificate
利用 SSL Client Certificate 驗證身份
一般網站使用 HTTPS 進行連線時,大多數情況都是為了把傳輸的資料進行加密,理論上透過 2048 長度的密鑰進行 SSL 通道加密是安全的。但其實 SSL 還提供另一個功能,就是用來確認身份。我們可以透過 OpenSSL 由我們的憑證簽發一組 SSL 用戶連線憑證,可以用來確認與驗證連線來源,你大可將之想像成是一種安全且不需要輸入密碼的身份確認機制。
先來介紹如何透過 OpenSSL 產生可以用來驗證 Client 身份的憑證,首先我們先產生一組測試用的 CA 根憑證,如果用在開放的網絡環境中,實際上這個根憑證需要花錢購買,請有公信力的第三方單位來核發。
產生測試根憑證(Root CA)
Linux 的憑證習慣放在 /etc/pki 目錄中,建立 CA 根憑證的命令如下:
mkdir -p /etc/pki/CA
cd /etc/pki/CA
mkdir certs crl newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > crlnumber
openssl genrsa -out ./private/ca.key 4096
openssl req -new -x509 -days 365 -key ./private/ca.key -out ./certs/ca.crt
上述命令產生一組長度為 4096 的金鑰,基本上金鑰長度最少要 2048 以上才會比較安全,不容易被破解。執行過程如下:
產生SSL連線中繼憑證(Intermediate Certificate)
接著我們利用前面產生的測試根憑證,簽發一組金鑰長度為 2048 並且可以用來建立 SSL 連線的中繼憑證,命令如下:
openssl genrsa -out ./private/server.key 2048
openssl req -new -key ./private/server.key -out ./certs/server.csr
openssl x509 -req -days 365 -in ./certs/server.csr -CA ./certs/ca.crt -CAkey ./private/ca.key -set_serial 01 -out ./certs/server.crt
執行過程如下:
建立 Web Sever 需要的 PEM 檔(合併金鑰與證書)
由於最後要用在 HAProxy 的設定中,所以我們先產生 PEM 檔,如下:
cat ./certs/server.crt > ./certs/server.pem
cat ./private/server.key >> ./certs/server.pem
設定 HAProxy 強制檢驗 Client Certificate
接著我們來設定 HAProxy SSL 連線設定(HAProxy 安裝教學可以參考 富人用 L4 Switch,窮人用 Linux HAProxy 這一篇文章)。請注意,HAProxy 必須 1.5.x 之後的版本才有預設編譯 SSL Module,記得先確認版本有沒有支援 SSL。然後先編輯 /etc/haproxy/haproxy.cfg,範例如下:
global
log /dev/log local0
log /dev/log local1 notice
maxconn 1024
user haproxy
group haproxy
daemon
nbproc 1
pidfile /var/run/haproxy.pid
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
timeout server 120s
timeout connect 120s
timeout client 120s
retries 2
frontend ssl_switch
mode http
bind :443 ssl crt /etc/pki/CA/certs/server.pem ca-file /etc/pki/CA/certs/ca.crt verify required
default_backend service_cluster if { ssl_fc_has_crt }
backend service_cluster
mode http
server srv1 192.168.0.1:80 check
server srv2 192.168.0.2:80 check
haproxy.cfg 存檔後記得 restart haproxy 命令如下:
service haproxy restart
上述的設定我們限制 SSL 連線一定要使用 Server 所簽發的憑證,也就是「verify required」這一個設定,因此在沒有憑證的狀態下連線會出現以下錯誤畫面(Chrome 為例):
也可以直接透過 openssl 命令來測試 SSL 連線,輸入以下命令後,由於沒有提供 Client 憑證進行連線,所以會直接斷線。
openssl s_client -connect 127.0.0.1:443
接著我們介紹如何簽發 SSL Client 連線憑證。
簽發 Client SSL 連線用憑證
接著我們開始簽發 Client SSL 連線憑證,這張憑證可以讓使用者建立 SSL/TLS 連線,並且在 Server 上驗證憑證的合法性。命令步驟如下:
openssl genrsa -out ./private/client.key 2048
openssl req -new -key ./private/client.key -out ./certs/client.csr
openssl x509 -req -days 365 -in ./certs/client.csr -CA ./certs/ca.crt -CAkey ./private/ca.key -set_serial 02 -out ./certs/client.crt
上述的過程我們會產生一張可以用來建立 SSL 連線的憑證 client.crt 與密鑰 client.key,可以透過以下 openssl 命令測試 SSL 連線,執行命令如下:
openssl s_client -connect 127.0.0.1:443 -cert ./certs/client.crt -key ./private/client.key
當進行有憑證的連線時,就可以正確建立SSL通道,不像之前會直接斷線。
建立傳說中的.p12檔
由於一般的使用者都是透過瀏覽器進入網站或服務(應該沒有人用 openssl 或 open socket 這種低階方式),所以我們必須建立可以直接匯入瀏覽器的 PKCS12 格式檔案,就是傳說中的 p12 檔。一樣是透過 openssl 工具,產生的方式如下:
openssl pkcs12 -export -in ./certs/client.crt -out ./certs/client.p12 -name “Client Name” -inkey ./private/client.key
建立時會要求輸入檔案的密碼,避免檔案外流後的一道保障。
瀏覽器設定憑證進行連線
由於我們的 Server 目前已經設定為強制驗證 SSL Client Certificate,因此我們要將上述產生的 p12 檔匯入瀏覽器才能進行連線。以Chrome 為例,點選「設定」在下方展開「顯示進階設定…」,進入「管理憑證…」功能,如下:
點選「匯入」,選取我們剛剛產生好的 p12 檔,匯入時要輸入密碼。
然後 Chrome Refresh 就可以看到瀏覽器得到適合的憑證,並且出現確認畫面:
按下「確定」後就可以進入網站,如下:
出現上述的警告畫面是正常的,因為我們 Server 使用的憑證並非第三方公證單位所簽發,如果要簽發可以通過驗證的憑證,就需花費金錢購買(但預計 2015 年會有免費的 SSL 憑證可以使用)。關於其他的 Web Server,像 Apache, Nginx, Tomcat 等,它們的設定方法也都差不多,差別在有的 Web Server 設定 Key 與 Certificate 時,不需要合併為 PEM 檔。下期我們再分享更進階的憑證玩法,下次再見。