Nginx 版本高于等于 1.19.4,才可以使用 ssl_reject_handshake 特性来防止 SNI 信息泄露。如果 Nginx 版本太低,可以看看姥爷的这篇文章自编译 Nginx。
讲人话也就是,有些无良爬虫可通过HTTPS访问扫描全网IP,暴露证书、同时暴露你的域名。即使你套了CDN也逃不掉。
示范一下扫描IP命令:
curl -v -k https://35.186.1.1
curl -v -k https://35.186.1.1
* Rebuilt URL to: https://35.186.1.1/
* Trying 35.186.1.1...
* TCP_NODELAY set
* Connected to 35.186.1.1 (35.186.1.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=normal_domain.tld
* start date: Nov 15 05:41:39 2019 GMT
* expire date: Nov 14 05:41:39 2020 GMT
* issuer: CN=normal_domain.tld
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
> GET / HTTP/1.1
> Host: 35.186.1.1
> User-Agent: curl/7.58.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host 35.186.1.1 left intact
curl: (52) Empty reply from server
可以看见,证书和域名都暴露了。下面就来讲讲 ssl_reject_handshake 怎么用。只要新添加个443端口默认块就可以了。
#新添加的443端口块,如果使用了错误的 Hostname,SSL 握手会被拒绝
server {
listen 443 ssl default_server;
ssl_reject_handshake on;
}
#常规的443端口,包含正确的域名和证书。对于携带正确 Hostname 的请求,服务器会继续做后续处理
server {
listen 443 ssl;
server_name example.com;
ssl_certificate example.com.crt;
ssl_certificate_key example.com.key;
}
配置好重启nginx后,俺们再来测试一下:
curl -v -k https://35.186.1.1
* Rebuilt URL to: https://35.186.1.1/
* Trying 35.186.1.1...
* TCP_NODELAY set
* Connected to 35.186.1.1 (35.186.1.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, Server hello (2):
* error:14094458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name
* stopped the pause stream!
* Closing connection 0
curl: (35) error:14094458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name
可以看见已经扫描不出域名和证书了。试试使用错误的域名测试一下:
curl -v -k --resolve wrong_domain.tld:443:35.186.1.1 https://wrong_domain.tld
* Added wrong_domain.tld:443:35.186.1.1 to DNS cache
* Rebuilt URL to: https://wrong_domain.tld/
* Hostname wrong_domain.tld was found in DNS cache
* Trying 35.186.1.1...
* TCP_NODELAY set
* Connected to wrong_domain.tld (35.186.1.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, Server hello (2):
* error:14094458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name
* stopped the pause stream!
* Closing connection 0
curl: (35) error:14094458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name
域名错误也不会暴露证书和域名,需要正确的域名和正确的IP才会暴露域名和证书。