Mal*_*ous 4 routing ipv6 multicast
我有一个通过 IPv6 发送多播流量的程序。它将流量发送出默认网络接口。它正常工作正常(流量消失eth0
),但是如果我加载了 Docker,那么它会从docker0
接口发送流量eth0
,而不是在网络上不再看到流量。
一个例子是,如果我运行该命令,并且在运行时我使用as或 asping ff05::1
检查接口,那么数据包并不总是按预期离开。tcpdump -n host ff05::1 -i XXX
XXX
eth0
docker0
eth0
现在我可以通过检查我正在使用的每个程序并指定要绑定的接口(例如使用-I
上面的 ping 选项)来解决这个问题,但是这是有问题的,因为我想在多台计算机上共享相同的配置文件,但我必须为每个地址设置不同的 IPv6 地址和接口名称,并记住在动态 IP 地址发生变化时更新它们。
相反,我想了解Linux在绑定到套接字时如何选择要使用的接口,希望我可以在每台机器上手动设置首选接口。然后我正在使用的程序将在正确的接口上发送和接收其多播流量,而不需要任何特殊配置。
我尝试过添加网络路由 ( ip -6 route add ff05::/16 dev eth0
) 但这没有任何区别。问题似乎是 Linux 选择一个要绑定的接口(在路由发生之前),然后使用该接口的 IP 地址作为传出数据包的源地址,将其锁定到该接口,而不管路由规则如何。
那么,以ping
上面的命令为例,默认的出接口是如何选择的(当-I
不使用时)以及如何更改它呢?
注意:应该使用 FF05::2(站点本地所有路由器多播地址)或 FF02::1(链路本地所有节点多播地址,可能应该使用接口范围),因为 FF05::1(假设站点本地所有路由器多播地址)节点多播地址)未定义 ,并且可能永远不会得到答案(ip -6 maddress
至少在路由器显示 ff05::2 时不会在任何 Linux 系统上显示它)。
每次添加并启动新接口时,在各种自动地址中,都会在本地表中添加 IPv6 多播路由,因此在主路由表中不可见:
$ ip route get ff05::02
multicast ff05::2 from :: dev dummy0 table local proto kernel src fe80::8c5f:87ff:fe50:d08a metric 256 pref medium
$ ip -6 route show type multicast table local
multicast ff00::/8 dev dummy0 proto kernel metric 256 pref medium
multicast ff00::/8 dev lxcbr0 proto kernel metric 256 pref medium
multicast ff00::/8 dev eth0 proto kernel metric 256 pref medium
...
Run Code Online (Sandbox Code Playgroud)
equals 之间的顺序是相当随机的并且难以重现。每次关闭/打开接口时,多播条目都会被删除并重新添加,但顺序可能会发生变化。只有内核可以添加这样的“相等路由”,用户不允许这样做(=> RTNETLINK answers: File exists
)。本地表在规则优先级(优先级 0)中先于任何其他表使用,主表中的类似条目可能没有效果:
$ ip -6 rule
0: from all lookup local
32766: from all lookup main
Run Code Online (Sandbox Code Playgroud)
反正。只需要在本地表中手动添加一条具有较低度量的多播路由即可确定地选择哪个是“默认”多播路由:
# ip route add multicast ff00::/8 dev eth0 table local metric 100
$ ip route get ff05::02
multicast ff05::2 from :: dev eth0 table local src 2001:db8:123:4567:52fb:e94:d3b7:5ba8 metric 100 pref medium
Run Code Online (Sandbox Code Playgroud)
当接口关闭(和打开)时,此路由将消失,因此应沿着配置此接口的工具添加。
注意:IPv4 在任何地方都没有默认定义任何组播路由(并且遵循一些内核内置逻辑来了解该地址是否为组播),因此组播路由遵循默认路由。如果想要留出多播块(例如:使用生成多播流的工具,但不想用该流淹没没有 IGMP 侦听功能的交换机的 LAN),则可以执行相反的操作并为这些流添加多播类型路由流在不同的(这里是虚拟的)接口上。由于没有本地表交互,主表就足够了(但table local
也可以添加):
# ip route add multicast 239.255.16.0/20 dev dummy0
$ ip route get 239.255.16.2
multicast 239.255.16.2 dev dummy0 src 172.20.21.22 uid 0
cache <mc>
Run Code Online (Sandbox Code Playgroud)