在嵌入式/物联网用例中,我有一个运行 Linux 的管理主机,它需要能够与多个网络通信,每个网络都使用一组通用的静态 IP 地址。
这主要工作正常,包括 UDP 多播流量,给定:
- 每个嵌入式网络的网络链接(称它们
eth1
为 ,eth2
等) - 每个不同的嵌入式网络都有一个单独的 Linux 网络命名空间(称它们
ns1
为 ,ns2
等) - 每个网络命名空间和根命名空间之间的对等链接(从网络命名空间端调用它们
peer1
,等,从根命名空间端调用它们 , 等)peer2
veth1
veth2
- 每个命名空间中的 iptables NETMAP 规则将冲突的静态 IP 子网(调用它
192.168.0.x
)映射到一组非冲突的静态 IP 子网(调用它们192.168.1.x
,192.168.2.x
等等) - 每个网络命名空间内的一个
smcrouted
实例,用于转发多播组注册 - 对等链接的根命名空间侧的不同(非 NAT)子网中的单独 IP 地址,以解决此问题的主题(调用它
192.168.(x+100).1
)
要尝试可视化流量:
[|root namespace|::veth1] <-> [peer1::(namespace ns1)::eth1] <-> embedded network
[| |::veth2] <-> [peer2::(namespace ns2)::eth2] <-> embedded network
... etc ...
ns1
静态 IP 子网的示例 NETMAP 规则:
sudo -n ip netns exec ns1 iptables -t nat -A PREROUTING -d 192.168.1.0/24 -i peer1 -j NETMAP --to 192.168.0.0/24
sudo -n ip netns exec ns1 iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o peer1 -j NETMAP --to 192.168.1.0/24
ns1
smcrouted
支持的多播组的示例配置规则:
mgroup from eth1 group 239.255.60.60
mgroup from peer1 group 239.255.60.60
mroute from eth1 group 239.255.60.60 to peer1
mroute from peer1 source 192.168.101.1 group 239.255.60.60 to eth1
这个问题的实际主题是NETMAP
源IP调整中有一个奇怪的故障,我无法解释,只能解决。
我的预期行为:
- 网络命名空间内的 UDP 多播订阅将看到未修改的 pre-NETMAP
192.168.0.x
源地址 - 根命名空间内的 UDP 多播订阅将看到修改后的 NETMAP
192.168.1.x
源地址
不过,这不是发生的事情。相反,两个命名空间中的订阅者要么看到 NETMAP 之前的 192.168.0.x 源地址,要么他们看到 192.168.1.x 之后的 NETMAP 地址。
配置中规则的source
过滤器用于防止多播路由循环,否则该循环会在服务器切换到第二组行为时启动。mroute from peer1
smcroute
到目前为止,我还无法确定导致两种状态之间转换的原因,只能在源地址信息看起来错误时通过基于活动网络命名空间或源网络接口进行调整来解决应用层的问题。
提出问题的目的是帮助确定以下哪一项适用:
- 预计这不会起作用,在应用程序层进行补偿是可以做到的最好的(考虑到在 Linux 容器环境中使用网络命名空间,这似乎不太可能)
- 在内核、iptables 或 smcroute 中需要配置(或未配置)其他东西,以防止错误行为发生
(注意:这是一个非常深奥、非常具体的问题,所以我想知道网络工程是否更合适,但是https://networkengineering.stackexchange.com/questions/64744/linux-local-multicast-egress-follows -forward-chain-when-smcroute-is-active明确表示这是用于使用商业路由器等,而不是用于 Linux 网络名称空间配置。我不太清楚 Server Fault 与 Unix & Linux 堆栈交换之间的界限但是,在配置 Linux 服务器时)
SMCRoute的维护者在这里。这绝对应该有效。我们为工作中的各种客户使用这种精确的方法,尽管使用实际的硬件而不是网络命名空间。
SMCRoute 问题跟踪器中报告了一个非常相似的问题,与您的唯一区别是他们不使用 1:1 NAT 和 netmap(还)。
我为此准备了一个测试用例,为下一个版本(v2.5)做准备。我使用以下方法在本地和 GitHub Actions(Azure 云)中运行所有测试:
该测试在专用网络命名空间中有两个独立的路由器(R1 和 R2),它们之间有一个共享的 LAN 网段(192.168.0.0/24)。每个路由器后面是一个专用 LAN (10.0.0.0/24),两个路由器都相同。额外的(虚拟)接口 eth1 用于将多播从共享 LAN (eth0) 路由。NETMAP 规则使用 PREROUTING 和 POSTROUTING 链。将 R1 专用 LAN 转换为 192.168.10.0/24,将 R2 专用 LAN 转换为 192.168.20.0/24。如下所示,安装在内核中的多播路由使用 1:1 映射(全局)地址。
它可能有点难以阅读,您可能需要查阅测试用例以获取详细信息。无论如何,我在翻译中得到了一致的结果,顺便说一句,这是 Linux 而不是 SMCRoute 的责任,所以你可能有内核错误之类的。可能个人工作站具有内核为 5.11.0 的 Linux Mint,而 GitHub Actions 的后端服务器运行 Ubuntu 20.04 LTS、内核 5.8.0,两者都已打好补丁的发行版内核,但也许是一个开始的基准?