nftables:セグメント間でブロードキャストパケットを複製します
4つの異なるネットワークセグメントに接続されたDebianバスターボックス(nftables 0.9.0、カーネル4.19)があります。これらのセグメントのうち3つは、UDPポート21027へのブロードキャストを介して独自のローカル検出を実行するSyncthingを実行するデバイスのホームです。したがって、ブロードキャストはセグメントを横断しないため、デバイスはすべて互いに「見る」ことができません。バスターボックス自体は同期クラスターに参加しません。
BusterボックスでSyncthingの検出サーバーまたはリレーサーバーを実行することでこれを解決できますが、それらを使用しないように要求されています(構成および他のサイトにローミングするデバイスに関する理由)。したがって、nftablesベースのソリューションを検討しています。私の理解では、これは通常は行われていませんが、これを機能させるには、次のことを行う必要があります。
- UDP21027の着信パケットを照合します
- それらのパケットを、表示する必要のある他のセグメントインターフェイスにコピーします
- 新しいパケットの宛先IPを、新しいセグメントのブロードキャストアドレスと一致するように変更します(検出プロトコルが信頼できるため、送信元IPを保持します)。
- 再度複製されることなく、新しいブロードキャストを送信します
アタッチされたセグメントのうち3つだけがデバイスに参加します。すべてが/ 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で目的のインターフェイスに到達しているが、ボックス自体の入力フックに到達しており、セグメント上の他のデバイスからは見えないことを示しています。
ここで私たちが探している結果は実際に達成可能ですか?もしそうなら、どのルールで達成できますか?
回答
この場合、入力のみが必要であるため(nftablesにはまだ出力がありません)、netdevファミリーで(ipファミリーではなく)nftablesを使用することは可能です。入力フック内のおよびの動作は、tc-mirredのおよびとまったく同じです。dup
fwd
mirror
redirect
また、マイナーな詳細についても説明しました。これがなくても実際にルーティングされたパケットの場合と同様に、イーサネット送信元アドレスを新しいイーサネット発信インターフェイスのMACアドレスに書き換えます。したがって、インターフェイスのMACアドレスは事前に知っておく必要があります。必要な2つ(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
}
}
編集:後でこれを見つけた人のために、ABから受け入れられた答えは純粋にnftの解決策を与えます。
ABの提案のおかげで、これは純粋にnftablesルールではなくtcを使用して機能しています。
tc qdisc add dev eth2 ingress
tc filter add dev eth2 ingress \
protocol ip u32 \
match ip dst 192.168.2.255 \
match ip protocol 17 0xff \
match ip dport 21027 0xffff \
action nat ingress 192.168.2.255/32 192.168.0.255 \
pipe action mirred egress mirror dev eth0 \
pipe action nat ingress 192.168.0.255/32 192.168.1.255 \
pipe action mirred egress redirect dev eth1
tc qdisc add dev eth1 ingress
tc filter add dev eth1 ingress \
protocol ip u32 \
match ip dst 192.168.1.255 \
match ip protocol 17 0xff \
match ip dport 21027 0xffff \
action nat ingress 192.168.1.255/32 192.168.0.255 \
pipe action mirred egress redirect dev eth0
これらのフィルターについての私の理解は、UDPポート21027の着信ブロードキャストパケットと一致し、それらを他の目的のサブネットのそれぞれのブロードキャストアドレスにNATして(ingress
変更する送信元IPではなく宛先IPを変更nat egress
するため)、複製/リダイレクトすることです。他のインターフェイスの出力キューへのNATされたパケット。
tcの初心者であることは、問題を解決するための最良の方法ではないかもしれませんが、アナウンスブロードキャストをセグメント間で移動させるという点では機能します(そしてSyncthingは新しいノードを喜んで発見しています)。