在Nginx中,当用户能通过IP地址+端口访问到服务,而你已经配置了server_name
,这通常与Nginx的虚拟主机匹配机制有关。以下是具体原因和解决方法:
原因分析
Nginx处理请求时,会根据请求头中的Host
字段匹配对应的server
块:
- 当请求的
Host
字段(即访问时使用的域名/IP)与某个server
块的server_name
完全匹配时,Nginx会使用该server
块处理请求。 - 若没有匹配的
server_name
,Nginx会使用默认服务器(default server)处理请求。 - 如果你只配置了一个
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;
}
关键说明
default_server
:标记该server
块为默认服务器,处理所有不匹配server_name
的请求。server_name _
:下划线是一个特殊值,表示"不匹配任何合法域名",专门用于捕获IP访问等无效Host
请求。return 403
:直接拒绝IP访问,也可根据需求改为return 404
或跳转至指定页面。
配置后重启Nginx,IP+端口的访问会被默认服务器拦截,只有www.jadl.com:8899
能正常访问。
即使注释了 listen [::]:8899 default_server;
,用户仍能通过 IP+端口访问,原因在于:Nginx 的"默认服务器"机制不仅针对 IPv6([::]
是 IPv6 地址格式),还会作用于 IPv4,且默认服务器是"自动分配"的。
具体原因
-
默认服务器的自动分配规则 :
当某个端口(如 8899)上没有显式标记
default_server
的server
块时,Nginx 会将该端口上的第一个server
块 视为默认服务器。你当前的配置中,可能只有一个
server
块监听 8899 端口,因此它会被自动当作默认服务器,无论请求的Host
是域名还是 IP,都会被这个server
块处理。 -
注释的是 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+端口的访问会被拒绝。