最底层安全防护是启用 ssl_reject_handshake on,需在 http 块顶部全局配置、严格声明 server_name 域名、配合 openssl 验证及 http 拦截等加固措施。

直接在 TLS 握手初始阶段拒绝非法请求,是提升 Nginx 服务器安全最底层、最干净的方式——不发证书、不建连接、不进日志、不留指纹。核心就是正确启用 ssl_reject_handshake on,但它真正起效,依赖三件事:配置位置对、域名声明严、配套措施跟得上。
必须全局开启且位置唯一
这个指令只能写在 http { } 块的最顶部,不能放在某个 server 块里,也不支持 if 条件或 stream 上下文。它只对启用了 listen 443 ssl 的 HTTPS server 生效:
- 在
nginx.conf的http块开头添加:ssl_reject_handshake on; - 修改后执行
nginx -s reload即可生效,无需重启进程 - 它对 HTTP(80 端口)完全无影响,只作用于 TLS 握手环节
每个 HTTPS server 必须显式列出合法域名
启用后,Nginx 会严格比对客户端发送的 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 握手阶段失败,浏览器报ERR_SSL_UNRECOGNIZED_NAME_ALERT - 再用合法域名测试,确认业务不受影响
搭配基础加固避免绕过
单靠 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 做速率限制











