Ryan

Nginx 反代理的四个标准头:官方文档摘抄

Host / X-Real-IP / X-Forwarded-For / X-Forwarded-Proto,少一个都会以难查的方式出问题;还有那条反直觉的「proxy_set_header 不跨层合并」。

评论
Nginx 反代理的四个标准头:官方文档摘抄

反向代理是自建服务里最容易「配得看起来能跑、实际埋着雷」的一环。Nginx 官方文档里关于 proxy_set_header 的说明,加上几个高频踩坑点,值得逐条抄下来。

一、四个标准头:一个都别少

官方反代示例里给出的基础配置,是这一领域的「最小正确集」:

location / {
    proxy_pass http://backend;
    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;
}

每一行都在解决一个具体问题:

  • Host $host:保留客户端请求的原始域名。少了它,后端只能看到 proxy_pass 里的内网主机名,多域名共用一套后端时直接错乱,也是「登录后跳回内网地址」的经典元凶;
  • X-Real-IP:把真实客户端 IP 传给后端。否则后端日志里全是 Nginx 的地址;
  • X-Forwarded-For:注意这里用的是 $proxy_add_x_forwarded_for 而不是 $remote_addr——前者会把已有链路追加在逗号分隔列表后面,保留多级代理的完整路径;
  • X-Forwarded-Proto:告诉后端「用户那一侧其实是 HTTPS」。少了它,后端生成的重定向会把自己降级回 http,浏览器直接报混合内容。

二、WebSocket 要多两行

默认的 HTTP/1.0 不具备升级连接的能力,反代 WebSocket 必须显式抬高协议版本并透传升级头:

proxy_http_version 1.1;
proxy_set_header Upgrade    $http_upgrade;
proxy_set_header Connection "upgrade";

典型的症状是:页面能打开,但实时日志、终端、状态推送全部卡住不动——那就是漏了这两行。

三、最容易吃亏的一条:proxy_set_header 不跨层合并

与 add_header 不同,proxy_set_header 不会从上层继承后合并:只要在更内层的 location 里写了任意一条 proxy_set_header,server 层配置的那一整组就会被整体覆盖。

这条反直觉到官方要专门写一段提示。后果是:你在 server 里精心写的四个头,被某个子路径 location 里随手加的一行 proxy_set_header 全部抹掉,而且只有那个子路径出问题,极难排查。

对策只有一条:凡是写了 proxy_set_header 的 location,就把需要的那组头原样补齐,别指望继承。

四、proxy_pass 末尾那个斜杠

少一个斜杠、多一个斜杠,转发结果完全不同:

  • proxy_pass http://backend; → 原始 URI 原样拼接;
  • proxy_pass http://backend/; → 用斜杠后面的部分替换掉 location 匹配到的那段前缀。

子路径挂载(把服务放在 /app/ 下却要它以为自己在根目录)时,这个斜杠就是唯一开关。

五、出处

  • Nginx Documentation — NGINX Reverse Proxy
    https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
  • Nginx Documentation — ngx_http_proxy_module / proxy_set_header
    https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header

六、在自家服务器上的印证

本站前面挂的正是 Nginx Proxy Manager(底层就是 Nginx),上面这些规则天天在生效:

  • 十来个域名共用同一台 Nginx,全靠 Host 头区分后端——少这一行,所有站点会一起指向第一个后端;
  • 日志面板和监控面板都是 WebSocket 重依赖,反代里必须开 Upgrade;这两个服务当初「页面能开、数据不动」,根因就在这里;
  • 博客后台与网盘的登录跳转依赖 X-Forwarded-Proto,否则会从 https 掉回 http 再被浏览器拦下;
  • 证书统一由 NPM 申请与续签(现在这批有效期到 2026 年 12 月),所以「协议头正确」不只是观感问题,而是能不能正常登录的问题。

评论

推荐阅读

订阅邮件

订阅更新,及时收到最新文章。

作者