目录

nginx如何防止非 server_name 配置的域名访问

在 Nginx 中,如果客户端请求的域名未在 server_name 指定的配置中匹配,Nginx 仍然会将请求转发到默认的 server 块。为了防止非 server_name 配置的域名访问,可以使用以下几种方法:


方法 1:使用默认 server 块拦截未匹配的域名

在 Nginx 配置文件中(通常是 /etc/nginx/nginx.conf/etc/nginx/conf.d/default.conf),添加一个默认的 server 块,只允许 server_name 明确配置的域名访问,其他所有未匹配的域名都返回 444(直接断开连接)。

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    return 444;
}

解释

  • listen 80 default_server;:表示该 server 块是默认的服务器,所有未匹配的请求都会进入这里。
  • server_name _;:这个 _ 是一个通配符,表示未匹配的任何域名都会进入该 server 块。
  • return 444;:返回 444 状态码,直接断开连接,不给客户端任何响应,提高安全性。

方法 2:使用 if 语句在特定 server 块中拦截

如果不想使用默认 server 块,也可以在你的业务 server 块中检查 Host 头,拒绝非指定域名的访问。

server {
    listen 80;
    server_name example.com www.example.com;

    if ($host !~* ^(example\.com|www\.example\.com)$) {
        return 403;
    }

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

解释

  • if ($host !~* ^(example\.com|www\.example\.com)$):检查 Host 头,如果不符合 example.comwww.example.com,则返回 403 Forbidden
  • return 403;:拒绝访问。

⚠️ 注意:Nginx 官方不推荐 if 语句用于控制访问,但在简单场景下可以使用。


方法 3:监听特定 IP,限制非指定域名访问

如果服务器有多个 IP,可以让 Nginx 只监听特定 IP,并通过 server_name 控制。

server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

server {
    listen 80;
    server_name _;  # 未匹配的所有请求
    return 444;     # 直接断开连接
}

方法 4:针对 HTTPS 限制非 server_name 访问

如果使用 HTTPS,并且不希望未配置的域名访问你的服务器,可以使用以下方式:

server {
    listen 443 ssl default_server;
    server_name _;
    
    ssl_certificate /etc/nginx/ssl/default.crt;
    ssl_certificate_key /etc/nginx/ssl/default.key;

    return 444;
}

解释

  • default_server 处理所有未匹配的域名。
  • 使用一个默认的 SSL 证书(可以是一个无效或自签名证书)。
  • 直接返回 444,防止服务器暴露给未授权的访问者。

如何生成自签名 SSL 证书?

mkdir -p /etc/nginx/ssl
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
    -keyout /etc/nginx/ssl/default.key \
    -out /etc/nginx/ssl/default.crt \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=Default/CN=default"

总结

如果希望完全禁止未配置 server_name 的域名访问,推荐使用 方法 1(默认 server 块拦截)或 方法 3(监听特定 IP),它们是 Nginx 官方推荐的方式,性能最好,配置最清晰。

如果有更复杂的需求(如某些域名返回 403,其他域名正常访问),可以使用 方法 2if 语句检查 $host)。对于 HTTPS,使用 方法 4 结合默认 server 块。