Nginx 中 ssl_reject_handshake 拒绝未识别的域名连接

作者:袖梨 2026-07-21
启用 ssl_reject_handshake on 可在 TLS 握手初始阶段拒绝未匹配合法域名的请求,不发证书、不建连接、不写日志;须置于 http 块顶层,仅对 listen 443 ssl 的 server 生效,需显式配置 server_name 且禁用通配符与 default_server。

启用 ssl_reject_handshake on 能在 TLS 握手最初阶段就拒绝未匹配合法域名的请求,不发证书、不建连接、不写访问日志,是阻断恶意 HTTPS 扫描和 SNI 探测最干净的方式。

必须放在 http 块顶层开启

这个指令只在 HTTP 模块生效,且必须全局启用:

  • nginx.confhttp { } 块最上方添加 ssl_reject_handshake on;
  • 不能写在某个 server 块里,也不支持 if 判断或条件开关
  • 仅对启用了 listen 443 ssl 的 server 生效,不影响 HTTP(80 端口)
  • 修改后执行 nginx -s reload 即可生效,无需重启进程

每个 HTTPS server 必须显式声明合法域名

启用后,Nginx 会严格比对客户端在 TLS 握手中发送的 SNI 字段:

  • ✅ 正确写法: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 请求
  • 配合防火墙或 Nginx 限速模块,对高频 TLS 握手失败的 IP 做速率限制

相关文章

精彩推荐