最干净的恶意探测阻断方式是在tls握手初期拒绝未匹配域名请求,需在http块顶层启用ssl_reject_handshake on,仅对显式列出合法域名的https server生效,并配合sni验证与基础加固措施。

直接在 TLS 握手初期就拒绝未匹配域名的请求,是阻断恶意探测最干净的方式——不发证书、不建连接、不进 HTTP 流程。核心就是用好 ssl_reject_handshake on,但它不是加了就行,关键在位置、配合和验证。
必须放在 http 块顶层启用
该指令只在 HTTP 模块生效,且不能写在 server 块里,也不支持 if 判断或条件启用。正确做法是在 nginx.conf 的 http { } 块最上方添加:
ssl_reject_handshake on;- 它仅对启用了
listen 443 ssl的 server 生效,不影响普通 HTTP 请求 - 配置后执行
nginx -s reload即可生效,无需重启进程
每个 HTTPS server 必须显式列出合法域名
启用后,Nginx 会严格比对客户端在 TLS 握手中声明的 SNI。只有被 server_name 明确列出的域名才允许继续握手:
- ✅ 正确写法:
server_name example.com www.example.com api.example.com; - ❌ 禁止通配符:
server_name *.example.com;—— 所有子域都会通过,等于放弃防护 - ❌ 不要保留带证书的
default_server—— 它会接管未匹配请求并返回证书,彻底抵消拦截效果
验证是否真正生效
别只看配置文件是否存在,要用真实工具观察 TLS 层行为:
- 用 OpenSSL 模拟非法 SNI:
openssl s_client -connect 1.2.3.4:443 -servername fake.test.com -tls1_2成功拦截时,输出中会出现SSL routines::UNRECOGNIZED_NAME,且没有Certificate:段 - 用 curl 测试 IP 直连:
curl -vI https://1.2.3.4应卡在 TLS 握手阶段失败,看不到Server Hello,浏览器报ERR_SSL_UNRECOGNIZED_NAME_ALERT - 再用合法域名测试:
openssl s_client -connect 1.2.3.4:443 -servername example.com应正常完成握手并显示证书信息,确认业务不受影响
搭配基础加固避免绕过
单靠 ssl_reject_handshake 不足以覆盖全部风险,建议同步做几项轻量但关键的加固:
- 对 HTTP 默认站点也做拦截:
server { listen 80 default_server; return 444; },防止 80 端口暴露服务指纹 - 在 HTTPS server 块中强制现代协议:
ssl_protocols TLSv1.2 TLSv1.3;,禁用弱加密套件 - 在日志格式中加入
$ssl_server_name,便于识别高频空值或异常 SNI 请求











