使用 Nginx 配置域名及禁止直接通过 IP 访问网站

最近我搭建了一个个人网站,发现一个问题:网站可以通过 IP 地址直接访问。为了解决这个问题,我深入研究了 Nginx 的配置方法,以确保网站只能通过域名访问,同时防止恶意用户通过其他域名指向我的服务器 IP 来蹭流量。以下是详细的配置步骤和解决方案。

1. Nginx 配置域名及禁止直接通过 IP 访问

Nginx 的默认配置文件通常位于 /etc/nginx/sites-enabled 目录下(以 Ubuntu 系统为例)。需要注意的是,sites-enabled 目录中的文件通常是软链接,指向 sites-available 目录下的实际配置文件。这是 Nginx 的最佳实践,建议在 sites-available 中修改配置,完成后创建软链接到 sites-enabled。不过,为了简化操作,我直接在 sites-enabled 目录下创建和修改配置文件。

以下是 Nginx 的默认配置文件示例:

# default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;
}

最简单的配置方式是直接修改这个 default 文件,添加自己的网站配置,例如:

# default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name www.example.com;

    root /path/to/www.example.com;

    index index.html index.htm;
}

问题:这种方式不推荐。因为恶意用户可能通过其他域名指向你的服务器 IP,蹭你的流量,甚至养他们的域名。

推荐做法:复制默认配置文件,创建专属的网站配置文件。例如:

cp /etc/nginx/sites-enabled/default /etc/nginx/sites-enabled/example-website

然后修改新文件 example-website

# example-website
server {
    listen 80;
    listen [::]:80;

    server_name www.example.com;

    root /path/to/www.example.com;

    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
}

说明

  • 去掉 default_server,避免该配置成为默认服务器。
  • server_name 设置为自己的域名。
  • root 指向网站文件根目录。
  • 支持 PHP 文件处理,适用于动态网站(使用 PHP 8.1)。

禁止 IP 访问

为了禁止通过 IP 直接访问网站,可以修改默认配置文件 default。以下是一个常见的配置方法,以及对提供的代码片段的分析和改进:

提供的代码片段

# default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    # 对直接 IP 访问返回 444 错误
    if ($host ~* "^[0-9.]+$|^[0-9a-f:]+$") {
        return 444;
    }
}

代码分析

  • 监听端口listen 80 default_serverlisten [::]:80 default_server 分别监听 IPv4 和 IPv6 的 80 端口,并设置为默认服务器,处理所有未匹配到其他 server 块的请求。
  • server_name _:表示匹配任何未明确配置的域名或 IP 访问。
  • if 条件if ($host ~* "^[0-9.]+$|^[0-9a-f:]+$") 使用正则表达式检查 $host 变量,匹配 IPv4(如 192.168.1.1)和 IPv6(如 2001:db8::1)地址。
  • return 444:返回 Nginx 特有的 444 状态码,直接关闭连接,不返回任何响应内容。这比返回 500 更高效,因为 500 会生成错误页面,而 444 完全拒绝连接。
  • 问题:注释错误地提到“返回 500 错误”,与实际的 return 444 不一致,可能会误导读者。HTTP 500 表示“服务器内部错误”,不适合用于阻止 IP 访问,而 444 是更合适的选择。
  • 改进建议:由于 server_name _ 已确保只匹配未配置的请求(包括 IP 访问和未配置的域名),可以省略 if 条件,直接使用 return 444,以提高性能:

改进后的配置

# default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    return 444;
}

说明

  • return 444 能阻止所有未匹配的请求(包括 IP 访问和恶意域名指向),适用于所有未配置的情况。
  • 相比 return 500(服务器内部错误),return 444 更适合,因为它直接关闭连接,不生成错误页面,减少服务器负载。
  • 去掉 if 条件避免了 Nginx 中 if 指令的潜在性能问题,尤其在高并发场景下。

2. 配置 HTTPS

对于 HTTPS 网站,需要创建一个默认的 SSL 配置文件来处理通过 IP 或未配置域名的 HTTPS 访问。例如,创建 default-ssl 文件:

# default-ssl
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    ssl_certificate /path/to/cert/www.example.com.pem;
    ssl_certificate_key /path/to/cert/www.example.com.key;

    server_name _;

    return 444;
}

注意

  • 必须提供有效的 SSL 证书和密钥文件,否则 HTTPS 访问会失败。
  • 使用 return 444 替代 return 500,与 HTTP 配置保持一致,高效拒绝未授权访问。

正常的 HTTPS 网站配置如下,创建 example-website-ssl 文件:

# example-website-ssl
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate /path/to/cert/www.example.com.pem;
    ssl_certificate_key /path/to/cert/www.example.com.key;
    ssl_session_timeout 30m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_prefer_server_ciphers on;

    server_name www.example.com;

    root /path/to/www.example.com;

    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
}

说明

  • 使用 TLSv1.2 和 TLSv1.3 协议以提高安全性。
  • 配置合理的加密套件,禁用不安全的加密算法。
  • 使用 PHP 8.1 支持动态网站。

3. 处理恶意域名指向

如果已经有恶意域名指向你的服务器 IP,可以通过重定向将这些流量导入自己的域名。修改 defaultdefault-ssl 文件如下:

修改 default 文件(HTTP):

# default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    return 301 https://www.example.com;
}

修改 default-ssl 文件(HTTPS):

# default-ssl
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    ssl_certificate /path/to/cert/www.example.com.pem;
    ssl_certificate_key /path/to/cert/www.example.com.key;

    server_name _;

    return 301 https://www.example.com;
}

说明

  • return 301 表示永久重定向,将所有未匹配的 HTTP 或 HTTPS 请求重定向到你的域名。
  • 这不仅能防止流量被蹭,还能将流量导入你的合法域名。

HTTP 到 HTTPS 重定向

为了确保所有 HTTP 请求都重定向到 HTTPS,创建或修改 example-website 文件:

# example-website
server {
    listen 80;
    listen [::]:80;

    server_name www.example.com;

    return 301 https://$server_name$request_uri;
}

说明

  • 将 HTTP 请求永久重定向到 HTTPS,确保用户始终使用安全连接。

4. 语法错误分析

以下是原文中存在的语法错误或不推荐的配置问题,以及对新代码的检查:

  1. 重复的 return 语句

    • 原文中 defaultdefault-ssl 配置同时包含 return 500return 301,会导致语法错误或后一个语句覆盖前一个。新代码使用单一 return 语句,避免此问题。
  2. 过时的 ssl on 语句

    • 原文使用了 ssl on,在新版本 Nginx 中已弃用。新代码正确使用 listen 443 ssl
  3. PHP 版本过旧

    • 原文使用 PHP 7.0,已停止支持。新代码更新为 PHP 8.1。
  4. SSL 协议配置不完整

    • 原文包含不安全的 TLSv1 和 TLSv1.1。新代码只使用 TLSv1.2 TLSv1.3
  5. 缺少 $request_uri 在重定向中

    • 原文的 HTTP 到 HTTPS 重定向缺少 $request_uri,可能导致路径丢失。新代码使用 return 301 https://$server_name$request_uri
  6. 注释错误

    • 提供的代码中,注释提到“对直接 IP 访问返回 500 错误”,但实际使用 return 444。这是一个描述错误,可能误导读者。改进后的配置修正了注释为“关闭连接”,并推荐直接使用 return 444 替代 if 条件,以提高性能。
  7. 使用 if 指令的性能问题

    • 提供的代码使用 if ($host ~* "^[0-9.]+$|^[0-9a-f:]+$") 检查 IP 地址。虽然功能正确,但 if 指令在 Nginx 中可能影响性能。改进后的配置直接使用 return 444,更高效。
  8. 未说明 Nginx 配置测试

    • 原文未提到修改配置后需运行 nginx -t 测试语法。新代码分析中已补充此建议。

5. 总结

通过以上配置,我们可以:

  • 使用 Nginx 实现域名绑定,禁止通过 IP 直接访问网站(推荐使用 return 444 关闭连接)。
  • 配置 HTTPS,确保安全通信。
  • 通过重定向处理恶意域名指向,保护服务器流量。
  • 优化配置,避免语法错误和不安全的设置。

每次修改 Nginx 配置文件后,记得运行以下命令检查语法并重启服务:

nginx -t
systemctl restart nginx

希望这些配置方法能帮助大家更好地管理自己的网站!

No comments

公司简介

 

自1996年以来,公司一直专注于域名注册、虚拟主机、服务器托管、网站建设、电子商务等互联网服务,不断践行"提供企业级解决方案,奉献个性化服务支持"的理念。作为戴尔"授权解决方案提供商",同时提供与公司服务相关联的硬件产品解决方案。
备案号: 豫ICP备05004936号-1

联系方式

地址:河南省郑州市经五路2号

电话:0371-63520088

QQ:76257322

网站:800188.com

电邮:该邮件地址已受到反垃圾邮件插件保护。要显示它需要在浏览器中启用 JavaScript。