你加上了路由,隧道也起来了,但发往另一端的 ping 仍以完全丢包结束,而不是「network unreachable」。这个差别很重要,因为它把视线从路由表移向地址本身。169.254 目标属于链路本地,其作用域按设计在第一条跳之后结束,而不是配置错误所致。

接下来的决定很窄:修好服务端子网,或者扩展第 2 层网段,让地址重新具有本地意义。其他做法,包括加一条更宽的路由,都只是让同样的失败波及更多目标。

这个地址不是没有路由,而是不可路由

IPv4 链路本地地址在没有更好的应答时由主机自行分配;Windows 的自动专用地址就来源于此,其他系统也有对应的回退机制。该范围在每个链路上同时使用,这正是它能工作的原因:同一网段的两台主机无需任何协调即可通信。

正因为这个特性,路由器不得在网络之间转发这类数据包。收到发往链路本地目标的数据包、再把它从另一个接口发出去,会造成歧义,因为发送方的「本地」和接收方的「本地」是不同的地方。没有任何查表能判定发送方指的是哪一个。此处的转发不是管理员可以打开的策略选项;地址类别排除了它。

因此,把 169.254.1.10 配置为可经隧道到达的网关,是在要求内核做地址格式所禁止的事。数据包在到达远端主机之前很久就被丢弃,任何路由精度都改变不了这个结果。

隧道为什么让作用域问题显现

TUN 接口在两个对端之间承载 IP 数据包,背后没有共享网段。没有广播,没有针对另一端的 ARP,也没有能把链路本地目标解析成链路层地址的邻居发现。

一旦知道该看什么,症状就完全对得上。路由在表中存在,ping 报告完全丢包而不是网络不可达,邻居表显示不完整或失败的条目。在隧道上抓包会看到数据包发出,这让人去看远端,而不是地址类别。

在 Windows 上还有第二个看似无关、根源相同的症状:只剩链路本地地址的网卡没有可用网关,网络识别无法分类连接,防火墙配置文件落到公用。隧道不是原因;地址才是。

用三个问题做决定

修复子网还是把链路桥接,取决于三个条件,其中任何一个都可能在打开配置文件之前决定答案。

QuestionIf yesIf no
Can the far-side host be given a routable address?Change the host or fix DHCP and route normallyContinue to the next question
Does the device accept a static address at all?Assign one from the site's real prefixBridging is the only remaining option
Can you accept broadcast crossing the tunnel?A bridge is viable for a small segmentReplace the device or accept no remote access

大多数情况停在第一个问题。主机显示链路本地地址通常意味着 DHCP 没有应答、网线或 VLAN 有误,或者有人手工输入了地址。修好它比任何隧道工作都便宜,并且能为所有未来客户端消除问题,而不只是这一台。

在假设任何事情之前先检查服务端。在主机上运行 ip addr show 和 ip route,在客户端运行 arp -n 或 route print -4,看前缀是否真实存在,还是只有一条旧记录在这样说。

当网桥才是正确答案时,它的代价

把物理网卡与 TAP 网卡桥接,会让远端客户端成为本地广播域的一部分。此时广播和邻居发现可以工作,链路本地地址重新有意义,因为客户端确实本属于那条链路。

代价是真实的,应当在有人同意之前说明。广播流量会穿过隧道,客户端对本地网段全面暴露,而不只是它需要的服务;服务器现在要转发帧而不是路由数据包。对实验台或没有可路由配置路径的设备来说这是合理交换,对远程访问则是糟糕的默认值。

做网桥时两半都需要:服务器上的网桥,以及客户端配置里指明哪些目标在另一端的路由。只有网桥会让客户端靠猜,只有路由无法修正地址类别。

相关文章