グローバルネットワークから特別なネットワークネームスペースへの2つのUDP接続に対してステートレスNATを設定する方法は?

グローバルネットワークから特別なネットワークネームスペースへの2つのUDP接続に対してステートレスNATを設定する方法は?

ステートレス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は常に最初に起動し、sv1IPアドレスを持つ物理ネットワークアダプタを介して通信CPUのサービスとサービスと通信するために複数のUDPポートを開きます。sv2enp4s00.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:504040.0.0.5:53404postroutingenp1s0sva0.0.0.5:534040.0.0.6:504040.0.0.17:50404preroutingdnat0.0.0.170.0.0.17

ただし、このステートフルNAT設定は、ポート番号50441とUDPチャネルには適用されません534441。原因は、svaサービスが開始される前にアプリケーションCPUが複数のUDPパケットを送信し、宛先ポートが0.0.0.5:53441ネットワーク名前空間に開いているためです。 ICMP は宛先ポートに接続できないことを返します。目的地の港がまだ開いていないことを考えると、これは驚くべきことではありません。残念ながら、サービスが開始され、両方のUDPポートが開かれるまでUDPパケットがサービスから送信されるのを防ぐ方法はありません。このサービスは、接続状態に関係なく定期的に送信し、時にはさらに自発的なUDPパケットをトリガします。0.0.0.6:50441sv2nsprot1svasv2sva0.0.0.5:534410.0.0.6:50441

したがって、この構成の問題はステートフルNATのようです。これは、フックdnatのルールpreroutingがネットワークネームスペースで開かれる宛先ポートではまだ使用されていないためですnsprot1。 UDP パケットはとにかくルーティングされ続けるため、0.0.0.6:50441UDP パケットが破棄され、宛先ポートに接続できないことを示す 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.17enp1s05040450441

以下は私が実行したものです。

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ソリューションが見つかりませんでした。5044153441sva0.0.0.17:50441

アプリケーションCPUでサービスを手動で終了しsva、通信CPUでネットワーク構成を設定し、両方のサービスを開始してからsv1sv2最後にsva通信CPUで開いているすべてのUDPポートでサービスを手動で再起動すると、ステートフルNAT構成が適用されます。 。 。ただし、基本的にこれらのサービス開始シーケンスは工業用機器では実行できません。アプリケーションサービスは、sva通信サービスが通信する準備ができているかどうかとは無関係に実行する必要があります。

宛先ポートのオープン状態に関係なく、2つのUDPチャネルに対してステートレスNATを持つために必要なコマンド(チェーン/ルール)は何ですか0.0.0.5:53404 - 0.0.0.17:504040.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フィルタフック次のガイドラインを理解するには、まずページを開いて読む必要があります。

コマンドの使用方法:

  1. Webフィルタ テーブルip(IPv4)というプロトコルに追加されましたprot1
  2. チェーン優先順位としてフックタイプ名テーブルに追加されますprot1。接続追跡をバイパスするには、これより低い優先順位番号を使用することが重要です。これは、優先順位の低い宛先ネットワークアドレス変換タイプチェーンの使用を排除します。preroutingfilterprerouting-300-200conntracknat
  3. フィルター ルールプロトコルタイプまたはの入力インターフェイスから受信したIPv4パケットにのみ適用prot1されるテーブルチェーンに追加され、パケットの宛先をからに変更し、このUDPパケットへの接続を有効にします。実際には、通信CPUのサービスのためにアプリケーションCPUのサービスから受信したUDPパケットをできるだけ早く次のフック(この場合はフック)に転送する必要はありませんが、決定は明示的に指定されます。preroutingiifenp1s0udpdport5040450441ip daddr0.0.0.60.0.0.17no trackacceptsvasv2forward
  4. 一秒フィルター ルールprot1チェーンにテーブルに追加prerouting、次にのみ適用されます。みんなiプロトコルタイプ(、、...)に関係なく、入力インターフェイスから受信したIPv4パケットには、パケットを有効にしたi接続のソースがあります。もちろん、適切な送信元または宛先ポート番号を使用してUDPパケットのみをフィルタリングすることは可能ですが、この追加の制限はここでは必要ではなく、この規則はサービスによってまだ開かれていない宛先ポートで再送信されるICMPパケットにも適用されます。現在は実行されません。暗黙的なデフォルト値を使用する代わりに明示的に判定を再指定すると、パケットはできるだけ早くフックに転送されます。fvprot0udpicmpip saddr0.0.0.17no track0.0.0.170.0.0.5sv2acceptcontinueforward
  5. 一秒チェーン優先順位としてフックタイプ名テーブルに追加されますprot1。接続追跡をバイパスするUDP(およびICMP)パケットに送信元アドレス変換を適用するには、タイプチェーンの代わりにタイプチェーンを使用することが重要です。postroutingfilterpostrouting100filternat
  6. フィルター ルールessでパケットのソースを変更するソースを使用して、プロトコルタイプ(、、...)に関係なく、出力インターフェイスから送信されたIPv4パケットにのみ適用されるprot12番目のチェーンをテーブルに追加します。通信CPUのサービスで受信されたUDPパケットは、実際にはできるだけ早くアプリケーションCPUのサービスに転送される必要はありませんが、この決定は再び明示的に指定されます。このルールは、サービスがまだ実行されていないために接続できない宛先ポートに送信されたICMPパケットの送信元アドレスを変更します。したがって、アプリケーションCPUは、両方のUDPチャネルの通信に異なるインタフェースを使用していることを決して認識しません。これは重要ではありませんが、満たす必要がある2番目の要件です。postroutingoifenp1s0udpicmpsaddr0.0.0.17ip saddr0.0.0.170.0.0.6acceptsv2sva0.0.0.60.0.0.17sv20.0.0.6

非常に具体的なネットワーク構成と無状態のネットワーク変換を必要とするサービス間の通信タイプと、sva実行sv2する必要があるNATを検索するのは難しい作業です。いいえフックを使用してくださいnat

おすすめ記事