You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx配置疑问:为何带test.com主机头的HTTP请求匹配了HTTPS默认服务器块

Nginx配置疑问:为何带test.com主机头的HTTP请求匹配了HTTPS默认服务器块

这个问题的核心在于Nginx对请求的处理顺序:协议层的校验优先级远高于server_name的匹配逻辑,咱们一步步拆解清楚:

  1. 先看你的两个server块的监听差异:

    • 第一个块是listen 8200;:表示监听8200端口,处理纯HTTP请求
    • 第二个块是listen 8200 ssl default_server;:这里的ssl标记是关键——它告诉Nginx,这个8200端口的监听套接字要强制启用SSL/TLS协议,只能处理HTTPS请求;同时default_server意味着如果请求匹配不到其他server块,就 fallback 到这个块
  2. 当你执行curl -H "Host: test.com" http://127.0.0.1:8200时,发送的是纯HTTP请求——没有SSL握手过程,直接就发了HTTP的请求行和头信息。这时候Nginx的处理流程是:

    • 首先检查8200端口的监听套接字:因为第二个server块的listen 8200 ssl已经把这个端口的套接字设置为SSL模式,Nginx会先尝试和客户端完成SSL握手
    • 但你的请求是纯HTTP,根本没有SSL握手的步骤,Nginx立刻识别出这是非法请求,直接返回400 Bad Request: plain HTTP request was sent to HTTPS port
    • 这个过程发生在Nginx解析HTTP请求头(包括Host字段)之前,所以第一个server块的server_name test.com根本没机会参与匹配!
  3. 验证这个逻辑的小方法:

    • 把第一个server块的监听端口改成8201,比如:
      server {
        listen 8201;
        server_name test.com;
      
        location / {
          return 200 'Block1';
        }
      }
      
    • 再执行curl -H "Host: test.com" http://127.0.0.1:8201,就会正常返回Block1,说明server_name的匹配逻辑本身是正常的,问题出在端口的SSL标记冲突上
  4. 更合理的配置建议:

    • 不要在同一个端口上混合配置HTTP和HTTPS的server块,应该分开端口(比如80端口跑HTTP,443跑HTTPS),这也是行业通用的做法
    • 如果特殊场景下必须用同一个端口,需要借助SNI等高级配置,但这种需求非常少见,不推荐

备注:内容来源于stack exchange,提问作者Parzival

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 11:33:03