流量错乱到其他网站,根本原因是Nginx多server块间域名匹配冲突或加载顺序干扰:未精确匹配Host头的请求落入隐式default_server(首个server块),或SNI未正确传递导致证书错配;须显式设default_server、精确配置server_name、独立绑定证书并用curl/openssl验证。

流量错乱到其他网站,通常不是配置没写,而是多个 server 块之间发生了域名匹配冲突或加载顺序干扰。Nginx 不会报错,但请求悄悄进了“不该进”的站点——关键在 谁先被选中、谁真正匹配、谁成了默认兜底。
确认 server_name 是否精确命中 Host 头
Nginx 的 server_name 匹配严格区分大小写,且不自动补 www 或协议前缀。比如:
- 配置了
server_name example.com;,但用户访问www.example.com→ 不匹配,可能落入其他块或默认 server - 配置了
server_name ~^([a-z]+)\.example\.com$;,但没设server_name example.com;→ 顶级域名访问也会失配
建议每个主域显式列出常用变体:server_name example.com www.example.com api.example.com;
检查是否有隐式 default_server 抢占流量
当请求的 Host 头不匹配任何 server_name,Nginx 会交给该端口下第一个定义的 server 块处理——这就是隐式兜底行为。
- 运行
nginx -T | grep "listen.*443" -A 5,看哪个server块排最前面且没加default_server - 若该块绑的是 site-b.com 的证书,那么所有未明确定义的域名(如 typo.site.com)都会触发证书错配或内容错乱
解决方法:显式声明一个安全兜底块:server { listen 443 ssl default_server; return 444; }
验证 SNI 与证书是否一一对应
HTTPS 场景下,证书干扰常表现为“访问 A 域名却弹出 B 域名的证书警告”。这说明 TLS 握手阶段没按 SNI 选对证书。
- 每个域名必须有独立的
server { listen 443 ssl; server_name xxx.com; ssl_certificate ...; }块 - 禁止把多个
server_name写在一个 HTTPS server 块里(否则只用第一个证书) - 用
openssl s_client -connect your-ip:443 -servername site-a.com -showcerts 2>/dev/null | openssl x509 -noout -text | grep "DNS:"确认返回的证书确实包含目标域名
用 curl 模拟真实请求路径验证路由
别只靠浏览器访问,用带 Host 头的 curl 直接测试 Nginx 路由逻辑:
-
curl -I --resolve example.com:80:192.168.1.100 http://example.com/(绕过 DNS,直连 IP 并指定 Host) -
curl -I --resolve example.com:443:192.168.1.100 https://example.com/ -k(忽略证书错误,看实际响应头和 body 来源)
观察返回的 Server、X-Accel-Redirect 或页面内容,比对是否来自预期的 root 或 upstream。


















