我有一个通过 IPv6 发送多播流量的程序。它将流量发送出默认网络接口。它正常工作正常(流量消失eth0
),但是如果我加载了 Docker,那么它会从接口发送流量,docker0
而不是eth0
在网络上不再看到流量。
一个例子是,如果我运行该命令,并且在运行时我使用as或ping ff05::1
as 检查接口,那么数据包并不总是按预期离开。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
不使用时)以及如何更改它呢?
答案1
注意:应该使用 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
...
equals 之间的顺序是相当随机的并且难以重现。每次关闭/打开接口时,多播条目都会被删除并重新添加,但顺序可能会发生变化。只有内核可以添加这样的“相等路由”,用户不允许这样做(=> RTNETLINK answers: File exists
)。这当地的在规则优先级(优先级 0)中先于任何其他表使用的表,在主要的表可能没有效果:
$ ip -6 rule
0: from all lookup local
32766: from all lookup main
反正。只需要在本地表中手动添加一条具有较低度量的多播路由即可确定地选择哪个是“默认”多播路由:
# 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
当接口关闭(和打开)时,此路由将消失,因此应沿着配置此接口的工具添加。
注意: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>
答案2
为了添加 AB 的详细解释,您可以告诉 systemd 按照描述添加多播路由,方法是编辑/etc/systemd/network/*.network
应处理多播流量的网络接口的配置文件,并将其添加到其末尾([Route]
如果您已经有一个):
# Have all IPv6 multicast traffic go out on this interface.
[Route]
Type=multicast
Destination=ff00::/8
Metric=100
Table=local