导读:本期聚焦于椎名光创作的《Nginx如何使用ssl_reject_handshake拒绝无效SSL握手请求?》,敬请观看详情。服务器IP被扫描工具批量探测时,默认站点往往会暴露证书信息甚至返回有效响应,这会带来安全隐患。Nginx从1.19.4版本开始提供ssl_reject_handshake指令,可以直接在TLS握手阶段拒绝未匹配任何server_name的连接,攻击者拿不到证书也建立不了会话。本文介绍这个指令的配置方法、与默认站点返回444方案的区别、适用版本以及实战中的注意事项,帮助你彻底关闭IP直连和域名扫描的探测通道。

当有人直接用IP地址或者一个不属于你的域名访问你的服务器时,Nginx默认会把请求交给第一个匹配的server块处理,或者落入默认的默认站点。更麻烦的是,在HTTPS场景下,TLS握手阶段服务器就会把证书发出去,扫描工具通过证书里的域名信息就能确认这台服务器上跑了哪些站点。为了解决这个问题,Nginx 1.19.4引入了一个非常干脆的指令——ssl_reject_handshake,它可以在握手还没完成时直接掐断连接。

Nginx如何使用ssl_reject_handshake拒绝无效SSL握手请求?

ssl_reject_handshake 是什么,解决了什么问题

在介绍这个指令之前,先回顾一下传统的处理方式。早期很多运维同学的写法是配置一个默认server块,监听443端口,然后配合return 444。444是Nginx特有的状态码,含义是不返回任何响应直接关闭连接。这种方案在HTTP层是有效的,但问题在于它发生在TLS握手完成之后——也就是说,证书已经被发送给客户端了,SNI信息也已经暴露,隐藏站点信息的目的并没有真正达成。

ssl_reject_handshake的思路完全不同。它工作在TLS握手阶段,当客户端发起ClientHello之后,如果这个连接匹配到了配置了该指令的server块,Nginx会直接返回一个握手失败的告警信息,然后中断连接。整个过程证书不会发送,会话密钥也不会协商,客户端得到的信息基本为零。对于使用工具批量扫描IP段、枚举SNI来找隐藏服务的探测行为,这个指令能起到釜底抽薪的作用。

这个指令于2020年11月发布的Nginx 1.19.4中首次加入,随后也向后合入到了1.18.0的稳定分支更新中。使用前建议通过nginx -v确认版本,太老的版本写进去会直接报unknown directive错误导致配置加载失败。

完整配置示例

下面是一个典型的配置结构。核心思路是:写一个catch-all的默认server块,它不配置任何证书,只配置拒绝握手;真正的业务站点放在独立的server块中,通过server_name精确匹配。

# 默认server块:拒绝所有未匹配的SSL握手
server {
    listen 443 ssl default_server;
    ssl_reject_handshake on;
}

# 真正的业务站点
server {
    listen 443 ssl;
    server_name www.ipipp.com;

    ssl_certificate     /etc/nginx/ssl/ipipp.com.pem;
    ssl_certificate_key /etc/nginx/ssl/ipipp.com.key;

    location / {
        root /var/www/ipipp;
        index index.html;
    }
}

几个细节需要注意。第一,默认server块上虽然写了listen 443 ssl,但因为没有配置证书,Nginx允许这种写法的前提就是该块内启用了ssl_reject_handshake,二者搭配才不会在启动时报缺少证书的错误。第二,default_server参数确保所有SNI无法匹配的连接都落到这个块上,这个参数不能省。第三,如果你同时监听了IPv6,需要再加一行listen [::]:443 ssl default_server;,否则IPv6的探测请求依然会走到别的server块。

对于HTTP的80端口,如果也想做类似处理,可以保留传统方案,因为没有TLS握手这个环节,444依然是最佳选择:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;
}

与return 444方案的对比及验证方法

把两种方案放在一起对比会更清晰。return 444发生在HTTP请求处理阶段,此时TLS握手早已完成,证书已交付,只是不返回HTTP响应就断开;ssl_reject_handshake发生在TLS握手阶段,证书根本不出门。对于普通浏览器用户,两者表现都是连接被重置,看起来差不多;但对于OpenSSL、nmap这类工具,前者能完整拿到证书链,后者只能收到一个handshake failure告警,信息量差别巨大。

配置完成后,可以用命令行工具验证效果。用不存在的域名或者直接用IP去连:

# 指定一个不属于该服务器的SNI去测试
openssl s_client -connect 服务器IP:443 -servername fake.ipipp.com

# 期望输出中包含类似信息:
# SSL handshake has read 0 bytes and written ... bytes
# tlsv1 alert handshake failure

如果输出里出现了证书内容,说明请求没有落到拒绝握手的server块上,通常是default_server没加上,或者业务server块误占了默认位置(Nginx在找不到显式default_server时,会拿配置文件中字母序最前的server块当默认)。改完配置记得nginx -t检查语法,再nginx -s reload平滑加载。

最后提醒一点:如果你的服务器前面还有CDN或者负载均衡,客户端握手实际发生在CDN节点上,这个指令只能在源站直连场景下发挥作用。另外某些老旧监控探活工具使用的是不发送SNI的裸连接,它们同样会被拒绝,需要把探活目标改成正确的域名,避免误杀。整体来看,这是目前隐藏服务器证书信息、对抗SNI扫描最简洁有效的Nginx原生方案,配置成本几乎为零,值得在生产环境统一启用。

Nginxssl_reject_handshakeSSL握手修改时间:2026-09-08 05:04:24

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260908/52594.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。