
简介这是一款面向Web安全测试人员的Burp Suite插件资源主要用于在渗透测试或访问控制验证时伪装请求源IP地址帮助规避基于IP的封禁与身份暴露适合中高级安全研究员及Burp Suite使用者扩展工具链。压缩包共12个文件包含Python核心脚本、PNG界面截图、文本测试样例及Markdown说明文档其中Python脚本为插件主功能PNG截图为运行效果与界面演示txt为测试样例md为使用说明整体仅1.09MB目录结构紧凑便于快速理解插件原理并部署使用。已有412人学习或下载。通过该资源读者可获得完整的fakeIP.py插件源码、运行效果截图、测试样例与README说明能够掌握插件在Burp Suite中的加载方式、参数配置及IP伪装逻辑并据此进行二次开发或融入自动化安全测试流程。需要特别指出IP伪装技术应在合法授权前提下使用避免违规渗透行为。1. burpFakeIP 不是改包插件是「请求身份调度器」做授权渗透测试时最常碰到的一种限制登录接口对单一 IP 做访问频控或者某个功能只开放给特定地区的出口 IP。于是你手动把 X-Forwarded-For 改成另一段地址请求放行测两分钟又被拦。burpFakeIP 就是干这个的——一个加载进 Burp Suite 的扩展按你配置的策略自动改写出站请求里的来源 IP 相关头X-Forwarded-For、Client-IP、X-Real-IP 这些让每个请求带着「新身份」出去。适合做过一段时间 Web 安全测试、或者做接口鉴权开发的工程师。注意它只能影响应用层看到的 IP改变不了 TCP 层的真实来源这一点后面会反复提到。2. 服务端为什么认一个客户端可控的头XFF 信任链与 burpFakeIP 的改写原理2.1 X-Forwarded-For 的本职工作与「信任错位」X-Forwarded-For以下简称 XFF头最初的定位是让处于反向代理后面的源站知道真实客户端 IP。典型链路是客户端 → CDN → Nginx → 应用服务Nginx 在转发请求前会把 CDN 从 TCP 连接里拿到的真实 IP 追加成X-Forwarded-For: 客户端IP后端程序读这个头做日志、审计、频控。问题在于这个头是纯客户端可控的。当客户端绕过 CDN 直连源站时它自己往请求里塞一个X-Forwarded-For: 1.2.3.4服务端如果无脑信任就会把 1.2.3.4 当成来源。burpFakeIP 利用的正是这种信任错位。说得更直白一点任何来自客户端的头都属于不可信输入源站只要没配置real_ip_recursive、没把关口放在网关层应用层看到的 IP 就是可以伪造的。这不是工具钻了什么黑匣子漏洞而是服务端自己选择了信任。2.2 burpFakeIP 的拦截模型挂进 IHttpListener 的请求流水线Burp Suite 的扩展体系里有一个面向所有代理流量的监听接口IHttpListener。扩展注册这个监听器之后每次请求经过 Burp包括 Proxy、Repeater、Intruder、Scanner都会触发一次回调。burpFakeIP 做的就是在回调里把请求头摘出来找到或插入伪造 IP 相关的头再用 Burp 提供的buildHttpMessage重新组装请求替换回去。关键点在于这个操作发生在请求离开 Burp 之前、到达目标服务器之前所以目标是感知不到 Burp 存在的。整个改写过程是在内存里做的不改动磁盘上的原始请求文件也不影响 Burp 自己的请求历史记录——你仍然能在 HTTP History 里看到原始报文和改写后的报文对比。这也是它比「把请求导出改完再重放」高效的原因你可以一边浏览、一边测试、一边让每个请求自动换 IP。2.3 为什么这事不交给 Burp 内置的 Match/Replace有人会问Burp 的 Match/Replace 功能也能做字符串替换为什么还要装扩展因为 Match/Replace 只能做静态或正则替换生成不了动态 IP。你可以把X-Forwarded-For: 1.2.3.4替换成X-Forwarded-For: 5.6.7.8但没法做到「每个请求换一个 IP」或者「每三个请求轮询一次 IP 池」。要在替换规则里写脚本逻辑Burp 需要依赖 Jython 或 JRuby 扩展这本质上就是在写一个自定义扩展。另外Match/Replace 是站在流量层面做盲替换它不会判断当前请求是否已经有 XFF 头、是否被 CDN 追加过、是否还有 Client-IP 头。burpFakeIP 这一类扩展则会把「头存在就改、不存在就插、多个头同时改」这个逻辑内置避免改完 XFF 忘了 Client-IP导致服务端读取顺序错位。用句行话说扩展管的是「语义」Match/Replace 管的是「字符串」后者在动态 IP 场景下明显不够用。3. 加载 burpFakeIP 到 Burp Suite扩展安装与三组关键参数3.1 从 master.zip 到可加载扩展Jython 环境与扩展加载从标题里的master.zip可以看出你拿到的是源码压缩包解压后通常是一个项目目录加一份 README里面是扩展源码而不是编译好的 jar。这类扩展绝大多数用 Python 写依赖 Jython 环境加载。加载路径如下下载 Jython 2.7.x standalone jar不要用 Jython 3Burp 对它的支持一直不稳定。打开 Burp Suite进入 Extender → Options在 Python Environment 一栏选择刚下载的 jython-standalone.jar。进入 Extender → Extensions点 AddExtender Type 下拉选 Python。选中解压目录里的主文件一般是burpFakeIP.py或项目根目录下的同名 py 文件。点 Next观察 Output 面板有没有报错。加载成功后Extensions 列表里会出现扩展名右侧 Output 通常会打印配置说明。如果是 Java 编写的版本Extender Type 选 Java 直接加载 jar 即可。区别在于Python 版本能直接改代码改完在扩展列表里点 Reload 就能生效适合边测边调Java 版本需要重新编译相对更稳但迭代慢。对绝大多数测试场景先跑 Python 版本就够了。提示加载报错里最常见的两类是ModuleNotFoundError和ClassNotFoundException。前者说明脚本里引用了缺失的依赖模块先看 README 有没有额外的库要装后者说明 Jython 版本和扩展要求不一致尽量换成 README 里指定的 Jython 版本。3.2 请求头声明XFF 之外还该改哪些头先明确一点服务端取「客户端 IP」不是一个标准动作各家框架的实现千差万别。常见的读取顺序是X-Forwarded-For优先但也有不少后端框架先看Client-IP或X-Real-IP。所以 burpFakeIP 这类扩展通常提供一个头列表默认勾选 XFF其他头按需开启。我一般会开的头如下头名作用建议X-Forwarded-For最通用的代理转发头CDN、Nginx、Spring Boot 都认必开Client-IP部分 PHP 框架和旧的负载均衡器使用强烈建议同开X-Real-IPNginx 的proxy_set_header常用写法同开X-Originating-IP一些邮件网关和历史遗留系统使用按目标情况开ForwardedRFC 7239 标准化头新系统偶尔读这个拉满时开容易引起 WAF 注意配置时注意服务端如果只取第一个头的值那这几个头保持同一个伪造 IP 即可如果服务端会在代码里拼接多级链比如XFF: 1.1.1.1, 2.2.2.2表示经过了多级代理那就要考虑提供多 IP 的格式。具体哪一种取决于目标系统的代理链路没有统一的正确答案。先单 IP 跑通再根据业务日志微调。3.3 IP 生成策略随机、自增、固定 IP 池怎么选动态生成伪造 IP 不是随便拿个随机数拼出来就完事。burpFakeIP 一类的扩展通常支持三种生成策略完全随机每次请求生成一个公网段合法 IP。优点是适合快速绕过简单频控缺点是如果目标服务端会做 IP 地理信息分析随机到异地 IP 反而触发风控。固定池轮询在配置里写死一个 IP 列表扩展按顺序或随机取。适合模拟固定出口节点场景也是我个人的首选。比如目标只放行了特定国家的 IP就把当地云服务商的一段 IP 放进池子里轮换比完全随机可控得多。固定 IP 保持在某个会话内保持同一个 IP直到手动重置。这个最贴近真实用户行为适合测试会话保持类逻辑比如登录后 IP 频繁变化是否会导致会话失效。生成时要做的关键处理是过滤保留网段。10.0.0.0/8、172.16.0.0/12、192.168.0.0/16这些私网段加上0.0.0.0/8、127.0.0.0/8、169.254.0.0/16、224.0.0.0/4组播段都要从随机范围内排除。否则伪造 IP 落入内网段目标服务的中间设备可能把它路由到内网黑洞表现就是请求超时或连接被重置——这是后续避坑章节的重点。3.4 最小可运行骨架一个能改写 XFF 的 Burp 扩展代码理解了原理之后哪怕 burpFakeIP 这个项目有问题你也可以自己花十分钟写一个最小可用版本。下面是一个能跑通基本流程的骨架基于 Jython 2.7from burp import IBurpExtender, IHttpListener class BurpExtender(IBurpExtender, IHttpListener): def registerExtenderCallbacks(self, callbacks): self._callbacks callbacks self._helpers callbacks.getHelpers() callbacks.setExtensionName(burpFakeIP-lite) callbacks.registerHttpListener(self) print([*] burpFakeIP-lite loaded) def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # 只处理出站请求响应直接放行 if not messageIsRequest: return request messageInfo.getRequest() analyzed self._helpers.analyzeRequest(request) headers list(analyzed.getHeaders()) body analyzed.getBody() fake_ip 203.0.113.7 # 测试用假 IP换成你的目标地址段 new_headers [] inserted False for header in headers: if header.lower().startswith(x-forwarded-for): # 已存在 XFF 头替换值 new_headers.append(X-Forwarded-For: fake_ip) inserted True else: new_headers.append(header) if not inserted: # 不存在则追加新头避免服务端只认第一个头时读不到 new_headers.append(X-Forwarded-For: fake_ip) # 用 buildHttpMessage 重建请求保证 Content-Length 自动更新 new_request self._helpers.buildHttpMessage(new_headers, body) messageInfo.setRequest(new_request)逻辑说明analyzeRequest把原始请求拆成头部和 body遍历头部时逐一比对大小写不敏感的键名。找到 XFF 就替换找不到就追加。最后buildHttpMessage是关键——它会重新计算 Content-Length如果手动拼接请求字符串一旦 body 里有非 ASCII 字符或压缩内容长度对不上就会 400。这里的fake_ip是写死的单 IP实际使用时要抽成配置项从扩展 UI 或配置文件读取。注意这个骨架只处理了 XFF要支持 Client-IP 等更多头把 for 循环里的判断条件换成集合对集合内每个头名走同样的替换逻辑即可。4. burpFakeIP 避坑清单5 个「改完头仍然翻车」的真实场景4.1 只改 X-Forwarded-For服务端却取 TCP 层真实 IP现象扩展正常加载代理流量也确实是带着新 XFF 头出去的但目标的频控逻辑照样把你拦截了日志里记录的来源 IP 依然是你本机的出口 IP。原因服务端并不总是信任 XFF。很多云 WAF、负载均衡器会在接入层配置proxy_protocol或直接读取$remote_addr应用层拿到的 IP 根本不是你伪造的那个。换句话说目标从 TCP 层取 IP应用层改什么都白搭。解决先确认目标是否有 Nginx 的real_ip_header X-Forwarded-For这类显式配置或 WAF 策略里有没有「信任 XFF」选项。如果对方只在接入层取 IPburpFakeIP 做不到绕过——你需要的是在本地起一个真实代理让目标看到的 TCP 来源变成代理的 IP。常见做法是本地跑 Squid 或 Nginx 四层转发把 Burp 的出站流量指向它再配合 burpFakeIP 做应用层双保险。这已经超出扩展本身的能力边界属于网络层方案。4.2 随机 IP 踩中保留地址请求超时或进黑洞现象开启完全随机策略后部分请求出现超时、连接重置刷新几次又恢复正常没有固定规律。原因随机算法生成了私网段或保留段地址。比如10.x.x.x、192.168.x.x目标网络内部的负载均衡或防火墙看到来源是内网段按内网路由处理把包转发进了内网、找不到回程路由于是请求石沉大海。0.0.0.0 和 255.255.255.255 这类地址更是直接触发中间设备的过滤规则。解决不要用完全随机。把 IP 池收敛到几百个公网段地址哪怕是脚本生成的连续段也要先排除全部私网、组播和保留段。如果你不确定一段 IP 能不能用先拿 curl 带-H X-Forwarded-For: 该IP打一个连通性测试接口确认目标能正常返回再放进池子里。这个验证成本很低比在 Burp 里反复重发请求划算。4.3 多级 XFF 链上服务端取了「最后一跳」改了也白改现象你设置了X-Forwarded-For: 1.1.1.1请求正常通过但目标系统的业务日志里记录到的来源 IP 不是 1.1.1.1而是链路里某一个代理的真实 IP或者干脆是空。原因部分框架解析 XFF 时不是取第一个值而是取链上最后一个「可信任代理」之前的值。比如链路是客户端 → Nginx → 应用Nginx 会追加一层变成XFF: 1.1.1.1, Nginx内网IP。如果应用配置了real_ip_recursive on且把 Nginx 内网 IP 视为可信代理它就会继续往前找 1.1.1.1这是正确的但如果配置里可信代理列表为空它可能直接取最后一个 IP也就是 Nginx 自己的内网地址。解决先做一次探测——用一个真实代理链请求目标看日志里最终记录的 IP 是 XFF 的哪个位置据此调整伪造的 XFF 链。常见做法是伪造两个 IP如X-Forwarded-For: 203.0.113.7, 203.0.113.8把第一个当最终来源、第二个当「代理」。多测试几种格式找到服务端真正读取的那一位比盲目加头更有效。4.4 Jython 版本不兼容扩展加载就报 ClassNotFound现象单击 Add 后Extensions 列表里出现了条目但状态是Errors下方报错堆栈里有java.lang.ClassNotFoundException或ImportError。原因Jython 2.7.x 有几个补丁版本部分扩展依赖collections或typing模块在旧版不存在。另一个常见原因是 Burp 本身自带的 JRE 版本过新与老 Jython 的字节码生成逻辑冲突。解决固定 Jython 版本不要用最新的。我一般保留jython-standalone-2.7.3.jar和jython-standalone-2.7.2.jar两个文件加载失败就切换重试。Burp 里切换只需在 Extender → Options 重新选择 jar 路径然后 Reload 扩展即可。这个玄学问题不常见但碰上一次就够折腾半小时。4.5 扩展对所有工具生效把正常流量也改了现象burpFakeIP 开着的时候用 Burp 自带浏览器访问正常的业务站点结果登录、支付等功能全部报安全校验失败甚至出现用户状态错乱。原因注册IHttpListener时没有过滤工具类型导致 Proxy 流量也被改写。这不是扩展 bug而是很多扩展默认全流量生效的设计。正常浏览时带一个伪造的 XFF目标站点的风控会直接弹出验证码或拒绝服务。解决把改写范围限定到需要的工具。常见做法是在processHttpMessage里判断toolFlag只对callbacks.TOOL_REPEATER或callbacks.TOOL_INTRUDER生效不动TOOL_PROXY。如果扩展没有这个开关就在 Burp 的 Scope 里把目标站点限定为测试域名让请求只在匹配 Scope 时经过扩展逻辑。这样正常上网的流量走你自己的真实 IP 出去只有测试流量才带伪造身份。5. burpFakeIP 进阶配 Intruder、会话规则与日志里验证真伪5.1 配合 Intruder 做 IP 轮换的批量测试单请求改 IP 只是入门真正有价值的是把 IP 轮换和 Intruder 的攻击载荷结合使用。典型场景目标登录接口每 IP 每分钟允许 5 次尝试。你在 Intruder 里放密码字典同时在扩展配置里勾选「每个请求换 IP」Intruder 每发一个包扩展自动生成一个新 IP 头。这样从目标视角看攻击来自几十个不同 IP。实现上不需要改 Intruder 的位置标记载荷类型设置为空把所有参数都放在 payload 列表里让扩展负责 IP。注意一点Intruder 自带的重发机制不会重放已生成的请求但如果你开了Recursive Grep或Resource Pool的延迟控制IP 轮换的频率会受线程数影响建议先用单线程跑通再调并发。批量测试结束后务必核对扩展日志里每个请求对应的 IP确认没有重复或落入保留段。5.2 用 Session Handling 规则固化「改头 重放」Burp 的 Session Handling Rules 可以把扩展的改头动作固化成一条规则配合宏一起执行。典型链路是目标系统有登录态 Cookie 有效期限制你希望在 Cookie 刷新后自动重放之前的请求同时保持 IP 身份不变。做法是在 Session Handling Rules 里新增一条规则指定为「Invoke a Burp extension」选 burpFakeIP 对应的扩展名规则作用域限定在目标测试域。这个组合的好处是宏观的登录态维持交给 Burp 的宏微观的 IP 身份交给扩展两者互不干扰。比如宏刷新 Cookie 后重放请求时扩展不会重新生成 IP从而保持同一个身份会话。如果希望刷新 Cookie 时也换 IP就在宏步骤里额外加一个「重置扩展状态」的请求。这类细节决定了测试结果的可复现性值得先想清楚再动手。5.3 在业务日志与响应头里验证服务端到底取信了谁改头成功不等于目标读取成功这两件事经常被混为一谈。验证手段有两种。一种是看响应头部分框架会在响应里回显来源 IP比如X-Client-IP: 203.0.113.7或调试模式下把服务端解析到的 IP 写入响应体。另一种是看业务日志把目标系统里和该请求相关的 access log、业务操作日志拿出来对照当时发出的伪造 IP。我习惯在测试前先发一个GET到目标的一个无状态接口比如/api/health然后在响应头和返回 JSON 里找ip、addr、client_ip字段。如果找不到就发到/api/debug这类调试接口。确认服务端取的是 XFF 之后再继续后续测试。否则前面所有伪造都是自我感动测出来的结论全部无效。6. 最后落地本地搭 Nginx 回显验证 burpFakeIP 到底改没改成功在打真实目标之前先花五分钟在本地把整个链路验证一遍。Nginx 配一个回显接口把服务端能看到的 IP 相关头全部打印出来Burp 代理指过去一测便知扩展有没有生效、服务端取的哪个头、格式对不对。Nginx 配置如下server { listen 8088; location /echo { default_type text/plain; return 200 remote_addr$remote_addr\nx_forwarded_for$http_x_forwarded_for\nx_real_ip$http_x_real_ip\nclient_ip$http_client_ip\n; } }启动 Nginx 后先直接用 curl 访问一次不经过 Burp确认拿到的是本机出口 IP再在 Burp 里把 Repeater 的目标指向127.0.0.1:8088手动加一个X-Forwarded-For: 203.0.113.7发出去响应里的x_forwarded_for应该是203.0.113.7。这个测试如果通了说明 Burp 的请求改写链路没问题。再打开 burpFakeIP关掉手动加头重新发请求看x_forwarded_for是否自动变成扩展生成的 IP。我自己第一次用这类工具时就翻过车扩展加载正常、请求历史里也能看到新 XFF 头但真正打目标时频控照样拦我。后来才发现目标服务端取的是Client-IP头而我只开了 XFF。从那以后我养成了一个习惯——先用本地回显环境把所有要改的头全部验证一遍再上真实目标。这个习惯帮我省下了大量跟目标系统「猜需求」的时间。希望帮到你。本文还有配套的精品资源点击获取