核心原理

Nginx 的配置是基于 server 块的,一个 Nginx 配置文件中可以包含多个 server 块,每个 server 块通过 server_name 指令来匹配不同的域名或 IP。

nginx 禁止ip访问网站
(图片来源网络,侵删)

要禁止 IP 访问,我们只需要创建一个专门用于“捕获”所有 IP 访问请求的 server 块,并将其放在配置文件的最前面,因为 Nginx 在匹配 server 块时,会按照配置文件中的顺序进行,第一个匹配到的 server 块将被使用。


直接返回错误页面(推荐)

这是最常用、最推荐的方法,我们创建一个 server 块,它的 server_name 是服务器的 IP 地址,然后直接返回一个 444 状态码或者一个自定义的 403 Forbidden 页面。

444 是 Nginx 专用的一个状态码,它表示“Connection Closed Without Response”,客户端会收到一个空的响应,然后连接被直接关闭,这种方式最节省服务器资源,对攻击者来说最不友好。

步骤:

  1. 找到你的 Nginx 配置文件 通常是 /etc/nginx/nginx.conf 或者位于 /etc/nginx/sites-available/ 目录下的配置文件(default)。

    nginx 禁止ip访问网站
    (图片来源网络,侵删)
  2. http 块内,最前面添加以下配置

    # 在 http { ... } 块的开头添加
    server {
        # 将这里的 IP 地址替换成你的服务器公网或私网 IP
        listen 80 default_server;
        listen [::]:80 default_server;
        # 如果你的网站开启了 HTTPS,也必须添加一个对应的 HTTPS server 块
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        # 注意:HTTPS 需要指定证书和密钥路径,否则会启动失败
        # ssl_certificate /path/to/your/certificate.crt;
        # ssl_certificate_key /path/to/your/private.key;
        # 直接关闭连接,最节省资源
        return 444;
        # 或者,返回一个 403 Forbidden 错误页面
        # return 403;
    }

    配置解释:

    • listen 80 default_server;:这个指令是关键。default_server 表示这个 server 块是监听 80 端口的默认服务器,当请求的 Host 头部不匹配任何其他 server 块的 server_name 时,这个默认服务器就会处理这个请求。
    • listen [::]:80 default_server;:这是 IPv6 的等效配置,建议同时启用。
    • return 444;:直接关闭连接,不给任何响应。
    • return 403;:返回一个“禁止访问”的 HTTP 状态码,客户端会看到错误页面。
  3. 保存文件并测试配置

    # 检查 Nginx 配置语法是否正确
    sudo nginx -t
    # 如果显示 syntax is ok 和 test is successful,则重载 Nginx 配置
    sudo systemctl reload nginx

完成以上步骤后,当用户直接通过 IP 地址访问你的服务器时,请求就会被这个 server 块捕获,并直接关闭连接或返回 403 错误,而不会到达你的网站。

nginx 禁止ip访问网站
(图片来源网络,侵删)

将 IP 访问重定向到主域名

如果你希望用户通过 IP 访问时,能自动跳转到你的主域名,可以使用 return 301 (永久重定向) 或 return 302 (临时重定向)。

配置示例:

# 在 http { ... } 块内,最前面添加
server {
    # 将 IP 替换成你的服务器 IP
    listen 80 default_server;
    listen [::]:80 default_server;
    # 将 yourdomain.com 替换成你的主域名
    return 301 http://yourdomain.com$request_uri;
}

适用场景:

  • 你希望给用户一个友好的跳转,告诉他们正确的访问地址。
  • 确保所有流量都集中到你的主域名上,对 SEO 更友好。

使用 if 指令(不推荐)

虽然也可以使用 if 指令来实现,但 Nginx 官方文档和社区都强烈不推荐server 块级别使用 if 指令,因为它会导致不可预测的行为和性能问题,这种方法仅作了解。

配置示例(不推荐):

server {
    listen 80;
    listen [::]:80;
    # 检查请求的 Host 头部是否不包含你的域名
    if ($host != "yourdomain.com") {
        return 444;
    }
    # 你的网站正常配置
    root /var/www/html;
    index index.html;
}

为什么不推荐?

  • 性能问题if 指令会增加 Nginx 的处理开销。
  • 陷阱和不可预测性if 的行为在不同版本的 Nginx 和不同的配置场景下可能不一致,容易引入难以发现的 bug。

请优先选择方法一


总结与建议

方法 优点 缺点 推荐度
直接返回 444 或 403 性能最佳,安全性最高,配置简单 对用户不友好(直接断开或显示错误) ⭐⭐⭐⭐⭐ (强烈推荐)
重定向到域名 用户体验好,利于 SEO 多一次网络跳转,消耗少量资源 ⭐⭐⭐⭐ (适用于有 SEO 需求的场景)
使用 if 指令 看起来直观 性能差,容易出错,不推荐 ⭐ (仅作了解,避免使用)

最佳实践:

  1. 首选方法一:在你的 Nginx 主配置文件中,为你的服务器 IP 地址添加一个 default_server 块,并使用 return 444;,这是最干净、最安全的做法。
  2. 务必包含 IPv6:同时配置 listen [::]:80 default_server;listen [::]:443 ssl default_server; 以确保 IPv6 用户也无法直接通过 IP 访问。
  3. 为 HTTPS 准备:如果网站支持 HTTPS,请在禁止 IP 的 server 块中也添加 listen 443 配置,即使你没有为 IP 配置 SSL 证书,加上 listen 443 default_server; 也能阻止通过 IP 的 HTTPS 访问(客户端会收到证书错误,但无法访问你的网站内容)。

通过以上配置,你的网站将只能通过你设定的域名进行访问,有效提升了安全性和规范性。