Lobsters | 📄 原文链接 | 2026-11-08 收录

被无条件信任的 Forwarded 头:一个代理配置如何变成 IP 伪装

来源:lkoskela.fi — 2026-11-05

📋 概述

作者在部署 HTTPS 反向代理时发现 Envoy 对 X-Forwarded-For 的处理怪异,干脆让代理丢弃所有传入的 X-Forwarded-* 与 Forwarded,然后想到一个问题:那些同时支持两套头的 Web 框架,会不会被利用?答案是会。RFC 7239 的 Forwarded 是 X-Forwarded-* 的标准化替代,但绝大多数代理、CDN 与中间件只处理 X-Forwarded-*,根本不碰 Forwarded,于是客户端自己塞的 Forwarded 会原样送到后端;而 Rails、Spring、Jetty 等在默认或最小配置下会读 Forwarded 并优先于 X-Forwarded-*,导致客户端 IP、主机名、协议都能被伪造。「可信代理」机制在这种场景下失效,因为它防的是绕过代理的直连请求,而不是代理原样透传的客户端伪造头。实测:Jetty 12 从 2016 年起默认开启且优先 Forwarded;Spring Boot 4.2 之前 Jetty、Reactor Netty 与 Spring 自身三种策略都兼收两套头;Rails 8.1 改用 Rack 取客户端 IP 而「顺带」支持了 Forwarded: for,且 8.1.4.1 之前的冲突检测漏掉其中一个头。Symfony 更安全(需显式开启、冲突即 400),但仍可伪造 host。作者还给了指纹方法:发一个端口非法的 host,返回 400 就大概能断定后端是 Jetty、Spring 或 Symfony。

🔑 核心要点

💡 金句

开发者和运维应确保代理与应用在「信任哪些头」上达成一致,并配置代理丢弃请求中任何不可信的代理头。
← 返回 Lobsters 首页