IKEv2 用 UDP 500 还是 4500 来传数据?
第一个交换和真正承载数据的路径不是同一条流。两个端口都要检查,并记住原生 ESP 是 IP 协议号,不是端口。
在防火墙中放行 UDP 500 能让隧道完成协商,随后连接却不再传输数据。端口清单不是写错,而是不全。IKEv2 在一个套接字上开始,在许多真实部署中却在另一个套接字上继续,而载荷甚至可能根本不是端口。按顺序读各个阶段,才能看出缺的是哪一条规则。
两个端口,两种分工
IKEv2 先在 UDP 500 上做密钥交换,双方在此完成认证并为隧道建立安全关联。随后的数据路径是另一回事:既可能是原生的 ESP,它是 IP 协议号而不是端口,也可能是封装在 UDP 中走 4500 的流量。在防火墙评审中把这两者分开,就是“能协商的隧道”与“能工作的隧道”之间的差别。一个套接字承载控制,另一个承载载荷。
正因如此,只放行 500 的规则会产生整个协议族里最令人困惑的症状:协商成功,却没有任何可用流量。状态里看得到对端,日志里看得到已建立的 IKE SA,应用却仍然超时。缺失的那条放行属于另一条流,而不是刚刚成功的那条。
4500 为什么存在
许多 NAT 设备无法转发 TCP 或 UDP 以外的协议,还有一些重写地址的方式会破坏 ESP 的完整性校验。把 ESP 封装进 UDP 能同时解决这两个问题,代价是多一个头部和一条需要放行的第二个端口。正是这层封装,才是第二个端口存在的原因。
一旦检测到 NAT,IKE 本身也会转到 4500,让所有流量共用穿过转换器的一条路径。一个四字节的非 ESP 标记用来在该套接字上区分控制消息与数据。这个切换是协议决定,而不是管理员偏好。
源端口在哪里改变
转换器可能重写客户端的源端口,于是服务器看到的元组与客户端上的元组并不一致。在断定某条规则被忽略之前,先看每一跳 NAT 的两侧。只在客户端排查,可能得到一条看起来正确却仍然失败的规则。
支持 MOBIKE 的实现也可以在没有检测到 NAT 的情况下转到 4500,有些部署会刻意强制走这条路。因此看到 4500 只说明做过决定,并不能证明是家用路由器。
在每一处边界检查两条流
走一遍三处边界:客户端网络、任何中间防火墙和服务器。每一处需要的是部署文档写明的流,而不是另一篇文章里针对别种情况的流。
sudo swanctl --list-sas
sudo tcpdump -ni any 'udp port 500 or udp port 4500'
sudo iptables -S | grep -E '500|4500|esp'
ip xfrm state
防火墙清单里的 ESP 行是协议匹配,端口规则永远覆盖不到它。如果运维方使用自定义端口,请按两端文档中的配置执行,因为客户端无法靠挑一个熟悉的端口号就在服务器上创建监听。
记录协商停在哪一步、子安全关联是否安装,因为这一对信息能把“路径被挡”与“认证或策略错误”区分开。然后用启用服务器校验的方式重测,因为可达并不等于通过认证。最后这一步,才把“放行的端口”与“可信的对端”区分开。