Site icon Soul & Shell Blog

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 檔。下期我們再分享更進階的憑證玩法,下次再見...

Exit mobile version