BurpFakeIP插件实战:伪造X-Forwarded-For头调试接口与限流策略

发布时间:2026/10/1 14:16:42
BurpFakeIP插件实战:伪造X-Forwarded-For头调试接口与限流策略
简介面向 Burp Suite 用户的开源 IP 伪装插件包现已在 GitHub 上公开分享主要用于 Web 应用安全测试与授权渗透测试。插件通过修改请求的源 IP帮助测试者在授权评估中隐匿真实身份、模拟不同地域用户并验证服务端基于 IP 的访问控制策略适合已掌握 Burp Suite 基础操作的安全研究员、红队成员进一步提升测试灵活性与隐蔽性。压缩包共 12 个文件核心为 Python 编写的 fakeIP 插件脚本另附 README 说明文档、测试文本和 9 张界面效果截图整体大小仅 1.09MB目录清晰便于对照阅读与二次开发。目前已有 412 人学习下载。借助完整源码与截图读者可快速理解 Burp Suite 扩展 API 的调用方式、IP 伪装的实现原理及请求头构造细节也可观察插件在实际请求中的表现随包文档记录了配置要点和测试效果遇到问题时可参考排查在合法合规的前提下让安全测试更高效、更隐蔽。1. 伪造 IP 头调通接口burpFakeIP 插件到底在帮你解决什么下午三点前端同事说测试环境的订单接口又返回数据为空本地联调明明一切正常。查参数、对鉴权、开断点折腾了半天最后发现网关层针对 X-Forwarded-For 做了限流和区域策略你的请求头带着本机地址直接被拦在门外。burpFakeIP 是 GitHub 上开源的 Burp Suite 扩展插件它在 Burp 把请求发出之前按你预设的规则改写或追加 X-Forwarded-For、X-Real-IP、Client-IP 等头字段把每次手动改 header 的活儿自动化。装好后大约十分钟能跑通全流程适合做接口联调、开发自测、验证网关限流逻辑的开发者和测试工程师。它不是用来钻合规空子的我只建议在你自己负责的测试环境和联调环境里使用。2. 它到底改了哪些头IP 字段、介入时机与执行顺序2.1 三个关键字段谁在读、读哪个网关、负载均衡、WAF 和业务应用判断客户端来源时优先级最高的就是 X-Forwarded-For、X-Real-IP、Client-IP 这三个字段。X-Forwarded-For 是 RFC 标准里定义的转发链记录每经过一层代理就追加一个 IP格式上存在“逗号分隔多值”的情况也是后端程序最爱取的一个。X-Real-IP 是 Nginx 系网关在 proxy_set_header 里手动指定的字段业务侧拿$http_x_real_ip读取很多老项目只用它不用 XFF。Client-IP 是部分云厂商和自研网关的私有约定读取概率相对低一些。写插件的时候要考虑的不是“能写哪个”而是“上线环境读哪个”。我见过不少团队把伪造的 IP 只写进 X-Forwarded-For恰好后端取的是 X-Real-IP最后请求还是被限流。burpFakeIP 的配置文件里允许对每个字段单独开关你需要在联调前先问清楚网关侧到底读哪个字段然后把对应的字段开关打开其余保持默认关闭。2.2 插件介入的时机请求发出前的那一瞬间Burp 扩展通过实现IHttpListener接口来拦截流量processHttpRequest方法会在请求构造完成后、真正发往服务器之前被调用一次burpFakeIP 的改写逻辑就挂在这里。常见做法是先遍历当前请求头列表逐行匹配目标字段名存在就把原值整体替换成规则里的新 IP不存在就在请求头末尾追加一行。这个执行顺序非常重要它是“先遍历、后追加”而不是“无脑往尾部塞”因为 Java 的 Header 集合允许同名键存在如果不知道先清理旧值就追加会出现两个 X-Forwarded-For。配合 Burp 的调试窗口观察你能明确看到每个请求出站前的头列表顺序。加载插件后随意发一个请求在 Burp 的 Proxy History 里选中该条记录切到 Headers 标签页就能看到被改写后的完整头集合。如果发现重复字段或值不对问题要么出在规则没命中要么出在执行顺序上这两点在后面避坑章节还会详细展开。2.3 IP 值怎么写才不会被网关一眼看穿很多新手直接填1.1.1.1或者127.0.0.1这在开发环境里能跑通但一旦网关侧做了基础的 IP 合法性校验就会直接把这类明显异常的地址拦掉。比较稳妥的做法是使用内网网段里看起来“真实”的地址比如10.12.3.4、192.168.10.20或者使用目标服务所在地理位置的公网段。另外要注意 IPv4 和 IPv6 的格式差异部分网关对格式做了强校验IPv6 地址必须写成完整的冒号分隔形式。burpFakeIP 支持在配置里自定义地址格式模板你可以把地址池写成一行一个 IP 的文本文件也可以直接配置一个 CIDR 段让插件随机生成。格式上我一般会配置成“点分十进制、标准端口直连、不带前缀”的写法避免因为格式不符合解析逻辑导致网关直接 400。值越接近真实流量调试越省事。3. 把 jar 装进 Burp编译、Loader 与配置面板逐个拆3.1 从源码到 jar 包一条命令完成编译项目下载解压后是一个标准的 Maven 工程目录结构与常见的 Java 插件项目一致包含src/main/java源码目录、pom.xml依赖描述和资源文件。编译前先确认本机已安装 JDK 8 以上版本和 Maven 3.6 以上版本两个环境变量配好后终端进入项目根目录直接执行cd burpFakeIP-master mvn clean package -DskipTests参数clean会清掉上一次的编译产物避免增量编译导致的 class 残留package负责把源码打成可分发 jar 包-DskipTests跳过单元测试以节省编译时间。编译完成后在target目录下会生成一个burpFakeIP-x.x.x-jar-with-dependencies.jar这个带依赖的胖包才是 Burp 加载时真正需要的文件。如果执行过程中报依赖下载失败大概率是 Maven 中央仓库连接超时。常见做法是换成阿里云镜像源修改~/.m2/settings.xml在 mirrors 节点追加mirroridaliyun/idurlhttps://maven.aliyun.com/repository/public/url/mirror再重新执行上面的命令。装完后看target目录里 jar 文件是否完整生成这一步没问题再进入下一步。3.2 装进 ExtenderLoader 与 jar 的依赖关系Burp 加载扩展的地方在 Extender 标签页你可以点击 Add 选择刚才编译好的 jar。初次加载容易踩的坑是只选主 jar 而忽略依赖 —— 虽然刚才打的包叫 jar-with-dependencies但如果用mvn package没生效或者下载的是 release 里的瘦包运行时就会报NoClassDefFoundError。稳妥的加载方式是把主 jar 和pom.xml里声明的依赖逐一挂进 Loader 列表这一步跟 Firefox 加载临时扩展类似不需要签名选对文件就能用。加载成功后 Extender 的表格里会出现burpFakeIP一行右侧 Extensions 信息面板能看到加载状态。我的习惯是加载后先随便发一个请求确认没有异常堆栈再往下配置。这个验证动作能节省大量排错时间因为扩展加载失败时 Burp 的界面不会弹任何强提示只会把这个错误安静地记在 Output 标签页里。3.3 配置面板每个输入框是干什么的插件安装后Burp 的 Tab 栏会多出一个名为 burpFakeIP 的面板。面板上最常见的配置项包括 IP 格式、地址池路径、启用开关和域名字段。配置项作用常见值Format控制 IP 生成格式single / random / round_robin / fileIP Pool直接填 IP 或引用外部文件10.12.3.4 或 /path/ip_pool.txtTarget Host限定只对哪些域名生效.*\.test\.corp\.comHeader Types要改写的目标头字段X-Forwarded-For、X-Real-IP、Client-IPEnabled全局总开关true / falseFormat 和 IP Pool 这两个字段要配合使用Format 选 single 时 IP Pool 只取第一个值选 random 时从整个池随机挑一个选 round_robin 时按顺序循环使用。Target Host 支持正则表达式空着表示对全部请求生效这个值我强烈建议一定要填否则会把线上域名的请求也一并改写。3.4 落一份 config.json按域名分组管理规则配置面板改完是即时的但它存在 Burp 的会话配置里重启后可能丢失。更可靠的方式是把规则写进项目的config.json这份文件会在插件初始化时自动加载。典型结构如下{ default: { enabled: false, ip_format: random, ip_pool: [] }, rules: [ { match: .*\\.test\\.corp\\.com, enabled: true, ip_format: round_robin, ip_pool: [10.12.3.4, 10.12.3.5, 10.12.3.6] } ] }default配置段负责兜底enabled设成 false 意味着不匹配任何规则的请求保持原样这个设计能有效保护线上流量。rules数组里每一项代表一个独立策略match字段是正则表达式命中后使用该分组下的 IP 池和格式。插件会按数组顺序逐一匹配第一个命中的分组生效后续规则不再处理。配置完保存文件后在插件面板点一下 Reload 让配置重新生效。一个容易忽略的细节是config.json必须使用 UTF-8 编码保存Windows 记事本默认的 GBK 编码会导致正则里的中文字段乱码匹配直接失效。4. 从固定 IP 到多 IP 轮播四种 IP 池策略与按域名分流4.1 固定、随机、轮播、文件导入四种策略怎么选四种 IP 池策略适用场景完全不同选错了轻则调试无意义重则把脏数据写进日志。策略适用场景关键特征single验证某个固定 IP 的限流阈值所有请求同一地址random模拟大量不同来源每次请求随机抽一个round_robin模拟有限几个节点轮询按顺序循环file从外部文件批量导入自定义地址池支持几千行大文件单 IP 模式适合快速验证“从 A 地址访问会被拒绝”这种确定性场景random 模式则适合压测时模拟海量用户来源但要注意随机命中同一 IP 的概率会随着请求量上升而变大round_robin 最适合模拟多节点服务比如你有 5 台后端服务器就配 5 个固定 IP 轮询行为稳定且可预期。外部文件模式是最灵活也最麻烦的灵活在于地址池可以随便换麻烦在于文件读取的路径环境不一致。插件读取时如果用的是相对路径会导致 Burp 在其他目录启动时找不到文件规则静默失效。我一般把 IP 池文件放在与config.json同级的绝对路径下并用Config 目录绝对路径 文件名的方式引用。4.2 用脚本生成两百个不重样的随机 IP没有现成 IP 池文件时可以临时用脚本生成一批随机地址。需要注意避开网络号和广播地址最简单的做法是把最后一段控制在 1 到 254 之间import random for i in range(200): ip ..join(str(random.randint(1, 254)) for _ in range(4)) print(ip)这段脚本生成 200 行点分十进制地址每行一个可以直接作为ip_pool.txt供插件读取。随机范围控制在 1 到 254 能有效避开网络号、广播地址以及常见的0结尾保留段作为联调用已经足够不需要再纠结子网掩码这类细节。生成后可以用sort -u去重重复的 IP 在随机模式里会降低池的有效多样性在轮播模式里则会导致同地址连续出现两次影响模拟真实度。4.3 按 Host 分流只影响测试域不污染线上请求这是整个插件配置里最容易被跳过的一步。很多人在面板里填完 IP 池就开测结果把线上请求也带着假 IP 发了出去后端的限流判定和安全审计全被干扰。正确做法是给线上域名配一条显式的“不处理”规则再让测试域名的规则覆盖它但要注意规则是“第一个命中即生效”的。一个严谨的配置顺序是第一条规则匹配生产域名enabled设为 false 并留空 IP 池第二条规则匹配测试域名启用 random 或 round_robin。这样生产请求在第一条规则处被拦截不会继续落入后续的伪造逻辑。正则表达式中的点号要转义corp\.com和corp.com的语义完全不同前者只匹配字面点号后者能匹配任意字符容易误伤其他域名。5. 避坑五个埋得最深的坑和排查思路5.1 现象后端日志里拿到的还是真实 IP伪造完全没生效原因绝大多数情况是规则里的正则没匹配上目标请求的 Host插件直接放了原始请求通过。其次是网关侧开启了real_ip模块或者前面的 CDN 层无条件覆盖了 XFF 头。解决先在插件面板把 Target Host 留空发一个测试请求确认头字段确实被改写确认无误后再把限定域名加回来。如果留空后仍不生效则改用 curl 手动指定 XFF 观察后端返回定位是否是网关层重写了头部。5.2 现象加载扩展时 Output 标签报java.lang.NoClassDefFoundError原因使用了瘦 jar 而非 jar-with-dependencies运行时找不到 commons-codec 等第三方类。解决检查 Extender 的 Loader 列表里是否把所有依赖都挂上了。最常见的做法是直接用target目录下带-jar-with-dependencies后缀的完整包而不是项目根目录下其他位置的旧 jar。换包后重启 Burp 再加载一次如果还有类似错误用jar tf查看包内是否存在对应的 class 文件。5.3 现象zip 包下载后解压多套了一层目录编译时路径找不到原因部分平台打包 zip 时会把顶层目录也包进去解压后出现burpFakeIP-master/burpFakeIP-master/两层嵌套。解决解压时注意观察顶层目录名若发现套娃把内层目录整体移动到工作目录。另外 jar 本质就是一个 zip你甚至可以理解成一种 zip 伪加密结构看起来正常但内部 class 可能被混淆或压缩过。检查 jar 是否可读用jar tf burpFakeIP.jar列出条目确认能看到com/github/burp/fakeip/Main.class之类的入口类。5.4 现象请求头里出现了两个 X-Forwarded-For网关取最后一个还是第一个全凭玄学原因插件执行“先遍历后追加”的逻辑是覆盖已有值但多个 Burp 扩展同时注册 IHttpListener 时监听器的调用顺序不受控制另一个插件可能又追加了一个 XFF。解决在 Proxy History 里查看原始请求确认是哪个环节多加的头。排查时禁用其他扩展再发一次请求如果头恢复正常就说明是插件间冲突而不是 burpFakeIP 自身的问题。网关侧对重复头字段的取值行为各不相同有取最左的也有取最右的耦合起来极难排查最好的结局是别让重复头出现。5.5 现象测试做完忘了关策略第二天上班线上告警原因插件在配置面板里开的 enabled 开关是全局的Target Host 留空时会对所有经过 Burp 的请求生效。Burp 退出后再启动旧配置还保留着而你可能完全不记得这个开关是开着的。解决每次结束联调前把面板上的全局总开关拨回关闭状态或者在config.json里把default.enabled设为 false。从那以后我给自己定了一条死规矩关 Burp 之前多花十秒检查一下插件状态这个习惯帮我挡住了至少三次线上事故。伪造 IP 头是条单行道请求一旦到达后端日志里留的就是假 IP它没有后悔药可吃你后期对账查不到任何真实来源只能靠客户端日志反推。6. 最后做一次完整验证从请求头到后端日志的闭环规则配好、插件加载成功后不要直接进业务测试先花三分钟走一轮验证流程确认链路里每个环节都认这个伪造的 IP。先在终端里用 curl 对比一下一条带上伪造头一条不带观察后端返回是否出现差异。curl -i -H X-Forwarded-For: 10.12.3.4 http://test.corp.com/api/order/list curl -i http://test.corp.com/api/order/list如果两条请求的返回完全一致要么是当前接口根本不走 IP 策略要么是网关校验了更底层的连接地址。不要把这两条命令的结果当成“插件没用”它只能证明这个特定接口不依赖 XFF。接着在 Repeater 里手动构造一次请求观察 Burp 在出站前是否按规则改写了头再切到插件面板确认命中的规则分组面板会标记当前请求命中了哪条规则这是一个很直观的定位手段。验证的关键一步是去后端日志确认在测试环境找到对应时间的 access log 或应用日志搜索10.12.3.4这个地址确认后端确实把它当成了客户端来源。这一步做完整个链路才算真正打通。很多人只验证了“Burp 发出了假头”就以为大功告成恰恰漏了链路最末端的那一环。有一个值得养成的习惯不要在 Burp 开着插件策略的状态下切到日常工作流。联调结束后强制把config.json里 default 分组恢复成初始状态并确认所有规则组的 enabled 都是 false。这个动作看起来多余但能避免“第二天登录线上后台发现所有请求都带着上次遗留的 IP 池”的尴尬。希望这份笔记能帮到你至少让你少走一次我走过的弯路。本文还有配套的精品资源点击获取