一台装有 Debian 10 的机器。它有 3 个具有不同 IP 的接口。其中一个接口在极少数情况下是需要的,它具有到管理网络的静态路由(其余路由通过另一个接口通过 ospf 工作)。
问题是,如果您将电缆从网卡中拔出,接口仍然处于打开状态,路由仍然存在。这不能自动化吗?我在这个问题上找不到任何东西,也许我做错了什么?
此外,如果我使用自动或允许热插拔,即使没有链接,接口也会在重启后启用,因此我必须在必要时手动将其调高。
答案1
高级工具(如 NetworkManager)通常会删除“linkdown”链路上的地址和路由(即:接口上显示 NO-CARRIER 标志)。因此,如果接口由此类工具管理,则可以预期其路由会在插入和拔出时出现和消失。
我知道使用 NetworkManager 可能会对同时使用的动态路由协议造成太大的干扰,因此可能不是最好的主意。
但实际上内核路由栈已经提供了这样的功能,无需修改任何地址或路由:忽略路由链接。
和其他几个条目一样,这个条目出现在内核 4.2 中(因此在 Debian 10 的内核 4.19 中可用),并且然后显示在 kernelnewbies.org 上当它出现时,已经自内核 5.11 起才有文档记录:
ignore_routes_with_linkdown - BOOLEAN
执行 FIB 查找时忽略链接断开的路由。
因此,如果调用该接口mgmt0
,并且仅在检测到运营商时才使用它提供的路由,那么只需执行以下操作:
sysctl -w net.ipv4.conf.mgmt0.ignore_routes_with_linkdown=1
或者把这个放进去/etc/sysctl.conf
。
现在,当这个仍然保持管理开启的接口断开连接时,显示的路由条目ip route
将显示标志dead linkdown
而不是单个标志linkdown
,以告诉用户该路由在 FIB 查找期间确实被忽略。
注意:接口要检测链路,必须先通电。因此,它必须保持管理状态。如果因载波丢失而关闭,则无法在稍后检测到载波时自动将其恢复,因为不再有此类检测。
完整示例:
ip link add name vethtest1 up type veth peer name vethtest1peer
ip link add name vethtest2 up type veth peer name vethtest2peer
ip link set dev vethtest2peer up
ip address add 192.0.2.2/25 dev vethtest1
ip address add 192.0.2.3/24 dev vethtest2
设置地址会安装自动内核 LAN 路由。vethtest1
其对等接口未启动时将处于 NO-CARRIER 状态,并且其路由将获得一个linkdown
标志。
# ip route show to root 192.0.2.0/24
192.0.2.0/25 dev vethtest1 proto kernel scope link src 192.0.2.2 linkdown
192.0.2.0/24 dev vethtest2 proto kernel scope link src 192.0.2.3
将使用到 192.0.2.100 的路由,vethtest1
因为它获得了一条更窄的路由(尽管有标志linkdown
)。
# ip route get 192.0.2.100
192.0.2.100 dev vethtest1 src 192.0.2.2 uid 0
cache
然后使用新设置:
sysctl -w net.ipv4.conf.vethtest1.ignore_routes_with_linkdown=1
新的行为如下:
# ip route show to root 192.0.2.0/24
192.0.2.0/25 dev vethtest1 proto kernel scope link src 192.0.2.2 dead linkdown
192.0.2.0/24 dev vethtest2 proto kernel scope link src 192.0.2.3
# ip -4 netconf show dev vethtest1
inet vethtest1 forwarding on rp_filter off mc_forwarding off proxy_neigh off ignore_routes_with_linkdown on
# ip route get 192.0.2.100
192.0.2.100 dev vethtest2 src 192.0.2.3 uid 0
cache
现在,如果接口获得载波(这里通过启动其对等接口进行模拟):
ip link set dev vethtest1peer up
路线通过它恢复:
# ip route show to root 192.0.2.0/24
192.0.2.0/25 dev vethtest1 proto kernel scope link src 192.0.2.2
192.0.2.0/24 dev vethtest2 proto kernel scope link src 192.0.2.3
# ip route get 192.0.2.100
192.0.2.100 dev vethtest1 src 192.0.2.2 uid 0
cache