VPN隧道中的数据包结构解析

VPN的工作原理 / 浏览:2
2026.08.15分享SSR、V2Ray、Clash免费节点,包含美国、韩国、德国、日本、新加坡,免费节点仅供学习研究,请勿非法使用。 【查看详情】

凌晨两点十七分,某互联网公司的运维值班室。咖啡机发出最后一声叹息,屏幕上跳动的告警曲线却突然拉直——跨境专线的流量在3秒内归零。老周揉了揉发红的眼睛,抓起桌上缠着胶带的抓包工具U盘,冲向三楼核心机房。他隐约觉得,今晚要撞见某些“不该存在”的数据包。

一、隧道入口:当普通数据包穿上“防弹衣”

老周在核心交换机上做了端口镜像,Wireshark的滚动窗口立刻被密密麻麻的十六进制字符淹没。他深吸一口气,在过滤栏敲下vpn,屏幕瞬间安静下来。只剩下一串串以ESP(Encapsulating Security Payload)为协议标记的帧,像幽灵列车般在隧道里穿梭。

“看好了,”老周指着屏幕,对刚入职的小徒弟说,“这就是VPN隧道里的‘集装箱货车’。”他放大一个数据帧的头部字段:

  • 外层IP头:目标地址是公司在美国机房的网关IP,端口号被刻意伪装成HTTPS的443——这是为了绕过某些防火墙的深度包检测。
  • ESP头:包含一个32位的SPI(安全参数索引),像一把钥匙,告诉接收端“我是哪个安全联盟的包”。
  • 加密载荷:这里才是真正的“内层数据包”——你访问的网页请求、邮件内容、甚至语音通话的RTP流,全都被AES-256算法嚼碎成密文。

“所以,外人看隧道,只能看到两个IP在互扔‘垃圾数据’。”老周敲了敲屏幕,“但隧道内部,其实是个完整的‘套娃’结构。”

二、套娃解剖:内层IP包的“三重身份”

小徒弟凑近屏幕,老周索性调出Follow TCP Stream功能,把ESP载荷解密后重组。一个完整的内层IP包浮现出来,像从俄罗斯套娃里掏出的小一号娃娃。

1. 最外层:运输标签(Transport Header)

这是“集装箱”本身。老周用Wireshark的Expert Info面板展开字段:

  • 源IP:公司出口网关的私网地址(192.168.x.x)
  • 目的IP:美国机房的VPN网关公网地址
  • 协议号:50(ESP)

“注意这个协议号,”老周用笔尖戳着屏幕,“如果是IPsec的AH模式,协议号会是51。但AH不加密,只做完整性校验,所以现在主流都用ESP。”

2. 中层:加密信封(ESP Header + Trailer)

老周手动解析ESP的头部细节:

  • SPI:0xA1B2C3D4——这是双方通过IKE协商出的随机值,相当于“暗号”。
  • 序列号:32位计数器,防止重放攻击。
  • 填充长度:加密算法要求数据块对齐,比如AES-256-CBC需要填充到16字节的倍数。老周指着一段0x04 0x04:“这里填充了4个字节,填充内容也是0x04,表示‘我填充了4字节’。”

“最关键的是这个ICV(完整性校验值),”老周说,“HMAC-SHA256算出来的,放在ESP尾部。接收端解密后重新计算,如果和这个值不一致,直接丢包——这就是防篡改的‘封条’。”

3. 最内层:真实业务数据(Inner IP Packet)

老周点击Wireshark的Decode As,把解密后的明文还原。屏幕上出现一个全新的IP头:

  • 源IP:员工笔记本的真实IP(10.0.0.5)
  • 目的IP:美国那边服务器的地址(172.16.8.3)
  • 协议号:6(TCP)
  • 载荷GET /index.html HTTP/1.1——一个普通的网页请求。

“看到了吗?”老周把椅子转过来,“VPN的本质,就是把你原本的IP包整个塞进另一个IP包里。内层包是‘信’,外层包是‘信封’。只不过这个信封是用防弹材料做的,还上了三道锁。”

三、隧道中的“幽灵现象”:分片与重组

正当老周讲解时,告警声突然响起——一条大流量下载任务触发了MTU(最大传输单元)问题。小徒弟看着屏幕上出现的Fragmented IP标记,一脸茫然。

“这就是隧道最头疼的地方。”老周调出分片前后的对比图:

  • 原始内层包:1400字节(含TCP头)
  • 外层封装后:加上ESP头(8字节)+ 加密填充(16字节)+ ICV(12字节)+ 外层IP头(20字节)= 1456字节
  • 物理网卡MTU:1500字节——按理说能装下,但问题是外层IP头还要加上20字节,变成1476字节,仍然小于1500,勉强能过。

“但如果内层包是1500字节的满包呢?”老周反问道。他在终端敲下ping -l 1472 -f(Windows下禁止分片),果然,返回Packet needs to be fragmented but DF set

“这时候,VPN网关有两个选择:要么把外层包分片(违反ESP的完整性校验),要么丢弃并发送ICMP错误。”老周指着Wireshark里一个红色标记的包,“看,这个外层IP头的Fragment Offset字段是1480,说明它被切成了两片。接收端必须把两片组装起来再解密——但中间经过的防火墙可能会丢弃分片包,这就是为什么某些网络环境下VPN会突然卡死。”

“所以,好的VPN客户端会自动调整TCP MSS(最大分段大小)。”老周在命令行输入iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu,“把内层TCP的MSS从1460降到1360,给外层封装留出空间。”

四、隧道深处的“心跳”:Keepalive与NAT穿透

凌晨三点半,老周的手机震动——美国那边的同事发来消息:“隧道又断了,正在重连。”老周瞥了一眼Wireshark的统计面板,发现一个规律:每隔60秒,就有一个“空包”通过隧道。

“这是Keepalive机制。”老周指着那些长度仅为60字节的ESP包,“里面没有实际业务数据,只有ESP头和几个填充字节。它的作用是告诉对端:‘我还活着,别把隧道关了。’”

但问题出在NAT(网络地址转换)上。老周用ipsec status查看,发现公司出口的NAT设备把ESP协议(协议号50)给“遗漏”了——因为NAT只识别TCP/UDP,ESP的协议号不在映射表里。

“这就是为什么很多VPN要用UDP封装。”老周调出另一个隧道配置,“看,这个隧道用的是UDP 4500端口——IKE的NAT-T(NAT穿越)机制。它把ESP包再塞进一个UDP包里,UDP的源端口和目的端口都是4500,这样NAT设备就能正确处理了。”

他展开一个UDP封装的ESP包:

  • 外层UDP头:源端口4500,目的端口4500
  • 非ESP标记:UDP载荷开头有4字节的0x00 0x00 0x00 0x00,表示“这是一个NAT-T封装的ESP包”
  • 真正的ESP头:紧随其后的才是SPI和序列号

“如果看到UDP载荷开头不是4个零,那可能是IKE协商包,而不是数据包。”老周补充道,“很多防火墙的深度包检测会特意检查这个标记,来识别VPN流量。”

五、隧道外的“旁观者”:如何用抓包分析VPN异常

小徒弟终于忍不住问:“师傅,那如果隧道挂了,我们怎么从抓包里定位问题?”老周笑了,他调出Wireshark的Statistics -> Flow Graph,屏幕上出现一条时间线:

  1. 20:00:00:IKESAINIT请求发出(UDP 500端口)——协商加密算法
  2. 20:00:01:响应返回,双方交换Nonce和DH公钥
  3. 20:00:02:IKE_AUTH请求——身份认证
  4. 20:00:03:创建ESP SA,SPI=0xA1B2C3D4
  5. 20:00:04:第一个ESP数据包发出——但立即收到ICMP端口不可达(说明对端的UDP 4500被防火墙拦截)

“看到这个ICMP错误了吗?”老周指着红色标记,“这就是隧道断开的直接原因。但更隐蔽的问题在重传——如果ESP包序列号出现跳变,比如从100直接跳到200,说明中间有设备丢包或重排序。”

他又打开Statistics -> Packet Lengths,发现大量1514字节的满包:“这是MTU问题导致的。如果看到大量TCP Previous segment lost的提示,而ESP包本身没有分片,那问题可能出在物理链路上——比如光模块衰耗过大。”

六、隧道的“另一副面孔”:WireGuard与新时代的裸包

凌晨四点,老周泡了杯浓茶,突然说:“你知道吗,现在有些新协议,根本不用ESP这种‘套娃’结构。”他打开一个WireGuard的抓包文件:

  • 外层IP头:协议号是UDP(17),目的端口51820
  • UDP载荷:直接是加密后的数据包,没有ESP头,也没有SPI——因为WireGuard用公钥和私钥对来标识隧道,而不是SPI。
  • 消息类型:1(握手初始化)、2(握手响应)、3(传输数据)。传输数据的消息头只有4字节的Type和4字节的Receiver Index。

“WireGuard把‘隧道’这个概念简化到了极致。”老周在键盘上敲出wg show命令,“它的配置里只有公钥、私钥、IP地址和端口,没有IKE协商,没有SA生命周期,没有AH/ESP之分。每个数据包都携带一个32位的索引,直接对应接收端的加密密钥。”

“但代价是——它不支持NAT-T的自动探测,也不支持动态IP变更。”老周耸耸肩,“所以在移动网络下,WireGuard反而容易掉线。而传统的IPsec虽然笨重,但兼容性最好。”

七、隧道尽头的“黎明”:一次真实的故障修复

清晨六点,老周终于定位到问题根源:公司新换的防火墙默认丢弃了协议号50的ESP流量,只放行了UDP 500和4500。他登录防火墙,添加了一条规则:

permit esp any any

然后重启了VPN服务。Wireshark的屏幕上,ESP包重新开始流动。小徒弟看到,内层IP包里的源IP变成了他自己的电脑——他刚刚用手机热点访问了一个外网测试站。

“看到了吗?”老周摘下眼镜,揉了揉鼻梁,“隧道里的数据包,就像深夜的货运列车。外人只看到一节节黑色的车厢(外层IP),但里面装的可能是黄金、文件,或者只是一堆无用的心跳包。你要做的,就是学会用Wireshark这双‘透视眼’,看清每一层封装、每一段序列号、每一个标志位。”

“那如果遇到加密的载荷,怎么知道里面是什么?”小徒弟问。

“你不需要知道。”老周关掉Wireshark,屏幕暗下来,“VPN的意义,就是让不该知道的人永远不知道。但作为运维,你得知道隧道本身是不是健康的——这就像看心电图,你不需要听懂心脏在说什么,但你要能从波形里看出它是否在正常跳动。”

窗外天色渐亮。老周把抓包文件保存为vpn_tunnel_2025_05_18.pcapng,文件名里包含了日期和隧道ID。他站起身,拍了拍小徒弟的肩膀:“下次隧道再断,别急着重启。先抓包,看看是SPI对不上,还是序列号跳了,或者是MTU惹的祸。数据包不会说谎——它们只是穿着层层外套,等你一层层剥开。”

小徒弟盯着屏幕上定格的ESP包结构图,那些十六进制字符仿佛活了过来。他知道,这个凌晨的“隧道解剖课”,比任何文档都来得真实。而隧道里那些加密的、分片的、重传的、心跳的“幽灵数据包”,从此在他眼里有了清晰的面孔。

版权申明:

作者: 什么是VPN

链接: https://whatisvpn.net/working-principle/vpn-packet-structure.htm

来源: 什么是VPN

文章版权归作者所有,未经允许请勿转载。