对于 HTTP(端口 80),这很好用,但对于 HTTPS 则不行。因此用户仍然可以进入https://<myip>
以访问 Web 服务器,并且 nginx 返回默认证书。顺便说一句,我在“常用”服务器块(使用我的域名)中使用 HTTP2,因此我使用:
listen 443 ssl http2;
listen [::]:443 ssl http2;
我现在尝试用这个来阻止 HTTPS IP 访问:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
return 444;
}
但不幸的是,无论是否使用该域名,这都会阻止所有 HTTPS 请求。我知道可能需要阻止非 SNI 客户端,因为这些客户端当然不会将使用的域名传送到服务器,所以我对此没有意见。(我的意思是,不支持 SNI 的客户端本来就很旧了……)
我通常更喜欢在 nginx 中阻止这种情况,但如果您对在防火墙级别(iptables)阻止这种情况有一些想法,我也很乐意听取这些建议。如果您想争论为什么使用 iptables 进行阻止更好,您也可以这样做并说服我也阻止对 IP 的 HTTP [或所有其他] 请求。通常,断开连接是可以的(就像 nginx 状态代码 444 一样)。
但是有一个要求:我不想在配置中明确提及服务器的 IP 地址,因为它是一个动态 IP,并且服务器使用动态 DNS 服务。
简而言之,这就是我想要实现的目标:
- 阻止通过 IP 访问
- 允许通过域名访问
- 可以阻止非 SNI 客户端
- 可以使用防火墙阻止此操作
- 断开连接是可以的
- 不提及服务器的 IP 地址
- 不会通过 HTTPS 暴露域名
编辑:又一次失败了。我试图跟随这个建议并使用这个配置片段,从逻辑上讲这似乎是一件好事:
if ($host != "example.com") {
return 444;
}
它基本上也可以工作,但是当我访问“https://”时,我发现 nginx 首先已经发送了 HTTPS 证书(包含域名),只有当我跳过连接警告时,我才会看到它阻止访问。这是合乎逻辑的,因为 nginx 只有在 HTTPS 连接存在时才能读取主机头,但此时 nginx 已经发送了包含域名的服务器证书,因此用户现在拥有域名并可以使用它重新连接,使整个 IP 阻止变得毫无用处。我也有点担心这个解决方案的性能方面,因为它会导致 nginx 检查每个请求的主机头,所以我仍然在这里寻找解决方案。
答案1
今天,我遇到了与此块相同的问题:
server {
listen 443 ssl default_server;
server_name <SERVER-IP>;
return 444;
}
nginx-logs 说:
SSL 握手期间监听 SSL 端口的服务器中未定义“ssl_certificate”
正如您所提到的,这似乎也会禁用其他服务器块。可以通过对服务器 IP 地址使用(自签名)证书来解决这个问题。我使用 openssl 做到了这一点:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt -subj '/CN=<SERVER-IP>'
然后将服务器块更改为:
server {
listen 443 ssl default_server;
server_name <server-ip>;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/privateKey.key;
return 444;
}
当有人使用 SERVER-IP 通过 https 访问服务器时,nginx 会提供(自签名)证书,而不是您想要隐藏的域名证书。
顺便说一句,将 server-block-with-IP 设为 default_server。这样,禁用 SNI 的客户端将获得 IP 证书,而不是域名证书。这也可以使用 openssl 进行测试(省略了启用 SNI 的 -servername 选项):
openssl s_client -connect <SERVER-IP>:443
答案2
试试这个 - default_server 位是重要的部分。如果它不起作用,请更新您的问题,显示在 443/SSL 上监听的其他服务器的配置。
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server; # not sure if you want/need it here as well. Try both ways.
server_name _;
return 444;
}
答案3
当有人尝试使用 IP:80 和 IP:443 时,您可以拒绝未知域的连接。
HTTP(80) 的响应:连接已关闭且无响应。HTTPS(443) 的响应:拒绝 SSL 连接。
将此配置包含到 /etc/nginx/nginx.conf:
# /etc/nginx/sites-enabled/default_server.conf
# HTTP:80 = catch-all server block, resulting in a 444 response for unknown domains.
# HTTPS:443 = catch-all server block, resulting in reject SSL connection for unknown domains.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name "_";
return 444; # Connection closed without response
}
server {
listen 443 default_server;
listen [::]:443 default_server;
server_name "_";
ssl_reject_handshake on; # Reject SSL connection
}