核心区分: 四层:校验 TCP 报文头部源 IP;七层 XFF:校验 HTTP 应用层请求头文本 伪造风险、适用场景、限制条件完全不同,结合你前面网关日志遇到的多级代理、NAT 出口漂移一并汇总。
1、四层(安全组 / 网络 ACL / 防火墙,基于 TCP 源 IP)
原理
读取 TCP/IP 数据包 IP 头里的源 IP,属于网络层,在 HTTP 解析之前完成过滤,根本不看 HTTP 头部。
伪造可能性
公网正常 TCP 业务连接:几乎无法伪造 TCP 需要三次握手,伪造源 IP 的 SYN 包,回包会路由到被伪造的 IP,攻击者收不到 SYN+ACK,无法建立完整 TCP 连接,业务请求跑不起来。
注意:DDoS 攻击可以发伪造源 IP 的裸 SYN 包,但只能做攻击,不能完成正常 HTTP 业务交互。
内网 / 同网段环境:可以 IP 欺骗 内网没有路由回包校验,可构造伪造源 IP 报文;但公网互联网业务几乎遇不到。
致命限制(非常关键,就是你遇到的场景)
只要中间经过 NAT、代理、LB、WAF、API 网关,四层看到的是【上一跳代理 / NAT 出口 IP】,看不到原始客户端 IP。
如果上一跳出口 IP 是固定 EIP / 专线固定 IP:✅四层黑白名单可用,但是只能管控代理出口,不是原始客户端;
如果上一跳是共享 NAT 地址池、多节点集群出口(你的日志:
220.202.19.150/.152/.160漂移):❌不可用,IP 不断变化,无法精准限制;家用宽带 PPPoE 动态 IP / CGNAT 共享 IP:❌四层黑白名单基本没法针对终端用户做限制。
优点 & 缺点
✅ 优点:无法被业务请求伪造;性能极高,请求还没进应用就拦截;抵御部分 DDoS ❌ 缺点:拿不到真实客户端 IP;依赖上一跳出口 IP 必须固定;多级代理场景粒度太粗
2、七层 X‑Forwarded‑For(XFF)黑白名单(API 网关、WAF 七层规则)
原理
读取 HTTP Header 文本,逗号分割 IP 列表,属于应用层。
伪造可能性
非常容易伪造,攻击者客户端直接自定义请求头即可篡改 XFF 内容。
X‑Forwarded‑For: 白名单IP
⚠️ 如果公网流量可以直接打到网关,没有前置可信代理,攻击者伪造 XFF 可以直接绕过 IP 白名单。
什么情况下 XFF 才安全?
必须上游是可信代理(ALB / CLB / WAF),并且代理做清洗:
丢弃客户端原始传入的 X‑Forwarded‑For 头,不要继承
代理把自己 TCP 四层收到的真实源 IP 追加到 XFF 列表末尾
只有经过可信代理清洗后的 XFF,里面的 IP 序列才可信;否则 XFF 只是一串可篡改的文本,没有安全意义。
致命限制
XFF 数组长度可变:经过的代理层数不一样,IP 数量不一样(你的日志:2 个 IP / 3 个 IP 两种情况); 👉 禁止写死拦截位置下标! 固定下标,链路一跳发生变化,匹配直接错位失效。 👉 正确做法:永远取 XFF 最左侧第一个 IP 作为原始客户端 IP(前提上游可信代理正确追加)。
只作用于 HTTP/HTTPS;非 HTTP 协议(TCP、UDP)拿不到 XFF。
优点 & 缺点
✅ 优点:可以拿到原始客户端真实公网 IP;多级代理场景依然可以识别源头 IP;适合业务维度 IP 管控 ❌ 缺点:原始请求可伪造;必须依赖可信代理清洗;只能处理 HTTP 类流量;在应用层处理,性能弱于四层。
3、场景对照表(结合你的业务)
表格
4、生产环境最佳实践(组合防护)
网络层(四层):安全组 / ACL 只放行可信上游代理的 IP 段,禁止公网直接访问 API 网关实例。把不可信流量直接挡在应用外面。
应用层(七层):API 网关开启 XFF 黑白名单,依靠可信代理清洗后的 XFF,取最左侧 IP 做客户端 IP 管控。
两层叠加:四层保证网关不会被原始公网直接触碰,杜绝 XFF 伪造绕过风险;七层实现对真实客户端 IP 业务级访问控制。
5、两个高频踩坑总结
❌坑:公网流量直打网关,直接开启 XFF 白名单。
后果:攻击者构造伪造 XFF 头绕过白名单。
❌坑:XFF 拦截位置写死固定数字。
后果:链路代理层数变化(多跳 / 少跳),IP 数组长度改变,匹配错位,放行 / 拦截全部错乱,就是你之前 1、2、3 位置都不对的根源。
✅正确:可信代理清洗 XFF,取 XFF 数组最左侧第一个 IP作为原始客户端 IP。
极简记忆口诀
四层看包,不怕伪造,但只能看见上一跳;上一跳 IP 一变,规则直接报废。 七层看头,能拿到真实客户端,但是头可篡改;必须可信代理清洗,不能写死数组下标。
什么是可信代理清洗 XFF
清洗 = 扔掉客户端自带、可伪造的原始
X‑Forwarded‑For,代理自己根据【四层 TCP 真实源 IP】重新构建一份 XFF 列表,再向后传递。 可信代理 = 这个代理设备你完全掌控(云厂商 CLB/WAF/API 网关、自建 Nginx),攻击者无法绕过它直接打到后端。
❶ 不做清洗(危险!绝大多数人踩坑)
攻击者直接发 HTTP 请求,自己随便写伪造头:
curl -H "X‑Forwarded‑For: 101.126.36.10" https://your-api.com
代理不删除这个头,直接追加自己的 IP往下游转发
到达网关的 XFF 变成:
101.126.36.10, 代理IP后端看到最左边是白名单 IP,直接放行 → 绕过 IP 白名单
问题根源:XFF 只是 HTTP 文本,客户端完全可以自定义;这个伪造内容被原样透传到后端。
❷ 做清洗(安全)
可信代理收到攻击者请求:
直接丢弃请求里面自带的全部
X‑Forwarded‑For头,把攻击者写的伪造内容全部删掉。代理读取四层 TCP 连接真实源 IP(这个是 TCP 报文源 IP,公网无法伪造完整连接)。
用这个真实 TCP 源 IP,新建 / 重写
X‑Forwarded‑For,再继续向后转发。
示例流程
攻击者 TCP 源 IP 是223.1.1.1,同时 HTTP 头伪造X‑Forwarded‑For: 101.126.36.10
可信代理收到 TCP 连接,四层源 IP=
223.1.1.1;http 头带伪造 XFF。清洗:删掉传入的 XFF 头,丢弃伪造的
101.126.36.10。代理新建 XFF:
X‑Forwarded‑For: 223.1.1.1,传给下一跳。
👉 下游网关拿到的 XFF 全部是代理根据真实 TCP 连接写出来的,不再是客户端可以随便篡改的文本。
为什么 “经过可信代理清洗后的 XFF 就可靠”?
所有 IP 条目来源,不再来自客户端 HTTP 头;来自 TCP 四层 socket 源 IP。 TCP 四层源 IP 公网环境下,攻击者无法伪造建立完整业务连接。
攻击者不能绕过可信代理:后端服务器安全组 / ACL 只放通可信代理的 IP 段;公网流量根本无法直连后端。
如果攻击者可以绕开代理直接访问后端,那清洗就失去意义,攻击者可以直打后端继续伪造 XFF 头。
每一跳可信代理只会追加自己四层看到的上一跳 IP,不会接收、保留客户端传入的伪造内容。
⚠️ 注意:XFF 本身没有加密签名,不是不可篡改;是 “入口被可信代理封住,所有 XFF 字段全部由可信代理根据四层数据重写”,所以可靠MDN Web Do...。
两种错误理解澄清
❌误区 1:“XFF 头本身有防篡改能力”
XFF 只是普通 HTTP header,没有签名校验。可靠的不是头本身;可靠是流量必须全部经过你可控的代理,代理把客户端伪造内容全部清除,基于四层源 IP 重写。
❌误区 2:“只要是云厂商 LB,就自动帮你清洗 XFF”
不是!要看配置模式
模式 A(危险透传):继承原始 XFF,只追加;客户端伪造内容会保留在列表左侧。
模式 B(安全清洗):丢弃原始传入 XFF,基于 TCP 源 IP 重建 XFF。
火山 ALB、Nginx、Ingress 都要确认开启清洗行为,默认配置很多是透传,不清洗。
结合你日志的现实问题
你的火山 API 网关拿到的 XFF:101.126.36.10, 111.48.137.138, 220.202.19.152
这些 IP 是上游各个可信节点一层层追加出来。
但是链路跳数会变:有时候 2 跳,有时候 3 跳;所以千万不要写死拦截位置下标。 ✅正确做法:网关从右向左遍历 XFF 列表,跳过全部已知可信代理 IP 段,取第一个不属于可信代理网段的 IP,作为真实客户端 IP,而不是写死第 0/1/2 位下标MDN Web Do...。
Nginx 极简示意配置(清洗 XFF)
# 定义哪些是可信代理的IP段(只信任自己的LB)
set_real_ip_from 10.0.0.0/8;
# 从TCP连接获取真实源IP,丢弃上游传来的伪造XFF
real_ip_header X‑Real‑IP;
real_ip_recursive on;
# 向下游转发时,重写XFF,只填入当前四层看到的源IP,不继承客户端传入的XFF
proxy_set_header X‑Forwarded‑For $remote_addr;
最终极简记忆
没经过可信代理清洗的 XFF = 用户可以随便填写的文本框,完全不能做安全控制。
清洗 = 扔掉客户端写的 XFF,全部改用 TCP 四层真实源 IP 重新生成 XFF。
前提约束:公网不能直连后端,全部流量必须经过可信代理,否则清洗无效。
即使清洗完成,解析 XFF 不要写死数组下标;要配置可信代理 IP 段,从右往左跳过代理 IP 拿到客户端 IP,适配链路跳数变化。