IPsec NAT 穿透如何把 ESP 包进 UDP
ESP 没有端口,所以 NAT 穿透把它包在 4500 的 UDP 里。把控制交换和封装后的数据路径当作两个独立阶段来检查。
同一台路由器后面的两个客户端连同一个 IPsec 网关,一个不断掉线,另一个却保持连接。原生 ESP 是没有端口的 IP 协议 50,所以当多个客户端共用一个地址时,转换设备没有可用于映射的依据。NAT 穿透把 ESP 包进 4500 的 UDP,从而补上这个缺口,而那个头部解释了随后的大多数症状。它同时也指出了需要改动的设备。
数据面为何转到 4500 端口
在建立阶段,IKEv2 通过在 NAT 检测通知中交换哈希,比较双方各自认为自己使用的地址和端口。哈希不一致时,路径上某处存在转换设备,两端就把受保护流量切换到 UDP 封装。这就是遇到过转换设备的会话与没遇到的看起来不同的原因。
封装只是一层信封,不是协议变更:ESP 保留自己的头部、完整性校验和加密,UDP 只提供转换设备所需的端口。500 端口承载 IKE 交换;4500 承载检测后的封装数据,而且常常也承载之后的 IKE 消息。两个端口都不会让流变成 TCP 连接,正是这个假设让大多数看抓包的人误判。
按顺序检查两个阶段
先证明控制交换,再证明数据路径,并在笔记里把两者分开。抓包显示 500 上有流量、4500 上从来没有,通常意味着数据路径被过滤,所以修复应落在防火墙规则而不是客户端。
用 tcpdump -ni any 'udp port 500 or udp port 4500' 同时观察两个端口,并在会话活动期间读取路由器上的转换表。该表显示网关实际会看到的源端口,而笔记本上的抓包按设计与之不一致:笔记本认为是 500,网关看到的是经过转换的源端口和 4500,两者都对。同一条流的转换前后如下:
client 192.0.2.10:500 -> router 203.0.113.7:62000 -> gateway 198.51.100.9:4500
封装能解释的症状,以及两个它解释不了的症状
允许控制交换却阻断封装数据的路由器会给出“隧道已建立但什么都不通”的报告。映射表会过期,所以空闲会话需要两端刻意发送的保活流量,而那些包不是健康检查。当同一网关后面的多个客户端一起失败时,检查该网关的转换以及任何旧的直通功能。封装解释不了隧道建立后所有客户端都失败的应用程序,也解释不了阻止页面上的证书警告;这两者都在这一层之上。
同时读取两个客户端的映射表:如果两者显示同一个转换后的端口,设备就没有按网关要求把它们分开。只把一个原生 ESP 交给单台主机的直通模式,并不等同于服务多个经过转换的客户端,尽管厂商把两者都描述为对 IPsec 友好。双重 NAT 会增加一层映射和另一个过期点,但不会自动切断出站连接。
保活流量值得在运行手册里单独占一行,因为正是它在空闲期保持回程路径打开。在厂商有文档的地方启用它,并在一段静默几分钟后会话死掉、而不是首次使用时,优先检查它。
先改变映射的归属,再重新测试
按两端受支持的 NAT 穿透设置来做,而不是猜端口。在单个客户端上改本地源端口无法改变远端正在监听的服务,而且通常会破坏已经建立的映射。如果客户端位于你无法控制的设备后面,改动属于该设备的所有者。
任何改动之后,重跑两个阶段检查,确认数据包真的通过,而不只是状态页变绿。把元组、映射表输出和规则改动记在同一条笔记里,好让下一个人不必从控制交换重新开始。strongSwan 关于 NAT 穿透的说明涵盖两个阶段背后的封装与保活设置。