我有Nginx 1.10与ssl_verify_client = on 。 一切工作正常,除了服务器完成TLS握手,并继续parsing头,即使证书还没有被客户端发送。
可以通过发送没有客户端证书和非常大的http头的http请求来validation,nginx返回“ 400请求头或Cookie太大 ”。
据我们的安全审计员,服务器应该失败的TLS握手,因为parsing头“增加了可能的攻击面。
我的nginxconfiguration:
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。 要做到这一点,从主ssl服务器块中删除default_server指令,并添加一个明确的默认服务器上面,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返回是一个closures连接的nginx非标准代码。 这种结构还closures了一个潜在的安全漏洞,在这个漏洞中,默认服务器的证书可以以不可预料的方式暴露资源。 现在,nginx将只处理使用SNI并且主机名与其他服务器块匹配的请求。