X-Forwarded-Proto 传递原始协议
经过反向代理后,后端看到的连接往往是 HTTP,但用户访问的其实是 HTTPS。X-Forwarded-Proto 用来把第一跳的协议方案告诉后端,应用据此生成正确的跳转地址、判断是否需要设置安全 Cookie,以及决定是否强制跳转 HTTPS。它是事实标准而不是正式规范,写法上各家代理基本一致,但应用必须只信任来自可信代理的值。
基本信息
| 请求头名 | X-Forwarded-Proto,常缩写为 XFP |
|---|---|
| 作用 | 传递请求到达第一跳时使用的协议方案 |
| 规范 | 无正式 RFC,属于约定俗成;对应的标准化写法是 Forwarded 头里的 proto 参数 |
| 典型取值 | http 与 https |
| 设置位置 | 反向代理或负载均衡在转发给上游时补充或覆盖 |
| 信任前提 | 只接受可信代理来源的值,否则可被伪造 |
代理侧与应用侧配置
代理侧与应用侧配置
# nginx 反向代理:把原始协议带下去,并覆盖客户端可能伪造的值
# location / {
# proxy_set_header X-Forwarded-Proto $scheme;
# }
# 应用侧按框架配置信任该头,例如 Django:
# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# 验证后端是否收到正确的头
curl -sI https://app.example.com/ | grep -i 'strict-transport-security' # 后端若误判协议,安全头可能不生效同类转发头对照
| 头名 | 传递内容 | 常见用途 |
|---|---|---|
| X-Forwarded-For | 客户端与沿途代理的 IP 列表 | 访问日志记录真实来源 |
| X-Forwarded-Proto | 第一跳的协议方案 | 生成跳转地址与安全 Cookie |
| X-Forwarded-Host | 原始请求的 Host | 多域名共用后端时还原站点 |
| X-Real-IP | 单个客户端 IP | 简化场景下替代长列表 |
| Forwarded | 标准化的合并写法 | 新部署优先考虑使用 |
典型使用场景
- HTTPS 终止在负载均衡,后端需要生成 https 链接,否则出现混合内容告警
- 排查 http 与 https 互相跳转的死循环
- 应用是否设置安全 Cookie 与 HSTS 头的判断依据
- 多域名共用后端时还原真实访问站点
- 审计与日志中记录真实客户端来源地址
X-Forwarded-Proto 可以被客户端伪造。如果应用无条件信任它来判断「链路已加密」,攻击者可能绕过强制 HTTPS 的判断。正确做法是由代理覆盖该头,应用只信任来自代理的连接。