Nginx监听公网IP相关的安全与配置疑问
嘿,先结合你的场景捋清楚问题根源:你的Nginx配置直接监听了公网IP的443端口,而且没有设置默认处理未匹配域名请求的server块,所以当有人把恶意域名解析到你的公网IP时,Nginx找不到匹配的server_name,就会把第一个符合监听端口的server块(也就是你的example.com站点)返回给请求方,这就是为什么恶意域名能访问到你的网站。
下面逐个解答你的疑问:
1. 监听公网IP是不好的实践吗?有潜在威胁吗?
监听公网IP本身不算坏实践——如果你的服务器只有一个公网IP,或者你明确只想让这个IP提供服务,这么配置是合理的。但问题出在没有处理未匹配域名的请求,这会带来几个潜在威胁:
- 钓鱼风险:恶意域名指向你的IP后,用户如果忽略浏览器的证书警告(因为证书只绑定了你的合法域名),可能会误以为这个恶意域名就是你的官方站点,存在被钓鱼的风险。
- 资源消耗:大量恶意请求会占用你的服务器带宽和资源,影响正常用户的访问体验。
- 内容滥用:如果你的网站有原创内容,恶意域名可能会直接盗用你的内容,甚至用于违规用途,给你带来不必要的麻烦。
2. 不监听公网IP,只监听端口和server_name有什么注意事项?
改成listen 443 ssl;(不指定IP)的话,Nginx会默认监听服务器上所有可用IP地址的443端口(包括公网IP、内网IP)。这么做的注意点有这些:
- 端口冲突风险:如果你的服务器上还有其他服务需要在某个特定IP的443端口运行,这种全局监听的方式会导致端口冲突,服务无法启动。
- 不必要的暴露:如果服务器有多个IP(比如内网IP),你可能不想让内网IP对外提供服务,但全局监听会让这些IP也响应外部请求,增加了潜在的攻击面。
- 核心问题仍存在:不管你是指定公网IP还是全局监听端口,如果没有配置默认server块处理未匹配域名,恶意域名解析到你的IP后,仍然会返回你的网站内容——这才是核心问题,和是否指定公网IP无关。
3. 创建server_name _;的server块并重定向到主域名是否更好?
首先要纠正一个小误区:server_name _;是Nginx用来标识默认server块的(当请求的域名不匹配任何已配置的server_name时,会用这个块处理),但它生效的前提是——这个server块必须是第一个匹配监听端口的块,否则Nginx还是会把第一个出现的server块作为默认。
至于重定向到主域名,其实不是最优选择:虽然能让用户跳转到你的合法站点,但恶意域名仍然可以利用你的IP引流,甚至可能被搜索引擎收录,反而影响你的SEO。更推荐的做法是直接拒绝这类请求:
- 返回
444状态码:这是Nginx的特殊状态码,会直接关闭连接,不返回任何内容,恶意请求拿不到你的网站数据。 - 返回
403 Forbidden:如果需要明确告知请求方访问被禁止,可以用这个状态码。
给你一个参考配置:
# 放在所有server块最前面,作为默认处理 server { listen 185.xxx.xxx.xxx:443 ssl; server_name _; # 如果用SSL,这里需要配置证书(可以用自签证书,或者复用主域名的证书,不过用户会看到证书错误) ssl_certificate /path/to/your/cert.pem; ssl_certificate_key /path/to/your/key.pem; return 444; # 直接关闭连接 } # 你的主站点配置 server { server_name example.com www.example.com; listen 185.xxx.xxx.xxx:443 ssl; ssl_certificate /path/to/your/cert.pem; ssl_certificate_key /path/to/your/key.pem; # 其他站点配置... }
如果不想指定公网IP,把两个server块的listen改成listen 443 ssl;即可,同样要保证默认块在最前面。
备注:内容来源于stack exchange,提问作者Andrey Ao

