Pi 网关的主机名会自动更新静态路由吗?
Pi 网关的 DNS 名称永远不会改写已安装的下一跳。看看内核保存了什么,以及谁必须更新路由。
把静态路由指向网关名称,感觉它应该在地址变更后依然有效,实际上并不会。名称存在于 DNS 中,而路由以数字下一跳的形式坐在客户端路由表里。当 Pi 换到另一个地址时,每个已经安装旧下一跳的使用者仍然把流量发往同一个数字。没有任何解析器接入了转发表,因此没有东西替你重写那条记录。
DNS 应答和路由是两个不同的对象
假设你的 Pi 应答 vpn-gw.lan,并把 10.44.0.0/16 转发进一条隧道。192.168.30.0/24 上的客户端通过静态路由访问它。当 Pi 的地址从 192.168.30.4 变成 192.168.30.11 时,记录在自己的 TTL 内跟上了,而路由没有跟上。
这两种视角的分歧很容易被忽略,因为分开查询时两者看起来都合理:
$ ip route get 10.44.0.1
10.44.0.1 via 192.168.30.4 dev eth0 src 192.168.30.20
$ dig +short vpn-gw.lan
192.168.30.11
只有第一行决定数据包去哪里。第二行回答的是内核从未提出的问题。带有多条 A 记录的记录也不会变成故障切换策略,因为每个地址仍然必须是该网段上可用的下一跳。
命令退出后表里留下什么
Linux 路由会记录两件关键的事:作为协议地址的下一跳,以及作为索引号的外出接口。rtnetlink 路由属性把第一个字段称作 RTA_GATEWAY,里面存放的是字节。记录一旦就位,就没有 TTL 附在上面,也没有任何后台查询去刷新它。
这就是为什么 ip route add 10.44.0.0/16 via vpn-gw.lan 可能看起来可行。工具在命令运行期间解析名称,写入得到的地址,然后把名称彻底忘掉。之后运行 ip route show 10.44.0.0/16,你会拿回一个字面地址。
在怪罪隧道之前,这个行为值得了解。
替你解析名称的工具,以及它们何时解析
有些路由器和防火墙确实接受路由或网关字段中的主机名。关键在于解析发生在什么时候。如果设备只在你提交配置时解析名称,那么存下来的条目和手输地址一样静态,之后的地址变更需要再提交一次。字段接受名称,并不能告诉你任何关于刷新的信息。
受管理的部署往往把工作分开。DHCP 保留或静态租约把 Pi 固定在一个地址上,DNS 记录只是跟着租约走。没有东西需要追踪移动的目标,因为目标本身不移动。
受监控的更新程序是另一种正当模式,它需要一个负责人。
固定地址,或者自己运行更新程序
对小型局域网来说,在 DHCP 服务器上做保留是最省钱的修法。选一个动态地址池之外的地址,把它绑定到 Pi 的 MAC 地址,并在下一次租约续期后用 ip -4 addr show dev eth0 确认。然后把客户端的下一跳一次性指向那个地址。现在你有了稳定的网关和描述它的记录,而这就是这段关系真正生效的顺序。
如果 Pi 确实必须搬家,把路由修补集中在一处,而不是手动编辑每个客户端。一段会解析、比较并替换的小脚本,就足以让这一步可重复:
new=$(dig +short vpn-gw.lan | head -n1)
cur=$(ip route get 10.44.0.1 | awk '{print $3}')
if [ "$new" != "$cur" ]; then
ip route replace 10.44.0.0/16 via "$new"
fi
ip route get 10.44.0.1
最后一条命令是验收测试,因为它打印的正是内核实际会使用的网关。如果打印出的地址还是旧的,说明脚本跑在错误的网络命名空间里或缺少权限,DNS 那一侧无关紧要。
也要检查回程路径。Pi 必须知道如何到达客户端子网,它的防火墙必须放行隧道流量。为了掩盖不匹配而加上的默认路由,通常会隐藏真正的缺口,并在一个星期后弄坏别的东西。