利用 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 檔。下期我們再分享更進階的憑證玩法,下次再見。
HAProxy 輕鬆整合 SSL/TLS Client Certificate
https://www.facebook.com/hkitblog