反向代理与 Forwarded 相关 Header 深度解析

今天后端一个trace功能,发现移动端app请求,拿不到forwarded的ip,而且建立一个简单的echo服务器后,发现nginx是有添加的,但是收到的header被过滤掉了一些,这到底是什么原因呢?于是深入研究了一下,从而出了这篇文章,希望你能在header头key丢失时,获得一些启迪。
顺便打个广告,时光小铺上架鸿蒙商城,这款次世代的精益时间记录、身心平衡探索软件,值得你体验现在是免费的哦

速读

我的情况是,缺少了X-Forwarded-Proto,在wss 代理到 ws时 (https->http upgrade)时,x-xxx头等都丢失了,只有host/user-agent/accept-language三个),框架层把额外的过滤了,😔

所以在https/http wss/ws 不对等代理时,一定要注意

正文

在现代 Web 架构中,**反向代理(Reverse Proxy)**是必不可少的组件,它不仅做负载均衡,还负责 SSL 终止、路径重写等。反向代理在转发请求时,客户端的真实信息(IP、协议、端口等)可能会丢失,因此出现了 ForwardedX-Forwarded-* 系列 HTTP header,用于传递原始请求信息。本文将详细解析这些 header 的作用及不同场景下的影响。


1. 常见 Forwarded / X-Forwarded Header

Header 作用
X-Forwarded-For 原始客户端 IP 地址,代理服务器会追加自身 IP。多级代理时可形成逗号分隔列表。
X-Real-IP 客户端 IP,一般由最近的代理直接设置(单个 IP)。
X-Forwarded-Proto 客户端协议(http / https),反向代理可以告知后端真实协议。
X-Forwarded-Host 原始请求 Host(域名 + 端口),用于后端生成 URL 或做多域名处理。
Forwarded RFC 7239 标准,整合了 above 信息,例如:Forwarded: for=1.2.3.4; proto=https; host=example.com

⚠ 注意:X-Forwarded-* 是 de facto 标准,兼容性高;Forwarded 是官方标准,但实际使用相对少。


2. 各类场景下的 Header 传递与影响

2.1 HTTP → HTTP

  • 场景:客户端 HTTP 请求 → Nginx / HAProxy → HTTP 后端
  • 推荐设置:
nginx 复制代码
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
  • $remote_addr:客户端直接连接到 Nginx 的 IP
  • $proxy_add_x_forwarded_for:保留已有 X-Forwarded-For,多级代理可追踪链路
  • 后端可以使用这些 header 获取真实客户端 IP、Host、协议
  • ⚠ 注意:HTTP → HTTP 不会丢 header,除非后端框架对非标准 header 做过滤

2.2 HTTPS → HTTP(SSL 终止在 Nginx)

  • 场景:客户端 HTTPS 请求 → Nginx 解密 → HTTP 后端
  • 核心问题:后端看到的请求是 HTTP,如果不传递协议信息,后端可能认为是 HTTP → 会生成不正确的 URL、重定向或安全校验失败
  • 必须设置:
nginx 复制代码
proxy_set_header X-Forwarded-Proto $scheme; # 传递 https
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
  • 例如 Meteor / SockJS 对 WebSocket 协议升级请求,如果 X-Forwarded-Proto 缺失,可能 返回 null 客户端 IP(正如你之前遇到的情况)

  • ⚠ 影响:

    • URL 生成(url.protocol
    • Cookie 的 Secure 判断
    • WebSocket Upgrade 协议识别

2.3 HTTP → HTTPS(后端启用 HTTPS)

  • 场景:客户端 HTTP → Nginx → 后端 HTTPS
  • header 设置基本相同:
nginx 复制代码
proxy_set_header X-Forwarded-Proto $scheme; # http
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • 这里 $scheme 会是 http(客户端请求的协议)
  • 后端 HTTPS 接收时,会看到协议是 HTTP → 可以用于生成绝对 URL 或安全策略判断

2.4 HTTPS → HTTPS(SSL 终止 + 后端 HTTPS)

  • 场景:客户端 HTTPS → Nginx 解密 → 重新加密 → 后端 HTTPS
  • header 设置:
nginx 复制代码
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • $scheme 可以硬编码为 https 或使用 $scheme 变量
  • 保证后端知道原始请求协议

2.5 WebSocket 场景(ws / wss)

WebSocket 的 header 特殊,升级请求为 HTTP Upgrade,反向代理需要特别处理:

nginx 复制代码
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
5.5.1 WSS → WS(客户端 wss,Nginx SSL 终止,后端 ws)
  • 如果缺少 X-Forwarded-Proto,后端框架可能无法判断真实客户端协议 → SockJS/Meteor clientAddress 返回 null
  • 解决方案:一定要加 X-Forwarded-Proto 并确保 Nginx 转发 Upgrade 请求
5.5.2 WS → WSS(客户端 ws,Nginx 转发到后端 wss)
  • $scheme 会是 ws,传递给后端时可以告诉后端原始协议
  • 后端可据此生成重定向 URL 或安全校验
5.5.3 WS → WS / WSS → WSS
  • 与普通 HTTP header 类似
  • 确保 Upgrade / Connection / Forwarded Header 都设置
  • 不要依赖自定义 header 被 WebSocket transport 保留(如 SockJS 对 App WebView 可能丢失)

3. 总结:Header 影响点

  1. X-Forwarded-For / X-Real-IP → 影响 后端获取真实客户端 IP
  2. X-Forwarded-Proto → 影响 协议识别、URL 生成、Cookie Secure、WebSocket Upgrade
  3. X-Forwarded-Host → 影响 生成绝对 URL、多域名处理
  4. Forwarded(标准) → 可整合上述信息,现代框架开始支持

⚡ 实践建议

  • Nginx 配置统一:
nginx 复制代码
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_set_header X-Forwarded-Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
  • 不依赖 WebSocket transport 保留自定义 header(如 SockJS App WebView 可能丢失)
  • HTTPS → HTTP 或 WSS → WS 场景下,X-Forwarded-Proto 是必须的

4. 小结

  1. 反向代理会影响后端获取客户端信息
  2. 常用 Forwarded / X-Forwarded-* header 用于传递 IP、协议、Host
  3. 各种场景(HTTP/HTTPS/WS/WSS)下,Header 配置略有差异
  4. 尤其是 WebSocket + SSL 终止时,X-Forwarded-Proto 关键
  5. 后端框架(Meteor/SockJS、Node.js、Express 等)可能根据这些 header 决定 IP、协议、升级请求合法性
相关推荐
呆子罗8 小时前
原生JS请求API
开发语言·javascript·ecmascript
Moonbeam Community8 小时前
应用爆发,DeFi先行
javascript·ide·web3·区块链·polkadot
2301_796512528 小时前
使用状态管理、持久化存储或者利用现有的库来辅助React Native鸿蒙跨平台开发开发一个允许用户撤销删除的操作
javascript·react native·react.js
前端不太难8 小时前
RN Navigation vs Vue Router 的架构对比
javascript·vue.js·架构
小白学大数据8 小时前
Python 爬虫如何分析并模拟 JS 动态请求
开发语言·javascript·爬虫·python
2301_796512528 小时前
React Native鸿蒙跨平台开发包含输入收入金额、选择收入类别、记录备注和日期等功能,实战react-native-paper组件
javascript·react native·react.js
巴拉巴拉~~9 小时前
Flutter 通用表单输入组件 CustomInputWidget:校验 + 样式 + 交互一键适配
javascript·flutter·交互
San30.9 小时前
现代前端工程化实战:从 Vite 到 Vue Router 的构建之旅
前端·javascript·vue.js
sg_knight9 小时前
模块热替换 (HMR):前端开发的“魔法”与提速秘籍
前端·javascript·vue·浏览器·web·模块化·hmr