# 緣由
有一網站需要限制只有特定人員才可瀏覽,通常會使用來源 IP 進行限制,若是無固定辦公室人員(業務)則使用 VPN 連入公司網路獲得允許 IP。
但因為公司沒有自己的網路,所以沒辦法使用這個方法,因此採用 mTLS。
一般網站憑證只是單向用於驗證網站是否合法,mTLS 則是雙向驗證 雙向奔赴的憑證,除了驗證網站是否合法外,也驗證連接端 (client, browser) 是否合法。
官方文件其實有教學 (Set up mutual TLS with user-provided certificates),但是官方文件都是透過 gcloud 設定,所以這篇紀錄一下怎麼使用 GUI 方式設定。
思路:從 load balance 下手,在 load balance 進行驗證,client 合法才導入後端。
# 需求
先安裝 openssl 用於產生憑證
# 產生根憑證
# 憑證設定檔
建立憑證設定檔 example.cnf
[req] | |
distinguished_name = empty_distinguished_name | |
[empty_distinguished_name] | |
# Kept empty to allow setting via -subj command line arg. | |
[ca_exts] | |
basicConstraints=critical,CA:TRUE | |
keyUsage=keyCertSign | |
extendedKeyUsage=clientAuth |
# 根憑證與密鑰
使用 openssl 產生根憑證密鑰 root.key
與根憑證 root.cert
openssl req -x509 \ | |
-new -sha256 -newkey rsa:2048 -nodes \ | |
-days 3650 -subj '/CN=root' \ | |
-config example.cnf \ | |
-extensions ca_exts \ | |
-keyout root.key -out root.cert |
# 產生中繼憑證
# 中繼憑證簽名請求
產生中繼憑證密鑰 int.key
跟中繼憑證簽名請求 int.req
openssl req \ | |
-new -sha256 -newkey rsa:2048 -nodes \ | |
-subj '/CN=int' \ | |
-config example.cnf \ | |
-extensions ca_exts \ | |
-keyout int.key -out int.req |
# 中繼憑證
產生中繼憑證 int.cert
openssl x509 -req \ | |
-CAkey root.key -CA root.cert \ | |
-set_serial 1 \ | |
-days 3650 \ | |
-extfile example.cnf \ | |
-extensions ca_exts \ | |
-in int.req -out int.cert |
# 建立信任設定
從 https://console.cloud.google.com/security/ccm/list/trustConfigs 建立信任設定
把前面步驟產生的 root.cert
內容增加到信任錨點、 int.cert
內容增加到中繼 CA。
# 建立用戶端驗證
從 https://console.cloud.google.com/net-security/clientauth/serverTlsPolicies 建立用戶端驗證
用戶端驗證模式選擇 負載平衡
以及 拒絕無效的用戶憑證
,信任設定選取前一步驟建立的設定檔。
# 負載平衡設定
https://console.cloud.google.com/net-services/loadbalancing/list/loadBalancers
在負載平衡的前端設定處,選取剛建立的用戶端驗證,可能不會馬上生效,如果生效後開啟網址會是 ERR_CONNECTION_CLOSED
的訊息。
# 建立用戶端憑證
# 用戶端設定檔
建立用戶端設定檔 client.config
[req] | |
default_bits = 2048 | |
req_extensions = extension_requirements | |
distinguished_name = dn_requirements | |
prompt = no | |
[extension_requirements] | |
basicConstraints = critical, CA:FALSE | |
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment | |
extendedKeyUsage = clientAuth | |
[dn_requirements] | |
countryName = US | |
stateOrProvinceName = California | |
localityName = San Francisco | |
0.organizationName = example | |
organizationalUnitName = test | |
commonName = test.example.com | |
emailAddress = test@example.com |
# 產生用戶密鑰與簽名請求
會產生 client.key
, client.csr
。這邊會詢問金鑰密碼,後面匯出時會用到。
openssl req -new -keyout client.key -out client.csr -config client.config |
# 產生用戶端憑證
使用 int.cert
、 int.key
、 client.csr
產生用戶端憑證 client.cert
openssl x509 -req -in client.csr -out client.cert -extfile client.config -extensions extension_requirements -days 365 -CA int.cert -CAkey int.key |
測試
curl -v -k --key client.key --cert client.cert https://網址 |
# 瀏覽器匯入憑證
server 端大致上設置完成,還需設定 client 端,client 匯入憑證這邊使用 PKCS #12
格式。
首先將 client.key
、 client.cert
封裝。會產生 client.p12
。
這邊會詢問剛剛產生 client.key
時的金鑰密碼,驗證後會再詢問金鑰匯出密碼,在匯入時會需要 (可不設置)。
openssl pkcs12 -export -inkey client.key -in client.cert -out client.p12 -name "client-cert" |
# 憑證匯入
在 Windows、Linux 桌面環境大致上都直接點兩下 client.p12
後輸入匯出密碼即可。之後可開啟瀏覽器查看網站是否可正常瀏覽。
macOS 可能會出現一直詢問密碼 (匯出密碼錯誤) 的情況,強者我同事說是因為 openssh
版本差異關係,使用舊版的 openssh
重新匯出 p12 憑證即可。
macOS 還需要從 鑰匙圈
設定憑證的存取權限為一律允許,否則在瀏覽網站的時候,會一直出現詢問密碼請求允許的情況。