Nginx反向代理中proxy_pass必须配合proxy_set_header设置Host、X-Real-IP和X-Forwarded-For三个基础头,否则后端无法获取真实域名与客户端IP,导致400、502或日志IP全为127.0.0.1;proxy_pass末尾斜杠决定路径是否剥离前缀,有/则移除location匹配部分,无/则透传完整URI。

直接说结论:Nginx 的 proxy_pass 是反向代理的核心,但只写这一行几乎必然出问题——漏掉 proxy_set_header 会导致后端收不到真实 Host 和客户端 IP,常见报错如 502、400 或后端日志里全是 127.0.0.1。
为什么 proxy_pass 后必须配 proxy_set_header
后端服务(比如 Node.js、Django、Spring Boot)依赖 Host 头来判断域名,依赖 X-Real-IP 或 X-Forwarded-For 来记录访问者真实 IP。Nginx 默认会清空或重写这些头,不显式设置就会丢数据。
常见错误现象:
- 后端返回 400 Bad Request(因 Host 为空或为
localhost) - 日志里所有请求来源都是
127.0.0.1或 Nginx 本机地址 - HTTPS 站点跳转成 HTTP(缺
X-Forwarded-Proto)
必须加的三行(放在 location 块内):
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
如果后端需要知道协议类型(比如做跳转判断),再加一行:
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass 的 URL 尾部斜杠影响路径转发
这个细节 90% 的人踩过坑:斜杠位置决定路径是否被截断。
假设你配置了:
location /api/ {
proxy_pass http://127.0.0.1:3000/;
}
那么请求 /api/users 会被转发为 http://127.0.0.1:3000/users(/api/ 被剥离)。
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
但如果写成:
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
请求 /api/users 就会原样发过去:http://127.0.0.1:3000/api/users(后端可能根本没这个路由)。
简单记法:
-
proxy_pass末尾有/→ 前缀路径被去掉 -
proxy_pass末尾无/→ 完整路径透传 - 如果用域名或 upstream 名(如
http://backend),末尾必须带/才能触发路径剥离逻辑
多站点或不同后端共存时,server_name 和 upstream 怎么配合
一个 Nginx 实例代理多个服务,靠的是 server_name 匹配域名 + upstream 定义后端集群。
例如要同时代理两个服务:
upstream app_a {
server 192.168.1.10:8080;
}
upstream app_b {
server 192.168.1.11:3000;
}
然后分别定义 server 块:
server {
listen 80;
server_name a.example.com;
location / {
proxy_pass http://app_a;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name b.example.com;
location / {
proxy_pass http://app_b;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
注意点:
-
upstream必须定义在http块里,不能在server或location内 - 多个
server块监听同一端口(如 80)时,server_name是唯一区分依据 - 如果走 HTTPS,记得在
server块里加listen 443 ssl和证书路径,且proxy_pass可仍用http://(SSL 终止在 Nginx)
最常被忽略的一点:改完配置后,别只 nginx -t 就以为万事大吉——必须 nginx -s reload(不是 restart),否则旧 worker 进程还在跑老配置。reload 失败时,旧配置继续生效,但新规则完全不生效,排查起来极难定位。

















