nginx兜底服务必须通过listen的default_server标志实现,而非server_name空字符串;它处理ip访问、空host及未匹配域名请求,同一端口仅允许一个default_server且https需配有效证书。

在 Nginx 中,server_name 不能直接设为空字符串(如 server_name "";)来匹配纯 IP 访问,这是无效语法,Nginx 会报错:invalid server_name ""。
用 default_server 捕获未匹配的请求
真正可靠的做法是:利用 listen 指令的 default_server 参数,让某个 server 块作为该端口上的默认兜底服务。当用户直接用 IP(如 http://192.168.1.100)访问时,HTTP 请求头中 Host 字段就是 IP 地址本身,若没有其他 server 的 server_name 显式匹配这个 IP,Nginx 就会交给标记为 default_server 的块处理。
示例配置:
server {
listen 80 default_server;
server_name _; # 或留空不写 server_name,但必须有 default_server
return 403; # 或返回欢迎页、重定向等
}-
default_server必须加在listen行上,且每个端口(如80、443)最多只能有一个 -
server_name _;是一种惯用占位符(Nginx 认为它永远不会被真实 Host 匹配),可写可不写;关键是default_server - 如果已有其他
server块监听相同端口但没加default_server,Nginx 会把第一个定义的server当作默认项——但显式声明更清晰、更可控
避免意外匹配域名请求
如果你只想拦截 IP 访问,而不希望这个 default_server 同时响应所有未知域名(比如用户输错域名),可以配合 if 判断 $host 是否为纯 IP:
server {
listen 80 default_server;
if ($host ~ ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$) {
return 403;
# 或 rewrite /ip-access.html break;
}
return 444; # 非 IP 请求直接关闭连接(静默拒绝)
}注意:if 在 server 级别可用,但应只用于简单判断(如 Host、$args)。正则中 IP 校验较简略,生产环境如需严格校验,建议用 Lua 或后端处理。
HTTPS 场景下同样适用
对于 HTTPS,default_server 仍有效,但要注意 SNI(Server Name Indication):客户端在 TLS 握手时会发送 Host 名。若用户用 IP 访问 HTTPS,部分旧客户端可能不发 SNI,此时 Nginx 仍会选 default_server;现代浏览器通常会发,但 Host 字段仍是 IP,所以逻辑一致。
配置示例:
server {
listen 443 ssl http2 default_server;
ssl_certificate /path/to/default.crt;
ssl_certificate_key /path/to/default.key;
server_name _;
return 403;
}- 务必为
default_server的 HTTPS 块提供有效的证书,否则 TLS 握手失败 - 若使用 Let’s Encrypt 等自动签发工具,需单独为该 IP 申请证书(或使用通配符+DNS验证),不能复用域名证书
验证是否生效
重启 Nginx 后,可通过以下方式测试:
- 浏览器访问
http://你的服务器IP,看是否返回预设响应(如 403) - 命令行执行:
curl -I http://192.168.1.100,检查状态码和Server头 - 查看 Nginx 错误日志:
tail -f /var/log/nginx/error.log,确认无配置错误 - 运行
nginx -T | grep -A5 "listen.*default",确认default_server已加载











