Iptables

iptables NETMAP 不能可靠地調整多播 UDP 數據包的源地址

  • August 12, 2021

在嵌入式/物聯網案例中,我有一個執行 Linux 的管理主機,它需要能夠與多個網路通信,每個網路都使用一組通用的靜態 IP 地址。

這主要工作正常,包括 UDP 多播流量,給定:

  • 每個嵌入式網路的網路連結(稱它們eth1為 ,eth2等)
  • 每個不同的嵌入式網路都有一個單獨的 Linux 網路命名空間(稱它們ns1為 ,ns2等)
  • 每個網路命名空間和根命名空間之間的對等連結(從網路命名空間端呼叫它們peer1,等,從根命名空間端呼叫它們 , 等)peer2``veth1``veth2
  • 每個命名空間中的 iptables NETMAP 規則將衝突的靜態 IP 子網(呼叫它192.168.0.x)映射到一組非衝突的靜態 IP 子網(呼叫它們192.168.1.x192.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-NETMAP192.168.0.x源地址
  • 根命名空間內的 UDP 多播訂閱將看到修改後的 NETMAP192.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 雲)中執行所有測試:

cd test/
unshare -mrun ./multi.sh

該測試在專用網路命名空間中有兩個獨立的路由器(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 映射(全域)地址。

>> Starting emitters ...                                                           
R1[2811708]: New multicast data from 192.168.10.1 to group 225.1.2.3 on VIF 1
R1[2811708]: Add 192.168.10.1 -> 225.1.2.3 from VIF 1
R2[2811709]: New multicast data from 192.168.10.1 to group 225.1.2.3 on VIF 0
R2[2811709]: Add 192.168.10.1 -> 225.1.2.3 from VIF 0
R2[2811709]: New multicast data from 192.168.20.1 to group 225.1.2.3 on VIF 1
R2[2811709]: Add 192.168.20.1 -> 225.1.2.3 from VIF 1
R1[2811708]: New multicast data from 192.168.20.1 to group 225.1.2.3 on VIF 0
R1[2811708]: Add 192.168.20.1 -> 225.1.2.3 from VIF 0
>> R1 multicast routes and 1:1 NAT ...                                             
(192.168.10.1,225.1.2.3)         Iif: eth1       Oifs: eth0  State: resolved
(192.168.20.1,225.1.2.3)         Iif: eth0       Oifs: eth1  State: resolved
Chain PREROUTING (policy ACCEPT 5 packets, 244 bytes)
pkts bytes target     prot opt in     out     source               destination         
   0     0 NETMAP     all  --  any    any     anywhere             192.168.10.0/24      to:10.0.0.0/24

Chain INPUT (policy ACCEPT 1 packets, 84 bytes)
pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 4 packets, 248 bytes)
pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 2 packets, 124 bytes)
pkts bytes target     prot opt in     out     source               destination         
   2   124 NETMAP     all  --  any    any     10.0.0.0/24          anywhere             to:192.168.10.0/24
>> R2 multicast routes and 1:1 NAT ...                                             
(192.168.10.1,225.1.2.3)         Iif: eth0       Oifs: eth1  State: resolved
(192.168.20.1,225.1.2.3)         Iif: eth1       Oifs: eth0  State: resolved
Chain PREROUTING (policy ACCEPT 4 packets, 204 bytes)
pkts bytes target     prot opt in     out     source               destination         
   1    84 NETMAP     all  --  any    any     anywhere             192.168.20.0/24      to:10.0.0.0/24

Chain INPUT (policy ACCEPT 2 packets, 168 bytes)
pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 3 packets, 164 bytes)
pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 1 packets, 40 bytes)
pkts bytes target     prot opt in     out     source               destination         
   2   124 NETMAP     all  --  any    any     10.0.0.0/24          anywhere             to:192.168.20.0/24
>> Analyzing ...                                                                   
   1 0.000000000 0.000000000 192.168.10.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe769, seq=1/256, ttl=2
   2 1.000105261 1.000105261 192.168.10.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe769, seq=2/512, ttl=2
   3 1.000957268 0.000852007 192.168.20.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe76b, seq=1/256, ttl=2
   4 2.024216212 1.023258944 192.168.10.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe769, seq=3/768, ttl=2
   5 2.024216229 0.000000017 192.168.20.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe76b, seq=2/512, ttl=2
   6 3.048426868 1.024210639 192.168.10.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe769, seq=4/1024, ttl=2
   7 3.048426842 -0.000000026 192.168.20.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe76b, seq=3/768, ttl=2
   8 4.072270331 1.023843489 192.168.10.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe769, seq=5/1280, ttl=2
   9 4.072270458 0.000000127 192.168.20.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe76b, seq=4/1024, ttl=2
  10 5.096430449 1.024159991 192.168.20.1 → 225.1.2.3    ICMP 98 Echo (ping) request  id=0xe76b, seq=5/1280, ttl=2
=> 10 for group ff04::114, expected >= 8

它可能有點難以閱讀,您可能需要查閱測試案例以獲取詳細資訊。無論如何,我在翻譯中得到了一致的結果,順便說一句,這是 Linux 而不是 SMCRoute 的責任,所以你可能有核心錯誤之類的。可能個人工作站具有核心 5.11.0 的 Linux Mint 和 GitHub Actions 的後端伺服器執行 Ubuntu 20.04 LTS、核心 5.8.0,這兩個發行版核心都打了更新檔,但也許是一個開始的基線?

引用自:https://serverfault.com/questions/1069555