那个 L2TP 地址来自 IPCP,而不是局域网 DHCP 租约
内部地址来自 PPP 协商,而不是办公室的 DHCP 服务器。看看是哪个阶段分配的、为什么局域网无法回应,以及该检查什么。
连接建立起来,适配器显示了一个办公室网段的地址,于是自然的结论是 VPN 给了你一个 LAN 地址,因而把你放进了 LAN。这两半都不完全正确。 L2TP 承载 PPP 会话,而 PPP 通过 IPCP 协商内部 IPv4 地址。这个地址是双方商定的会话参数,不是办公室 DHCP 服务器发放的租约;拥有它也不意味着你成了办公室线路上的邻居。
一个连接里的两个地址
一个 L2TP 连接里有两套独立的协商。外层在你已有的任意网络之上,建立设备与 VPN 端点之间的受保护路径。内层就是 PPP 会话,你的会话地址与对端地址都在这里商定。互联网流量可能完全以第三个地址、也就是端点的公网地址出网,所以 VPN 检测页面显示的地址和适配器地址很少一致。
把这三个角色分开,就能回答人们带到这一层的大多数问题。VPN 接口上出现私有地址是正常且可预期的。它既不说明端点有没有改变你的公网出口,也不单独决定你的流量能到达哪些目的地。
IPCP 到底做什么
IPCP 是 PPP 的 IPv4 控制协议。每一方都发送 Configure-Request 报文来描述自己想要的选项,地址选项就是其中之一。还没有地址的客户端通常用 0.0.0.0 发起请求,服务器则用携带它希望客户端使用地址的 Configure-Nak 回应。随后客户端请求该地址,会话便带着一个本地地址和一个远端地址建立起来。
这套交换写在 PPP 和 IPCP 规范里,也解释了一个看起来像 bug 的细节:地址由服务器按自己的策略挑选,可能是地址池、按用户的设置,或与已认证身份绑定的地址。当地址池耗尽,或策略与请求冲突时,认证可能成功而地址协商失败,客户端就会报告一个始终无法稳定的连接。
ip addr show ppp0
ip route show default
dmesg | grep -i pppd
pppd 日志里同时给出本地地址和远端地址的那一行,就是这次协商成功的终点。如果没有这一行,而认证又成功了,问题就指向地址阶段,而不是凭据。
为什么局域网无法回应你
来自对端网段的地址会让人以为那个 LAN 上的主机能找到你,但多数情况下不能,除非服务器把你的会话地址路由回隧道。身处地址池之内只是关于分配的陈述,不是关于拓扑的。办公室文件服务器没有通往你会话地址的路由,除非 VPN 服务器转发它,而且即便转发也未必被允许。
这也正是地址段重叠时麻烦与其表面规模不成比例的原因。如果地址池和客户端已在使用的 LAN 重叠,客户端的路由表就对同一前缀有了两处主张,而错误的那一处常常因为与隧道毫无关系的原因胜出。
先验证会话,再验证路由
先查接口,再查路由,最后查一个重要的目的地。每一步都有自己的失败方式,同时测这三样会得出一个你事后无法自圆其说的结论。
curl -sS --max-time 5 https://ifconfig.me
ping -c 3 10.50.30.20
ip route get 10.50.30.20
如果公网检测显示的是端点地址,而某个私有目的地超时,说明隧道承载着你的默认路由,对端并不为该目的地作答。如果私有目的地有回应、公网检测却不变,说明该配置是拆分隧道,只有部分流量走这个会话。
把三个阶段分开
认证、地址协商与转发各自以不同方式失败,而且各有各的负责人。凭据是身份问题,IPCP 耗尽服务器策略问题,缺少回程路由是网络设计问题。把三者都报成“VPN 坏了”,必然导致修复缓慢。
记下分配到的地址、它来自哪个地址池,以及 LAN 是否本就应当能到达它。这一条记录能阻止下一个人假设存在 DHCP 租约,去找一个从未参与其事的地址范围。