Wireshark解密ESP协议:从识别IPsec包到还原内层流量实战指南 如果你做网络排障够久多半会遇到这么一种情况明明业务抓到的全是IP包却偏偏有好几屏看着像乱码的ESP包。翻半天抓包文件只能看个SPI和Sequence其他全是Encrypted。别慌这不是你的抓包姿势出了问题而是流量在离开源主机的那一刻就被ESP协议套上了一层加密外壳。这篇文章要聊的就是Wireshark里的ESP——Encapsulating Security Payload封装安全载荷。它是IPsec协议族里负责“加密完整性保护”的协议在网关对网关的加密通信场景里极其常见。很多朋友一看到ESP就懵一是因为字段看不懂二是就算看到了也解析不出内层内容。我尽量用一篇完整的实战笔记讲清楚三件事ESP包在Wireshark里怎么识别、如何判断封装方式、以及在有密钥的前提下怎么把它解密还原成普通IP/TCP流量。适合正在学IPsec、做网络排障、或者对协议分析有兴趣的读者。1. 先弄清楚ESP它到底把什么“封装”了1.1 协议栈里的50号和“加密”的身份在IP协议栈里每个上层协议都有一个协议号。我们熟悉的ICMP是1TCP是6UDP是17而ESP的协议号是50。也就是说当一个IP包的IPv4头里protocol字段是50接收方就知道这个包的载荷不是普通的TCP或UDP数据而是经过ESP封装后的密文。这里有个关键点ESP不是一个独立的应用层协议它工作在网络层。它干的事情可以理解成对原始IP数据报做了“加密封装”——把原始报文整体或者只包住传输层及以上部分当作加密输入外面再套上自己的头和尾。这样一来中间设备或者抓包者能看到的是一个普通的IPv4/IPv6包协议号是50后面跟着一串无法直接阅读的密文。这就是为什么Wireshark打开pcap文件后你会看到整屏整屏的ESP却完全不知道里面跑的是什么业务。从使用场景上讲ESP最常出现在两个安全网关之间建立的IPsec隧道中。客户端和服务器之间的往返流量经过网关时被ESP封装到达对端网关后再解封装还原。所以你在链路中间抓包看到的往往就是“IP头 ESP头 Encrypted Payload”这种结构。理解这一层后面看字段才不费劲。1.2 不看密钥也能读懂的ESP头很多人以为ESP整个包都是不可读的其实不对。ESP头本身有两部分字段是明文传输的SPISecurity Parameters Index安全参数索引和Sequence Number序列号。SPI是一个4字节的整数它本质上是接收方用来查找“安全关联”的索引号。每一条IPsec安全关联SA都会有一个唯一的SPI通信双方靠它来匹配对应的加密算法、密钥和生命周期等参数。所以在抓包里看到SPI它本身不泄露任何业务数据但它相当于一把钥匙的编号——只要你知道这个编号对应的SA参数就能用它来解密对应的包。Sequence Number也是4字节作用是防重放。发送方每发送一个ESP包序列号就递增接收方通过滑动窗口机制检查序列号是否在合理范围内如果发现重复或回退的序列号可以直接判定为重放攻击并丢弃。这个字段对排障同样有用比如你怀疑网络丢包看同一方向ESP包的序列号是否连续跳跃就能得到线索。真正被加密的部分是从Sequence后面的载荷区域开始的。整个加密区域一般包含可选的IV初始化向量、实际业务数据原始IP包或上层报文、填充字段Padding、填充长度Pad Length以及下一个头Next Header。这些内容在解密之前Wireshark统一显示为“Encrypted Payload”。填充字段的存在是为了满足块加密算法对数据长度的要求比如AES的块长度是16字节原始数据不够长就要补足同时填充也能掩盖真实载荷的精确长度算是一个小小的安全设计。1.3 ESP与AH一对容易被搞混的兄弟讲ESP的时候总绕不开AHAuthentication Header认证头。这两个都是IPsec框架里的协议但职责完全不同。AH的协议号是51它只做完整性校验和源认证不提供加密。换句话说AH能保证数据在传输过程中没有被篡改但内容本身是明文的抓包如果没被ESP包裹是可以直接看到内层TCP头的。而ESP同时提供机密性和完整性保护。根据你配置的安全套件ESP可以选择只加密、只认证也可以使用AEAD算法比如AES-GCM把加密和完整性校验合并完成。现在的实际环境中绝大多数场景用的都是ESPAH已经很少单独出现。用表格总结一下区别对比项ESP封装安全载荷AH认证头协议号5051机密性支持加密载荷不支持载荷明文完整性支持可选支持防重放支持支持保护范围不覆盖外层IP头覆盖外层IP头中可变字段外的部分抓包可见内容仅ESP头和外层IP头载荷不可读完整IP载荷可读附认证数据实际做安全分析时如果看到协议号是51重点应该看认证数据是否存在、完整性是否通过如果看到协议号是50就要做好“内容全是密文”的心理准备老老实实走解密流程。2. 在Wireshark里识别ESP从协议列开始2.1 一眼认出ESP协议列与捕获过滤器打开一个包含加密流量的pcap文件第一眼就是看Protocol列。Wireshark会把协议号50的包直接标记为ESP。如果抓包环境比较干净你会看到屏幕上刷出好几页的ESP这是最直观的识别方法。如果包特别多想快速过滤出ESP显示过滤器和捕获过滤器我建议分开记显示过滤器Display Filter用esp捕获过滤器Capture Filter用ip proto 50或ip6 proto 50捕获过滤器的作用是在抓包时就把非目标流量过滤掉减少文件体积。这个动作在现场排障时非常有用因为隧道一旦建立ESP流量往往占满整个抓包文件不加限制的话一个1GB的pcap里大部分都是无关信息。我一般习惯写成ip proto 50 or tcp port 500 or udp port 4500这里的500端口是IKEInternet Key Exchange协商流量的端口4500是NAT场景下IKE和ESP的封装端口。如果把这几类流量一起抓下来你既能看ESP加密包又能看协商阶段的信息对定位隧道建立问题帮助很大。2.2 逐个字段看一个典型ESP包随便点开一个ESP包Wireshark的Packet Details面板通常会长这样Frame: 物理帧信息Ethernet II: 源MAC、目的MACInternet Protocol Version 4: 这里能看到Protocol为50Encapsulating Security Payload: 这个节点下面就是ESP的字段展开ESP节点主要看两个明文字段Security Parameters Index: 例如0x1c45a3f7Sequence: 例如1代表这是该SA上的第一个包再往下是一个叫Encrypted Payload或者Data的字段多少多少字节点开只能看到一串十六进制密文。如果做了解密配置后面我会细说这个节点会多出几个字段比如Initialization Vector: IV值Decrypted ESP Payload: 解密后的真实数据Padding: 填充字段Pad Length: 填充长度Next Header: 内层协议类型如果是TCP就是6如果是UDP就是17如果是隧道模式下的IP-in-IP就是4一定要养成看Next Header的习惯。它直接告诉你ESP里面装的是什么是判断“传输模式”还是“隧道模式”的重要依据。2.3 判断传输模式还是隧道模式的两条线索ESP有两种封装模式排障时必须能区分。传输模式Transport ModeESP头插在原始IP头和传输层头之间只保护上层数据。外层的源IP、目的IP还是通信双方的地址没有新的IP头。这种模式一般用于端到端的通信保护。隧道模式Tunnel Mode原始IP包整个被塞进ESP的载荷里外面再套一个新的IP头。外层IP头的源地址和目的地址通常是两台网关不是真实的终端地址。这种模式在网关之间的加密隧道里最常见。在没有解密的情况下怎么判断我最常用的方法是观察三件事第一看IP头的地址和ESP封装后的载荷长度。隧道模式重新封装后整个数据包会明显变长如果原始应用数据不大外层包仍可能有几十甚至上百字节的固定开销。第二看外层IP头的src和dst是不是网关地址如果和业务终端地址不一致基本可以认定是隧道模式。第三如果抓包点两边都能抓到直接对比进出方向的IP头差异隧道模式下内层地址被隐藏进出网关前后的地址会发生明显变化。解密之后判断就更直接了。你在解密后的字段里会看到一个内层IP头如果把外层IP头的src/dst和内层IP头的src/dst做个对比两者不一样那就是隧道模式。2.4 SPI的作用解密和SA的钥匙从我自己的排障经验来说SPI的意义再怎么强调都不过分。因为ESP包的头部是明文的所以只要拿到一条SA的SPI你就能在各式各样的抓包文件里精确锁定属于这条SA的所有流量。假设你想只分析某个方向上的ESP包可以这样过滤esp.spi 0x1c45a3f7注意Wireshark里过滤SPI时记得用十六进制格式否则容易匹配不上。SPI是接收方为每条SA随机分配的标识因此通信双方各自方向上的SPI通常不同。你在A→B方向看到的SPI是B侧分配的B→A方向的SPI则是A侧分配的。这一点在小流量抓包分析时格外容易踩坑你明明只过滤了一个SPI值结果发现只有单方向上的包另外一半包丢了其实不是包丢了是SPI换了一个值。为了方便查看还可以在Wireshark列表里把SPI单独拉成一列。右键点击ESP头里的Security Parameters Index选择Apply as Column这样所有ESP包的SPI都会在列表里一目了然。之后排序、分类、对比方向效率会提高很多。3. 解密ESP让内层流量现出原形3.1 解密ESP的前提拿到安全关联参数说实话Wireshark本身是一个非常优秀的解密工具但它不是魔术师。要解密ESP流量前提是你必须拿到这条SA对应的参数。这些参数通常包括SPI值IPSec隧道的端点IP地址外层IP的src/dst加密算法比如AES-CBC、AES-GCM等加密密钥认证算法和认证密钥如果算法不是AEAD模式这些数据从哪里来正规途径有很多最常见的是从网关设备上下载或查看SA信息。在实验室环境或是在你自有设备上做协议分析也可以通过IKE协商日志导出。命令行的具体操作每家设备厂商不完全一样但思路是一样的找到SPI对应的安全关联表把key和salt摘出来填入Wireshark。这里我要特别提醒一句做任何解密分析前提是你自己拥有这些设备或者已经获得授权。对没有授权的流量做解密尝试没有任何意义也绝对不应该做。3.2 在Wireshark里配置SA并完成解密有了SA参数后配置步骤其实很简单。在Wireshark菜单栏选择Edit - Preferences。左侧找到Protocols往下拉找到ESP。在ESP协议设置里勾选Attempt to detect and decode ESP。点击Edit...按钮会打开一个管理安全关联的窗口。添加一条新SA填上前面拿到的参数。注意SPI一般填十六进制比如0x1c45a3f7加密算法选择对应的类型密钥填十六进制字符串。如果算法是AES-GCM这类AEAD模式还需要填salt。保存配置重新打开pcap文件或者直接点击Reload看ESP包是否被解析。一个容易踩的坑是安全关联是会过期的IPsec SA有lifetime限制到期后会自动重新协商。所以如果你抓包抓了很久很久中间可能经历了多次rekey那一条SA的参数就不够用了需要把整个抓包时间段内出现过的SPI和密钥都收集齐一条一条配进去。这也是为什么我建议抓包时间别太长尤其别开着抓一个通宵不然后续解密工作量会指数级上升。3.3 解密之后你能看到什么解密成功后Wireshark会把原来显示为Encrypted Payload的一整块密文替换成内层协议的完整解析。你可以直接在Packet Details面板里看到内层的IP头、TCP头甚至还能用Follow TCP Stream把这个TCP流完整还原出来。这个效果在实际排障中非常实用。有一次我排查某个网段间“偶尔慢”的问题ESB加密之后的TCP层报文在抓包里完全看不到只能看到ESP包大小、序号等信息。等我配上SA解密后马上看到内层TCP频繁出现快速重传定位到是某个中间设备的MTU问题导致的IP分片。如果没有解密只凭ESP的外部特征我可能要花两三倍的时间。再把视野拉远一点同一个原理也可以用在其他加密协议上TLS解密就是类似思路。Wireshark里只要配置对了密钥就能看到TLS解出来的HTTP明文。这篇不提TLS但方法论是一样的先识别、再找密钥、最后解密。3.4 常用tshark过滤与统计技巧很多时候你面对的抓包文件很大用图形界面一个个点效率太低了。这时候tshark就是你的好朋友。想把某个SPI的所有ESP包列出来只提取关键字段tshark -r ipsec.pcap -Y esp.spi 0x1c45a3f7 -T fields -e frame.number -e ip.src -e ip.dst -e esp.spi -e esp.seq输出会非常整齐1 192.0.2.1 198.51.100.1 0x1c45a3f7 1 2 192.0.2.1 198.51.100.1 0x1c45a3f7 2 3 198.51.100.1 192.0.2.1 0x8bd2e9aa 1 4 198.51.100.1 192.0.2.1 0x8bd2e9aa 2一眼就能看出两个方向各自用的SPI和序列号情况。如果发现某个方向上序列号突然跳变比如从100直接跳到230中间空了130个包那基本可以判定这段网络出现了明显丢包。做流量统计时我偶尔会用-z io,stat快速看一眼形tshark -r ipsec.pcap -q -z io,stat,0这能直接输出抓包时间范围内的流量速率判断ESP流量是否存在周期性峰值。对判断隧道是否饱和、是否需要扩容有很大参考价值。4. 实战避坑抓ESP数据包的几类经典问题4.1 抓包前先关掉网卡卸载避免收到“假”大包这个坑我踩过不少次。现在的网卡普遍支持各种硬件卸载功能比如TSOTCP Segmentation Offload、GSO、GRO、LRO这些功能会在硬件层面做大包预处理。带来的直接后果是你在抓包软件里看到的包根本不是网络上真实传输的包。对于ESP这种本身就要重新封装大包的场景影响尤其明显。你可能会抓到很多8000多字节甚至更大的巨型帧或者看到IP头里长度字段异常实际抓包长度和协议长度对不上。分析此类数据时分包重组和校验和都可能显示异常把自己绕进错误的排查方向。解决方法是抓包前把网卡的offload相关选项关掉。Windows环境在网卡属性里找“Large Send Offload”“TCP/UDP Checksum Offload”“Receive Side Scaling”之类的项尽量关闭。Linux环境用ethtool处理比如sudo ethtool -K eth0 tx off rx off tso off gso off gro off在虚拟化环境里比如用VMware或VirtualBox做实验时也要顺手检查虚拟网卡是否有类似的offload开关。实测下来关闭后抓到的包更干净后续解密分析的成功率更高。4.2 为什么协议列显示的是Data而不是ESP有时候你抓到了协议号是50的包但Wireshark的Protocol列显示的却是Data或Encrypted Data而不是ESP。这种情况大概率是解析器没有正确匹配。处理方式有几种按有效程度排序确认IP头里的Protocol是不是50。如果确实是50而Wireshark没识别右键点击这条数据包选择Decode As把该包解析成ESP。检查IP分片情况。如果ESP包在传输过程中发生了分片只有第一个分片会带着ESP头后面的分片荷载上可能只有ESP密文的尾段Wireshark无法从后续分片识别出ESP。这种时候需要开启IP重组Preferences - Protocols - IPv4 - Reassemble fragmented IPv4 datagrams。确认抓包点没有对ESP流量做了某种特殊处置。比如某些负载均衡设备或者安全设备可能会把ESP包转发到别的端口或者剥离掉IP头导致抓到的包结构不完整。如果以上都确认过没问题再用tshark直接跑一下底层字段tshark -r capture.pcap -Y ip.proto 50 -T fields -e frame.number -e _ws.col.Protocol看看协议列到底显示什么能帮助判断是解析器问题还是包本身结构问题。4.3 解密失败的排查清单解密ESP是件看运气的事但大多数失败都可以按这个清单排查密钥和算法对不对ESP的加密算法不仅名字要对参数也要对比如AES-CBC和AES-GCM在Wireshark里的配置完全不同GCM模式还要填salt漏了就解不出来。SA是否过期IPsec的SA通常有lifetime限制超时会触发重新协商。抓包文件如果跨度较长可能需要配置多个SPI的SA参数。外层IP的src/dst填反SPI是接收方分配的所以配置SA时Source IP/Dest IP必须和ESP包外层IP方向匹配。方向填反了密钥对不上自然解不出。看是否用了UDP封装有些场景下ESP流量会被封装在UDP 4500端口的包里这时候ESP内部结构外面还套了一个UDP头Wireshark需要先识别UDP封装再回归ESP解析。如果遇到这种情况检查NAPT-PT或NAT-T相关配置。典型的表现是配置后Wireshark依然显示密文或者ESP节点下方没有任何解密字段。这时候别反复配同一份参数先换个方向排查比如用SPI先过滤出对应方向的包确认SA参数和包的outer IP匹配。4.4 用tshark批量分析ESP流最后再分享一个批量处理的小技巧。如果你需要统计整个pcap文件里ESP包的数量、字节数以及各个SPI的分布情况可以这么写tshark -r ipsec.pcap -q -z io,phs它能输出整个抓包文件的协议分层统计ESP占了多少、占比多少一目了然。另一个更聚焦的命令是tshark -r ipsec.pcap -Y esp -T fields -e esp.spi | sort | uniq -c | sort -rn这个命令会把所有SPI出现的次数统计出来排个序。看到哪个SPI的包数量特别大就重点分析对应方向的SA。我经常用这个办法在抓包文件里快速定位“哪个隧道是主要流量”尤其是在网关同时跑了好几条隧道的场景下这个命令几乎是必备工具。我自己在实际操作中的体会是ESP解密这条路确实有点绕但只要抓住SPI这个线索把SA参数配置好之后整个分析过程就会变得非常顺滑。最后再分享一个小习惯抓包文件里如果涉及多条SA我在导出pcap的同时一定会把SPI和密钥单独存一个文本文件文件名直接标注抓包时间和网关接口名。这样隔几天回来分析自己也不会忘了哪条SA对应哪个时间段。毕竟Wireshark只是一个工具真正值钱的是分析前你把材料整理得够不够清楚。