Nginx
帶有 ssl_verify_client = on 的 Nginx 不會使 TLS 握手失敗
我有ssl_verify_client = on的 Nginx 1.10 。一切正常,除了伺服器完成 TLS 握手並繼續解析標頭,即使客戶端尚未發送證書。
可以通過發送沒有客戶端證書的http請求和極大的http頭來驗證,nginx返回“ 400 Request Header Or Cookie Too Large ”。
根據我們的安全審計員的說法,伺服器應該無法通過 TLS 握手,因為解析標頭“增加了可能的攻擊面。
我的 nginx 配置:
server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name myserver.com; ssl_certificate /etc/letsencrypt/live/myserver.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/myserver.com/privkey.pem; ssl_verify_client on; ssl_client_certificate /etc/nginx/ssl/ca.pem; location / { proxy_pass http://127.0.0.1:8001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
我認為您需要要求使用 SNI 以避免標頭檢查。Nginx 必須確定伺服器塊是否與請求匹配,為此,它需要一個主機名。它可以在 TLS 握手期間從 SNI 獲取主機名,但如果不使用 SNI,則需要從 http 標頭中讀取主機資訊。
您可以通過為拒絕這些連接的非 SNI 客戶端請求設置預設伺服器塊處理程序來要求使用 SNI。為此,請
default_server
從主 ssl 伺服器塊中刪除該指令,並在其上方添加一個顯式預設伺服器,該伺服器 1) 偵聽 443,2) 匹配沒有主機名的請求,並且 3) 始終返回 444。範例:server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name ""; ssl_ciphers aNULL; ssl_certificate /path/to/dummy.crt; ssl_certificate_key /path/to/dummy.key; return 444; } server { listen 443 ssl; listen [::]:443 ssl; server_name myserver.com; ssl_certificate /etc/letsencrypt/live/myserver.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/myserver.com/privkey.pem; ssl_verify_client on; ssl_client_certificate /etc/nginx/ssl/ca.pem; location / { proxy_pass http://127.0.0.1:8001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
然後預設伺服器處理任何不使用 SNI 的 SSL 請求。444返回是關閉連接的nginx非標準程式碼。這種結構還關閉了一個潛在的安全漏洞,預設伺服器的證書可以以意想不到的方式暴露資源。現在 nginx 將只處理使用 SNI 並且主機名與您的其他伺服器塊之一匹配的請求。