Nginx通过在HTTPS server块中配置ssl_reject_handshake on并显式声明server_name、禁用default_server,实现TLS握手阶段无证书拒绝IP直连;需配合协议加固、SNI日志及网络层限速封禁。

直接在 TLS 握手阶段切断连接,不发证书、不走 HTTP 流程,是拦截 IP 地址直连探测最干净的方式。关键不是“怎么加那行配置”,而是加在哪、配合什么、以及为什么这样才真正生效。
必须放在 HTTPS server 块里,且不能依赖 default_server
很多人误以为把 ssl_reject_handshake on; 放在全局 http 块就万事大吉——其实它只对启用了 SSL 的 server 块起作用,而且必须和明确的 server_name 配合使用:
- 每个生产用的 HTTPS
server块都要显式列出合法域名,比如server_name example.com api.example.com; - 不要留空
server_name,也不要只写通配符如*.example.com(这会让所有子域都通过,削弱防护) - 彻底删除或注释掉原来用于兜底的
default_server配置,比如listen 443 ssl default_server;—— 它的存在会让 Nginx 继续返回证书
IP 直连场景下,要靠“无匹配即拒绝”机制
当扫描器直接用 https://1.2.3.4 访问时,SNI 字段为空或为 IP 地址本身,Nginx 找不到任何 server_name 匹配项,此时 ssl_reject_handshake on 才会触发内核级拒绝:
- 客户端收到的是 TLS Alert:
unrecognized_name,连接在握手第 2 步(ServerHello 后)就终止 - 服务器日志里通常不会记录这次请求(部分版本可能有
SSL_do_handshake() failed提示) - 用
openssl s_client -connect 1.2.3.4:443 -servername 1.2.3.4可快速验证是否生效
搭配 SNI 白名单和协议加固,避免旁路绕过
单靠 ssl_reject_handshake 不够,攻击者可能尝试旧协议或模糊 SNI。需同步收紧:
- 在 HTTPS
server块中强制启用现代协议:ssl_protocols TLSv1.2 TLSv1.3; - 禁用弱加密套件,例如去掉
RC4、DES、MD5相关 cipher - 用
log_format记录$ssl_server_name,方便后续分析异常 SNI 请求(虽然被拒的请求不一定能记全,但高频空值或 IP 值就是线索)
别忘了网络层协同,封堵已知扫描源
即便握手被拒,高频探测仍会消耗系统资源。建议在 UFW 或云防火墙层面补充限速和封禁:
- 封禁 Censys、Shodan、ZoomEye 等主流测绘平台的公开 IP 段(如
162.142.125.0/24、167.94.138.0/24) - 对单 IP 在 60 秒内超过 5 次 TLS 握手失败的,自动加入临时黑名单(可用 fail2ban + nginx 日志实现)
- IPv6 地址段同样需要覆盖,例如
2602:80d:1000:b0cc:e::/80


















