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

NGINX多server块相互影响问题:为何80端口server块无proxy_pass时443端口反向代理失效?

NGINX多server块相互影响问题:为何80端口server块无proxy_pass时443端口反向代理失效?

看起来你遇到的问题本质是NGINX的server块匹配规则和默认server选择逻辑在搞鬼,再加上你可能对server_name _的作用有误解,导致请求被错误路由了。咱们一步步拆解:

1. 先澄清一个误区:server_name _不是“万能默认”

很多人以为server_name _会匹配所有未匹配的请求,但NGINX官方文档明确说明:_只是一个普通的server_name值,它不会作为默认server使用。真正决定哪个server是默认的,是listen指令后的default_server参数——如果没有显式指定,NGINX会把第一个匹配对应端口的server块设为该端口的默认server。

2. 你的配置为什么会“互相影响”?

我们对比你两次配置的差异:

正常工作的配置(80端口server块有proxy_pass)

# 443端口server块(处理HTTPS请求)
server {
    listen       443 ssl http2;
    listen       [::]:443 ssl http2;
    include      snippets/self-signed.conf;
    include      snippets/ssl-params.conf;
    server_name  secondave.net www.secondave.net;

    location / {
        proxy_pass http://localhost:3000;
    }
}

# 80端口server块(处理HTTP请求)
server {
    listen 80;
    listen       [::]:80;
    server_name  _;

    location / {
        proxy_pass http://localhost:3000;
    }
}

这时,对于HTTPS请求(443端口),第一个匹配的server块就是上面的443 server,它的server_name正好匹配你的域名secondave.net,所以请求被正确代理到3000端口。

失效的配置(80端口server块无proxy_pass)

# 443端口server块(代码不变)
server {
    listen       443 ssl http2;
    listen       [::]:443 ssl http2;
    include      snippets/self-signed.conf;
    include      snippets/ssl-params.conf;
    server_name  secondave.net www.secondave.net;

    location / {
        proxy_pass http://localhost:3000;
    }
}

# 80端口server块(去掉了location和proxy_pass)
server {
    listen 80;
    listen       [::]:80;
    server_name  _;
}

这时你访问https://secondave.net却返回NGINX默认页面,核心原因大概率是下面两种情况之一:

  • 你的http块下还有其他更早出现的、监听443端口的server块(比如默认安装的default.conf里的配置),当你的自定义443 server块不是第一个时,NGINX会把更早的那个设为默认server。如果请求的Host头匹配失败(比如自签名证书导致SNI不生效),就会落到这个默认server,返回默认页面。
  • SELinux限制:Amazon Linux 2023默认开启SELinux,当你修改80端口的server块后,SELinux的上下文规则可能阻止了NGINX向3000端口发起代理请求。你可以检查错误日志确认:
    cat /var/log/nginx/error.log | grep "SELinux"
    

3. 你后续测试的404问题是怎么回事?

你后来把80端口的server块改成:

server {
    listen 80;
    listen       [::]:80;
    server_name  secondave.net www.secondave.net;
    return 404;
}

这时访问https://secondave.net返回404,这说明你的HTTPS请求居然被这个80端口的server块处理了——这显然不符合逻辑,唯一的解释是:你可能误修改了443端口的server块,比如不小心删掉了它的listen 443指令,或者把两个server块的内容合并到了一起,导致这个80端口的server块同时处理了443的请求,从而返回404。

4. 正确的解决方法

方法一:显式指定默认server

给你的443端口server块加上default_server参数,确保它是443端口的默认处理者:

server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    include      snippets/self-signed.conf;
    include      snippets/ssl-params.conf;
    server_name  secondave.net www.secondave.net;

    location / {
        proxy_pass http://localhost:3000;
    }
}

同时,给80端口的server块也加上default_server,并合理处理HTTP请求(比如跳转到HTTPS,不要空着):

server {
    listen 80 default_server;
    listen       [::]:80 default_server;
    server_name  _;

    # 推荐把HTTP请求永久跳转到HTTPS
    return 301 https://$host$request_uri;
}

方法二:排查SELinux规则

如果是SELinux的问题,你可以临时关闭SELinux测试(不推荐长期关闭):

sudo setenforce 0

如果测试正常,再添加永久规则允许NGINX代理:

sudo setsebool -P httpd_can_network_connect on

方法三:清理多余的server块

检查/etc/nginx/conf.d/目录下的其他配置文件,看有没有更早加载的、监听443端口的server块,把它们注释掉或者修改,确保你的自定义443 server块是第一个被加载的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 13:19:37