對于 NGINX 的 HTTPS 配置佣耐,通常情況下我們只需要實現(xiàn)服務(wù)端認(rèn)證就行鸦致,因為瀏覽器內(nèi)置了一些受信任的證書頒發(fā)機(jī)構(gòu)(CA)前普,服務(wù)器端只需要拿到這些機(jī)構(gòu)頒發(fā)的證書并配置好籍胯,瀏覽器會自己校驗證書的可用性并通過 SSL 進(jìn)行通訊加密谬运。
但特殊情況下我們也需要對客戶端進(jìn)行驗證,只有受信任的客戶端才能使用服務(wù)接口仇祭,此時我們就需要啟用雙向認(rèn)證來達(dá)到這個目的披蕉,只有 當(dāng)客戶端請求帶了可用的證書才能調(diào)通服務(wù)端接口 。
CA 與自簽名
CA 是權(quán)威機(jī)構(gòu)才能做的乌奇,并且如果該機(jī)構(gòu)達(dá)不到安全標(biāo)準(zhǔn)就會被瀏覽器廠商“封殺”没讲,前不久的沃通、StartSSL 就被 Mozilla礁苗、Chrome 封殺了爬凑。不過這并不影響我們進(jìn)行雙向認(rèn)證配置,因為我們是自建 CA 的..
為了方便试伙,我們就在 NGINX 的目錄下進(jìn)行證書相關(guān)制作:
cd /etc/nginx
mkdir ssl
cd ssl
制作 CA 私鑰
openssl genrsa -out ca.key 2048
制作 CA 根證書(公鑰)
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
注意:
Common Name 可以隨意填寫
其他需要填寫的信息為了避免有誤嘁信,都填寫 . 吧
服務(wù)器端證書
制作服務(wù)端私鑰
openssl genrsa -out server.pem 1024
openssl rsa -in server.pem -out server.key
生成簽發(fā)請求
openssl req -new -key server.pem -out server.csr
注意:
Common Name 得填寫為訪問服務(wù)時的域名,這里我們用 usb.dev 下面 NGINX 配置會用到
其他需要填寫的信息為了避免有誤疏叨,都填寫 . 吧(為了和 CA 根證書匹配)
用 CA 簽發(fā)
openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out server.crt
客戶端證書
和服務(wù)端證書類似:
注意:
Common Name可以隨意填寫
其他需要填寫的信息為了避免有誤潘靖,都填寫 . 吧(為了和 CA 根證書匹配)
至此需要的證書都弄好了,我們可以開始配置 NGINX 了蚤蔓。
NGINX
server {
listen 443 ssl;
server_name usb.dev;
access_log off;
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_client_certificate /etc/nginx/ssl/ca.crt;
ssl_verify_client on;
location / {
proxy_pass http://backend$request_uri;
}
}
其中 ssl_client_certificate /etc/nginx/ssl/ca.crt; 的意思是使用 CA 證書來驗證請求帶的客戶端證書是否是該 CA 簽發(fā)的卦溢。
配置好后就就重新加載 NGINX 吧:
service nginx reload
好了,下面我們可以開始驗證了。
請求驗證
驗證過程可以選擇在其他機(jī)器或是本機(jī)单寂,為了能夠解析 usb.dev贬芥,還需要配置一下 /etc/hosts:
127.0.0.1 usb.dev
如果用瀏覽器驗證,需要把客戶端證書導(dǎo)出成 p12 格式的宣决,這里略過誓军。我們重點(diǎn)是通過 curl 進(jìn)行驗證:
curl --insecure --key client.key --cert client.crt 'https://usb.dev'
其中 --insecure 是忽略自建 CA 的非權(quán)威性。如果你驗證正常那說明你運(yùn)氣好疲扎,因為這里有個 深坑:某些版本的 curl 會報錯:
<html>
<head><title>400 No required SSL certificate was sent</title> </head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.11.0</center>
</body>
</html>
這些報錯版本的 curl 居然要嚴(yán)格要求 --cert 實參的路徑要完全正確昵时,比如當(dāng)前目錄下面要用 --cert ./client.crt,用 --cert client.crt 是錯誤的椒丧。爬坑過程是啟用了 -v 參數(shù)來觀察完整的過程壹甥,發(fā)現(xiàn)其中有一條告警: