nginx配置了仅使用域名访问,但是还能使用IP:PORT访问

在Nginx中,当用户能通过IP地址+端口访问到服务,而你已经配置了server_name,这通常与Nginx的虚拟主机匹配机制有关。以下是具体原因和解决方法:

原因分析

Nginx处理请求时,会根据请求头中的Host字段匹配对应的server块:

  1. 当请求的Host字段(即访问时使用的域名/IP)与某个server块的server_name完全匹配时,Nginx会使用该server块处理请求。
  2. 若没有匹配的server_name,Nginx会使用默认服务器(default server)处理请求。
  3. 如果你只配置了一个server块,Nginx会默认将其作为"默认服务器",即使请求的Host是IP地址,也会被这个server块处理,因此用户能通过IP+端口访问。

解决方法:禁用IP访问

需要添加一个默认服务器块 ,专门处理不匹配server_name的请求(如IP访问),并返回拒绝响应(如403/404)。

示例配置如下:

nginx 复制代码
# 1. 默认服务器:处理所有不匹配server_name的请求(如IP访问)
server {
    listen 8899 ssl default_server;  # 关键:default_server指定为默认服务器
    server_name _;  # 通配符,表示匹配所有未被其他server_name匹配的请求
    
    # 禁用IP访问:直接返回403禁止访问
    return 403;
    
    # 若使用SSL,需要配置证书(可复用已有证书,或仅用于拒绝访问)
    ssl_certificate /path/to/your/cert.pem;
    ssl_certificate_key /path/to/your/key.pem;
}

# 2. 你的业务服务器:仅处理www.jadl.com的请求
server {
    listen 8899 ssl;
    server_name www.jadl.com;  # 仅匹配该域名
    
    # 你的其他配置(如root、location等)
    # ...
    ssl_certificate /path/to/your/cert.pem;
    ssl_certificate_key /path/to/your/key.pem;
}

关键说明

  1. default_server:标记该server块为默认服务器,处理所有不匹配server_name的请求。
  2. server_name _:下划线是一个特殊值,表示"不匹配任何合法域名",专门用于捕获IP访问等无效Host请求。
  3. return 403:直接拒绝IP访问,也可根据需求改为return 404或跳转至指定页面。

配置后重启Nginx,IP+端口的访问会被默认服务器拦截,只有www.jadl.com:8899能正常访问。

即使注释了 listen [::]:8899 default_server;,用户仍能通过 IP+端口访问,原因在于:Nginx 的"默认服务器"机制不仅针对 IPv6([::] 是 IPv6 地址格式),还会作用于 IPv4,且默认服务器是"自动分配"的

具体原因

  1. 默认服务器的自动分配规则

    当某个端口(如 8899)上没有显式标记 default_serverserver 块时,Nginx 会将该端口上的第一个 server 视为默认服务器。

    你当前的配置中,可能只有一个 server 块监听 8899 端口,因此它会被自动当作默认服务器,无论请求的 Host 是域名还是 IP,都会被这个 server 块处理。

  2. 注释的是 IPv6 配置,不影响 IPv4

    你注释的 listen [::]:8899 default_server; 仅针对 IPv6 地址的默认服务器,而用户可能通过 IPv4 地址(如 192.168.x.x:8899)访问,此时 Nginx 仍会使用你的业务 server 块作为默认服务器处理请求。

解决方法:显式配置 IPv4 和 IPv6 的默认服务器

需要同时针对 IPv4 和 IPv6 配置默认服务器,明确拒绝 IP 访问。完整配置示例:

nginx 复制代码
# 1. IPv4 默认服务器:拒绝 IP 访问
server {
    listen 8899 ssl default_server;  # 明确标记为 IPv4 的默认服务器
    server_name _;  # 匹配所有未被其他 server_name 匹配的请求
    return 403;     # 拒绝访问
    # SSL 证书配置(可复用业务证书)
    ssl_certificate /path/to/your/cert.pem;
    ssl_certificate_key /path/to/your/key.pem;
}

# 2. IPv6 默认服务器:拒绝 IP 访问(即使不使用 IPv6,也建议配置)
server {
    listen [::]:8899 ssl default_server;  # 明确标记为 IPv6 的默认服务器
    server_name _;
    return 403;
    # 同上,配置 SSL 证书
    ssl_certificate /path/to/your/cert.pem;
    ssl_certificate_key /path/to/your/key.pem;
}

# 3. 你的业务服务器:仅处理域名请求
server {
    listen 8899 ssl;  # 不要加 default_server,避免成为默认服务器
    listen [::]:8899 ssl;  # 如需支持 IPv6 域名访问,可添加此行
    server_name www.jadl.com;  # 仅匹配该域名

    # 你的其他业务配置(如 root、location 等)
    # ...
    ssl_certificate /path/to/your/cert.pem;
    ssl_certificate_key /path/to/your/key.pem;
}

关键说明

  • 业务服务器块不要加 default_server,避免被当作默认服务器。
  • 通过 server_name _return 403,所有 IP 访问(无论 IPv4 还是 IPv6)都会被拒绝。
  • 配置后需重启 Nginx 生效:nginx -s reload

这样就能确保只有 www.jadl.com:8899 可访问,IP+端口的访问会被拒绝。