ステートレスNATは、グローバルネットワーク名前空間の物理ネットワークアダプタ(仮想ネットワークアダプタの接続ペアを介して)から特別なネットワーク名前空間で実行されているサービスへの2つのUDP接続用に設定する必要があります。これは、カーネルを含むLinux(Debian)を実行している産業用デバイスのIntel Atom(CPU)で実行する必要があります。5.9.7。
設定する必要があるネットワーク構成のシナリオは次のとおりです。
===================== =====================================================
|| application CPU || || communication CPU ||
|| || || ||
|| || || global namespace | nsprot1 namespace ||
|| || || | ||
|| enp4s0 || || enp1s0 | enp3s0 ||
|| 0.0.0.5/30 ========== 0.0.0.6/30 | 192.168.2.15/24 =======
|| || || | ||
|| UDP port 50001 || || UDP port 50001 for sv1 | TCP port 2404 for sv2 ||
|| UDP port 50002 || || UDP port 50002 for sv1 | ||
|| UDP port 53401 || || UDP port 50401 for sv1 | ||
|| UDP port 53402 || || UDP port 50402 for sv1 | ||
|| || || | ||
|| || || vprot0 | vprot1 ||
|| || || 0.0.0.16/31 --- 0.0.0.17/31 ||
|| || || | ||
|| UDP port 53404 || || UDP port 50404 for sv2 - UDP port 50404 for sv2 ||
|| UDP port 53441 || || UDP port 50441 for sv2 - UDP port 50441 for sv2 ||
===================== =====================================================
アプリケーションCPUは常に最初に起動し、sv1
IPアドレスを持つ物理ネットワークアダプタを介して通信CPUのサービスとサービスと通信するために複数のUDPポートを開きます。sv2
enp4s0
0.0.0.5
アプリケーションCPUで実行したときの出力は次ss --ipv4 --all --numeric --processes --udp
のとおりです。
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 0.0.0.0:50001 0.0.0.0:* users:(("sva",pid=471,fd=5))
udp UNCONN 0 0 0.0.0.0:50002 0.0.0.0:* users:(("sva",pid=471,fd=6))
udp ESTAB 0 0 0.0.0.5:53401 0.0.0.6:50401 users:(("sva",pid=471,fd=12))
udp ESTAB 0 0 0.0.0.5:53402 0.0.0.6:50402 users:(("sva",pid=471,fd=13))
udp ESTAB 0 0 0.0.0.5:53404 0.0.0.6:50404 users:(("sva",pid=471,fd=19))
udp ESTAB 0 0 0.0.0.5:53441 0.0.0.6:50441 users:(("sva",pid=471,fd=21))
通信CPUが2番目に起動し、最後に2つのサービスが実行されます。
sv1
グローバルネームスペースからそしてsv2
特別なネットワークネームスペースにありますnsprot1
。
ss --ipv4 --all --numeric --processes --udp
通信CPUのグローバルネームスペースで実行した結果は次のとおりです。
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 0.0.0.0:50001 0.0.0.0:* users:(("sv1",pid=812,fd=18))
udp UNCONN 0 0 0.0.0.6:50002 0.0.0.0:* users:(("sv1",pid=812,fd=17))
udp UNCONN 0 0 0.0.0.6:50401 0.0.0.0:* users:(("sv1",pid=812,fd=13))
udp UNCONN 0 0 0.0.0.6:50402 0.0.0.0:* users:(("sv1",pid=812,fd=15))
ip netns exec nsprot1 ss --ipv4 --all --numeric --processes --udp
(名前空間)の出力は次nsprot1
のとおりです。
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp ESTAB 0 0 0.0.0.17:50404 0.0.0.5:53404 users:(("sv2",pid=2421,fd=11))
udp ESTAB 0 0 0.0.0.17:50441 0.0.0.5:53441 users:(("sv2",pid=2421,fd=12))
sysctl
通常、すべての物理ネットワークアダプタにはIPv4転送が有効になっています。
ブロードキャストとマルチキャスト配信だけが必要でも望ましくないため、無効になります。
次のコマンドを使用して、通信CPUのネットワーク構成を設定します。
ip netns add nsprot1
ip link add vprot0 type veth peer name vprot1 netns nsprot1
ip link set dev enp3s0 netns nsprot1
ip address add 0.0.0.16/31 dev vprot0
ip netns exec nsprot1 ip address add 0.0.0.17/31 dev vprot1
ip netns exec nsprot1 ip address add 192.168.2.15/24 dev enp3s0
ip link set dev vprot0 up
ip netns exec nsprot1 ip link set vprot1 up
ip netns exec nsprot1 ip link set enp3s0 up
ip netns exec nsprot1 ip route add 0.0.0.4/30 via 0.0.0.16 dev vprot1
次のコマンドを使用してネットワークアドレス変換を設定します。
nft add table ip prot1
nft add chain ip prot1 prerouting '{ type nat hook prerouting priority -100; policy accept; }'
nft add rule prot1 prerouting iif enp1s0 udp dport '{ 50404, 50441 }' dnat 0.0.0.17
nft add chain ip prot1 postrouting '{ type nat hook postrouting priority 100; policy accept; }'
nft add rule prot1 postrouting ip saddr 0.0.0.16/31 oif enp1s0 snat 0.0.0.6
出力はnft list table ip prot1
次のとおりです
table ip prot1 {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
iif "enp1s0" udp dport { 50404, 50441 } dnat to 0.0.0.17
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 0.0.0.16/31 oif "enp1s0" snat to 0.0.0.6
}
}
グローバルネームスペースでさらに定義されます。ただテーブルには以下inet filter
が含まれます。
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
このNAT構成は、ステートフルNAT用です。これはポート番号を持つUDPチャネルで機能し、50404
最後に開始されて53404
からUDPパケットをsv2
開いて送信します。このパケットは、グローバルネームスペースのフックにソースネットワークアドレス変換を適用します。アプリケーションCPUサービスはUDPパケットをからに送信します。 UDP パケットが のルールを転送していません。後で見つけたように、接続追跡を介して直接送信されました。0.0.0.17:50404
0.0.0.5:53404
postrouting
enp1s0
sva
0.0.0.5:53404
0.0.0.6:50404
0.0.0.17:50404
prerouting
dnat
0.0.0.17
0.0.0.17
ただし、このステートフルNAT設定は、ポート番号50441
とUDPチャネルには適用されません534441
。原因は、sva
サービスが開始される前にアプリケーションCPUが複数のUDPパケットを送信し、宛先ポートが0.0.0.5:53441
ネットワーク名前空間に開いているためです。 ICMP は宛先ポートに接続できないことを返します。目的地の港がまだ開いていないことを考えると、これは驚くべきことではありません。残念ながら、サービスが開始され、両方のUDPポートが開かれるまでUDPパケットがサービスから送信されるのを防ぐ方法はありません。このサービスは、接続状態に関係なく定期的に送信し、時にはさらに自発的なUDPパケットをトリガします。0.0.0.6:50441
sv2
nsprot1
sva
sv2
sva
0.0.0.5:53441
0.0.0.6:50441
したがって、この構成の問題はステートフルNATのようです。これは、フックdnat
のルールprerouting
がネットワークネームスペースで開かれる宛先ポートではまだ使用されていないためですnsprot1
。 UDP パケットはとにかくルーティングされ続けるため、0.0.0.6:50441
UDP パケットが破棄され、宛先ポートに接続できないことを示す ICMP が返されます。
したがって、解決策はStateless NATを使用することです。したがって、次のコマンドも実行されました。
nft add table ip raw
nft add chain ip raw prerouting '{ type filter hook prerouting priority -300; policy accept; }'
nft add rule ip raw prerouting udp dport '{ 50404, 50441, 53404, 53441 }' notrack
しかし、結果は予想と異なっていた。入力インターフェイスと宛先ポートからの着信UDPパケットの場合、宛先prerouting
アドレスをからに変更する規則0.0.0.6
はまだ考慮されていません。0.0.0.17
enp1s0
50404
50441
以下は私が実行したものです。
nft add table ip filter
nft add chain filter trace_in '{ type filter hook prerouting priority -301; }'
nft add rule filter trace_in meta nftrace set 1
nft add chain filter trace_out '{ type filter hook postrouting priority 99; }'
nft add rule filter trace_out meta nftrace set 1
nft monitor trace
トレースを見ると、ルールがnotrack
考慮されましたが、宛先ポートを持つUDPパケットがフックに50441
直接転送されることがわかります。input
理由はわかりません。
私は次のことを非常に長い間非常に注意深く研究しました。
- NFTハンドブック(上から下に何度も完全にお読みください)
- nftables wiki(ほとんどのページが完了しました)
- ArchWikiのnftables
- また、ネットワークネームスペースの使用とネットワークアドレス変換に関する他の多くのWebページがあります。
Wiresharkを使用してさまざまな設定を試しましたが、ポートを持つUDPチャネルで動作し、宛先ポートが開かれる前にUDPパケットを送信するnft monitor trace
ソリューションが見つかりませんでした。50441
53441
sva
0.0.0.17:50441
アプリケーションCPUでサービスを手動で終了しsva
、通信CPUでネットワーク構成を設定し、両方のサービスを開始してからsv1
、sv2
最後にsva
通信CPUで開いているすべてのUDPポートでサービスを手動で再起動すると、ステートフルNAT構成が適用されます。 。 。ただし、基本的にこれらのサービス開始シーケンスは工業用機器では実行できません。アプリケーションサービスは、sva
通信サービスが通信する準備ができているかどうかとは無関係に実行する必要があります。
宛先ポートのオープン状態に関係なく、2つのUDPチャネルに対してステートレスNATを持つために必要なコマンド(チェーン/ルール)は何ですか0.0.0.5:53404 - 0.0.0.17:50404
?0.0.0.5:53441 - 0.0.0.17:50441
PS:サービスはsv2
デバイス構成に基づいて開始することも、NATおよびネットワーク名前空間なしでグローバル名前空間で他の物理ネットワークアダプタを使用することもできます。このネットワーク構成では、3 つのサービス間の UDP 通信にまったく問題はありません。
ベストアンサー1
数時間にわたってドキュメント、チュートリアル、さまざまなWebページに関するアドバイス、多くの実験、深く包括的なネットワーク、およびネットフィルタの監視と分析を読んだ後、ついにソリューションを見つけました。
nft add table ip prot1
nft add chain ip prot1 prerouting '{ type filter hook prerouting priority -300; policy accept; }'
nft add rule ip prot1 prerouting iif enp1s0 udp dport '{ 50404, 50441 }' ip daddr set 0.0.0.17 notrack accept
nft add rule ip prot1 prerouting iif vprot0 ip saddr 0.0.0.17 notrack accept
nft add chain ip prot1 postrouting '{ type filter hook postrouting priority 100; policy accept; }'
nft add rule ip prot1 postrouting oif enp1s0 ip saddr 0.0.0.17 ip saddr set 0.0.0.6 accept
これWebフィルタフック次のガイドラインを理解するには、まずページを開いて読む必要があります。
コマンドの使用方法:
- ㅏWebフィルタ テーブル
ip
(IPv4)というプロトコルに追加されましたprot1
。 - ㅏチェーン優先順位としてフックタイプ名テーブルに追加されます
prot1
。接続追跡をバイパスするには、これより低い優先順位番号を使用することが重要です。これは、優先順位の低い宛先ネットワークアドレス変換タイプチェーンの使用を排除します。prerouting
filter
prerouting
-300
-200
conntrack
nat
- ㅏフィルター ルールプロトコルタイプまたはの入力インターフェイスから受信したIPv4パケットにのみ適用
prot1
されるテーブルチェーンに追加され、パケットの宛先をからに変更し、このUDPパケットへの接続を有効にします。実際には、通信CPUのサービスのためにアプリケーションCPUのサービスから受信したUDPパケットをできるだけ早く次のフック(この場合はフック)に転送する必要はありませんが、決定は明示的に指定されます。prerouting
i
i
f
enp1s0
udp
d
port
50404
50441
ip
d
addr
0.0.0.6
0.0.0.17
no track
accept
sva
sv2
forward
- 一秒フィルター ルール
prot1
チェーンにテーブルに追加prerouting
、次にのみ適用されます。みんなi
プロトコルタイプ(、、...)に関係なく、入力インターフェイスから受信したIPv4パケットには、パケットを有効にしたi
接続のソースがあります。もちろん、適切な送信元または宛先ポート番号を使用してUDPパケットのみをフィルタリングすることは可能ですが、この追加の制限はここでは必要ではなく、この規則はサービスによってまだ開かれていない宛先ポートで再送信されるICMPパケットにも適用されます。現在は実行されません。暗黙的なデフォルト値を使用する代わりに明示的に判定を再指定すると、パケットはできるだけ早くフックに転送されます。f
vprot0
udp
icmp
ip
s
addr
0.0.0.17
no track
0.0.0.17
0.0.0.5
sv2
accept
continue
forward
- 一秒チェーン優先順位としてフックタイプ名テーブルに追加されます
prot1
。接続追跡をバイパスするUDP(およびICMP)パケットに送信元アドレス変換を適用するには、タイプチェーンの代わりにタイプチェーンを使用することが重要です。postrouting
filter
postrouting
100
filter
nat
- ㅏフィルター ルールessでパケットのソースを変更するソースを使用して、プロトコルタイプ(、、...)に関係なく、出力インターフェイスから送信されたIPv4パケットにのみ適用される
prot1
2番目のチェーンをテーブルに追加します。通信CPUのサービスで受信されたUDPパケットは、実際にはできるだけ早くアプリケーションCPUのサービスに転送される必要はありませんが、この決定は再び明示的に指定されます。このルールは、サービスがまだ実行されていないために接続できない宛先ポートに送信されたICMPパケットの送信元アドレスを変更します。したがって、アプリケーションCPUは、両方のUDPチャネルの通信に異なるインタフェースを使用していることを決して認識しません。これは重要ではありませんが、満たす必要がある2番目の要件です。postrouting
o
i
f
enp1s0
udp
icmp
s
addr
0.0.0.17
ip
s
addr
0.0.0.17
0.0.0.6
accept
sv2
sva
0.0.0.6
0.0.0.17
sv2
0.0.0.6
非常に具体的なネットワーク構成と無状態のネットワーク変換を必要とするサービス間の通信タイプと、sva
実行sv2
する必要があるNATを検索するのは難しい作業です。いいえフックを使用してくださいnat
。