阻止通过 HTTPS 直接访问网络服务器 IP

rug*_*ugk 10 nginx ip https web-server

thisthis question类似,我想阻止用户使用IP访问我的服务器。

对于 HTTP(端口 80),这可以正常工作,但不适用于 HTTPS。所以用户仍然可以进入https://<myip>访问webserver,nginx返回默认证书。顺便说一句,我在“常用”服务器块中使用 HTTP2(使用我的域名),所以我使用:

listen 443 ssl http2;
listen [::]:443 ssl http2;
Run Code Online (Sandbox Code Playgroud)

我现在尝试使用它来阻止 HTTPS ip 访问:

server {
   listen 443 ssl;
   listen [::]:443 ssl;

   server_name _;
   return 444;
}
Run Code Online (Sandbox Code Playgroud)

然而不幸的是,无论是否使用域,这都会阻止所有 HTTPS 请求。我知道可能有必要阻止非 SNI 客户端,因为这些客户端当然不会将使用的域名传送到服务器,所以我对此表示满意。(我的意思是不支持 SNI 的客户无论如何都是旧的......)

我通常更喜欢在 nginx 中阻止它,但是如果您对在防火墙级别 (iptables) 阻止它有一些想法,我也很高兴看到这些。如果你想争论为什么用 iptables 阻止更好你也可以这样做并说服我也阻止对 IP 的 HTTP [或所有其他] 请求。通常断开连接很好(就像 nginx 状态代码 444 那样)。

但是有一个要求:我不想在配置中明确提及服务器的 IP 地址,因为它是动态 IP 并且服务器使用动态 dns 服务。

简而言之,这就是我想要实现的目标:

  • 通过 IP 阻止访问
  • 允许通过域名访问
  • 可以阻止非 SNI 客户端
  • 可以为此使用防火墙阻止
  • 断开连接很好
  • 不提服务器的IP地址
  • 没有通过 HTTPS 暴露域名

编辑:另一个失败的尝试。我尝试遵循此建议并使用此配置片段,这在逻辑上似乎是一件好事:

if ($host != "example.com") {
        return 444;
}
Run Code Online (Sandbox Code Playgroud)

它也基本上有效,但是当我访问“https://”时,我看到 nginx 首先已经发送了 HTTPS 证书(包含域名),只有当我跳过连接警告时,我才看到它阻止了访问。这是合乎逻辑的,因为 nginx 只能在 HTTPS 连接存在时读取 Host 标头,但此时 nginx 已经发送了包含域名的服务器证书,因此用户现在拥有域名并可以使用它重新连接,从而生成整个 IP堵没用。我也有点担心这个解决方案的性能方面,因为它会导致 nginx 检查每个请求的主机头,所以我仍然在这里寻找解决方案。

小智 8

今天,我遇到了与此块相同的问题:

server {
  listen 443 ssl default_server;
  server_name <SERVER-IP>;
  return 444;
}
Run Code Online (Sandbox Code Playgroud)

nginx-logs 说:

在 SSL 握手时侦听 SSL 端口的服务器中未定义“ssl_certificate”

正如您所提到的,这似乎也禁用了其他服务器块。可以通过为 server-ip-address 使用(自签名)证书来解决此问题。我使用openssl做到了这一点:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt -subj '/CN=<SERVER-IP>'
Run Code Online (Sandbox Code Playgroud)

然后将服务器块更改为:

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;
}
Run Code Online (Sandbox Code Playgroud)

当有人通过 https 使用 SERVER-IP 访问服务器时,nginx 会提供(自签名)证书,而不是您想要隐藏的域名证书。

顺便说一下,让你的 server-block-with-IP 成为 default_server。这样,禁用了 SNI 的客户端将获得 IP 证书而不是域名证书。这也可以使用 openssl 进行测试(省略了将启用 SNI 的 -servername 选项):

openssl s_client -connect <SERVER-IP>:443
Run Code Online (Sandbox Code Playgroud)


Tim*_*Tim 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 推荐使用 default_server,因为它告诉 nginx 做什么,而不是依赖 nginx 默认值,后者将来可能会改变。 (2认同)