nftables:段之間重複廣播數據包
我們有一個 Debian Buster 盒子(nftables 0.9.0,核心 4.19)連接到四個不同的網段。其中三個網段是執行 Syncthing 的設備的所在地,這些設備通過廣播到 UDP 埠 21027 執行自己的本地發現。因此,由於廣播不跨網段,因此這些設備不能全部“看到”對方;Buster 盒子本身不參與同步集群。
雖然我們可以通過在 Buster 盒子上執行 Syncthing 的發現或中繼伺服器來解決這個問題,但我們要求我們不要使用它們(原因是配置和漫游到其他站點的設備)。因此,我們正在尋找基於 nftables 的解決方案;我的理解是,通常不會這樣做,但要做到這一點,我們必須:
- 匹配 UDP 21027 上的傳入數據包
- 將這些數據包複製到需要在其上看到的其他分段介面
- 更改新數據包的目標 IP 以匹配新段的廣播地址(同時保留源 IP,因為發現協議可以依賴它)
- 發出新的廣播,而不會再次被複製
只有三個附加的段參與設備;所有的子網遮罩為 /24。
- 不應轉發分段 A (eth0, 192.168.0.1)
- 段 B (eth1, 192.168.1.1) 應該只轉發到段 A
- 段 C (eth2, 192.168.2.1) 應該轉發給 A 和 B
到目前為止,我們最接近的工作規則是(為簡潔起見,省略了其他 DNAT/MASQ 和本地過濾規則):
table ip mangle { chain repeater { type filter hook prerouting priority -152; policy accept; ip protocol tcp return udp dport != 21027 return iifname "eth1" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.1.255 return iifname "eth0" ip saddr 192.168.2.0/24 counter ip daddr set 192.168.0.255 return iifname "eth0" ip saddr 192.168.1.0/24 counter ip daddr set 192.168.0.255 return iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1 iifname "eth2" ip saddr 192.168.2.0/24 counter dup to 192.168.1.255 device "eth1" nftrace set 1 iifname "eth1" ip saddr 192.168.1.0/24 counter dup to 192.168.0.255 device "eth0" nftrace set 1 } }
計數器顯示規則正在被命中,儘管沒有
daddr set
規則,廣播地址仍與原始段上的相同。nft monitor trace
顯示至少有一些數據包以正確的目標 IP 到達預期介面,但隨後降落在框本身的輸入掛鉤中,並且網段上的其他設備看不到。我們在這裡尋找的結果在實踐中是否可以實現,如果可以,遵循哪些規則?
在這種情況下,仍然可以在netdev系列(而不是ip系列)中使用 nftables,因為只需要入口(nftables 仍然沒有可用的出口)。ingress hook中
dup
andfwd
的行為與tc-mirred的and完全相同。mirror``redirect
我還解決了一個小細節:將乙太網源地址重寫為新的乙太網傳出介面的 MAC 地址,就像對真正路由的數據包所做的那樣,即使它在沒有這個的情況下也適用於您。因此,必須事先知道介面的 MAC 地址。我將兩個必需的(eth0和eth1)放在變數/宏定義中,應該使用正確的值進行編輯。
define eth0mac = 02:0a:00:00:00:01 define eth1mac = 02:0b:00:00:00:01 table netdev statelessnat delete table netdev statelessnat table netdev statelessnat { chain b { type filter hook ingress device eth1 priority 0; pkttype broadcast ether type ip ip daddr 192.168.1.255 udp dport 21027 jump b-to-a } chain c { type filter hook ingress device eth2 priority 0; pkttype broadcast ether type ip ip daddr 192.168.2.255 udp dport 21027 counter jump c-to-b-a } chain b-to-a { ether saddr set $eth0mac ip daddr set 192.168.0.255 fwd to eth0 } chain c-to-b-a { ether saddr set $eth1mac ip daddr set 192.168.1.255 dup to eth1 goto b-to-a } }