由于不正确vhost的配置,443端口泄露的证书可被某些无良的爬虫或网站(censys.io
)收集,用以将IP和SSL证书匹配,当源站IP泄露在公网是很危险的。这时不论是使用了CDN还是负载均衡都有可能被成本低廉的TCP/UDP放大攻击打到关机、黑洞。本篇文章就主要介绍使用Nginx(1.19+)ssl_reject_handshake
模块和给443端口配置一个错误的证书来避免这种情况的发生。
1.给443端口配置一个错误的自签证书
谷歌关键字自签名证书 生成
将证书放在服务器指定目录,新建一个服务器IP的vhost在ip.conf中引入证书即可,但这种方式既不优雅也在批量配置时费时费力。
2.使用
ssl_reject_handshake
参数on|off 默认为off
通过名字就可知道该模块大概作用,没错,它的作用就是控制ssl握手,当传入sni不匹配时,nginx会直接返回400错误拒绝连接,只有当证书和sni匹配时,nginx才会允许连接,放行访问。如何使用?
在默认default.conf(如没有则新建)新增
server {
listen 443 ssl default_server;
#如果有IPv6地址需加入下面这行,否则不用下面这行
listen [::]:443 ssl default_server;
ssl_reject_handshake on;
}
我们来看下效果直接浏览器访问IP:443返回错误ERR_SSL_UNRECOGNIZED_NAME_ALERT,curl -v -k IP:443
可以看到Nginx拒绝了不争取的ssl握手,配置成功。
还没有结束!
对于阻止爬虫来说这样配置足够,但众所周知IPv4的IP池是有限的,攻击者如果携带sni指定hosts来扫描全网IP的话也不需要耗费太长时间,nginx这时就无法为我们提供防御,且访问方式与正常访问一样无法分辨,比如使用
#ip为你的源站IP
curl -k https://anisland.net --resolve '*:443:ip'
nginx就会给出正确的响应,攻击者拿到源站IP我们依旧会面临Ddos攻击。解决方法:以debian为例目前我能想到的方式就是使用ufw防火墙对443防火墙做CDN IP白名单限制,CDN IP可向你的CDN提供商来索取。
注意事项
-
nginx无法启用tls1.3的握手失败解决办法,openssl 1.1.1h bug,详细见传送门。
- 升级至openssl ≥ 1.1.1j 修复此问题