nftablesでLinuxをルーターとして使用する - 応答を渡さないチャック

nftablesでLinuxをルーターとして使用する - 応答を渡さないチャック

ルーターとして使用するLinuxシステムがあります。これには5つのネットワークインターフェースがあります。つまり、3つの独立したLANとそれらの間にルーティングされる2つのWANがあります。現在、デフォルトパスとして1つのWANだけがあり、他のWANは実際には何もしません。私は長年、iptablesとIPルールを使用して両方のWANが動作するように努めてきましたが、成功しませんでした。

私が経験している問題は次のとおりです。 WAN 2(NATが必要)を介してpingをルーティングしようとすると、私のpingはクライアントホストからLinuxシステムに送信され、LinuxシステムはWAN 2を介して正しく転送します。応答を再確認しますが、パケットをクライアントコンピュータに転送しません。多くの検索と読書に関する質問にもかかわらず、なぜ再度伝わらないのかわかりませんでした。 (WAN 1 は、NAT が外部ルータで実行されるため、NAT は不要です.)

数日前にiptablesからnftablesに切り替えました。なぜなら、a) 構成を読みやすくし、b) 実際にルール評価を追跡して、何が起こっているのかを確認できるからです。これで、今すぐ質問する時間が十分になったようです。

これは私のものです/etc/nftables.conf

table ip filter {
    chain INPUT {
            type filter hook input priority 0; policy accept;

            ip protocol icmp counter meta nftrace set 1

            # allow loopback
            iifname "lo" accept

            # allow established/related connections
            ct state {established, related} accept

            # allow ping
            ip protocol icmp accept

            # accept anything from local networks
            ip saddr {
                    172.23.0.0/24, # lan1
                    172.23.2.0/24, # routed through lan1
                    172.23.3.0/24, # routed through lan1
                    172.23.4.0/24, # lan2
                    172.23.5.0/24, # lan3
            } accept

            # ntp exploit protection
            udp sport ntp ct state {invalid, related, new, untracked} counter drop

            # accept SSH from anyone else
            ct state new tcp dport ssh accept

            # drop all other packets
            counter drop
    }

    chain FORWARD {
            type filter hook forward priority 0; policy accept;

            ip protocol icmp counter meta nftrace set 1

            # drop anything to old local network 172.23.1.0/24
            ip daddr 172.23.1.0/24 counter drop

            # accept all other packets
            counter accept
    }

    chain OUTPUT {
            type filter hook output priority 0; policy accept;

            # ntp exploit protection
            udp dport ntp ct state {invalid, related, untracked} counter drop
    }
}

table ip mangle {
    chain FORWARD {
            type filter hook forward priority -150; policy accept;

            ip protocol icmp counter meta nftrace set 1
    }

    chain OUTPUT {
            type filter hook output priority -150; policy accept;

            # send replies to WAN->HERE connections via the same route as where they were initiated from
            ct state related,established meta mark set ct mark
    }

    chain PREROUTING {
            type filter hook prerouting priority -150; policy accept;

            # trace ALL packets coming from enp6s0 (WAN 2)
            iifname enp6s0 counter meta nftrace set 1

            # send subsequent packets on forwarded connections via the same route as when they were initiated
            ct state related,established meta mark set ct mark

            # trace all packets with a packet mark
            meta mark != 0x0 counter meta nftrace set 1

            # all further processing is for new connections only - so everything else returns here
            ct state != new return

            # any new WAN->LAN connections from enp6s0 (WAN 2) go into route 3, for the initial and subsequent packets
            # the return on the end ensures we don't do any further processing, which checks outbound protocols
            iifname enp6s0 ct mark set 0x3 meta mark set 0x3 return

            # any new WAN->LAN connections from enp4s0 (WAN 1) shouldn't do further processing either
            iifname enp4s0 return

            # everything from this point onwards is for new outgoing LAN->WAN connections only

            # for testing - route specific protocols through WAN 2
            #tcp dport 443 ct mark set 0x3 meta mark set 0x3
            #tcp dport 80 ct mark set 0x3 meta mark set 0x3
            ip protocol icmp ct mark set 0x3 meta mark set 0x3 counter meta nftrace set 1
    }
}

table ip nat {
    chain POSTROUTING {
            type nat hook postrouting priority 100; policy accept;

            oifname enp6s0 counter meta nftrace set 1 masquerade
    }
}

ip -4 addr:(enp4s0はWAN 1、enp6s0はWAN 2、残りはLANです)

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.0.3/24 brd 192.168.0.255 scope global enp4s0
       valid_lft forever preferred_lft forever
3: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 172.23.4.3/24 brd 172.23.4.255 scope global enp5s0
       valid_lft forever preferred_lft forever
4: enp6s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet (redacted).117/22 brd 255.255.255.255 scope global enp6s0
       valid_lft forever preferred_lft forever
5: enp7s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    inet 172.23.5.3/24 brd 172.23.5.255 scope global enp7s0
       valid_lft forever preferred_lft forever
6: enp8s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 172.23.0.3/24 brd 172.23.0.255 scope global enp8s0
       valid_lft forever preferred_lft forever

ip route:

default via 192.168.0.1 dev enp4s0
(redacted).0/22 dev enp6s0 proto kernel scope link src (redacted).117 metric 204 mtu 1500
172.23.0.0/24 dev enp8s0 proto kernel scope link src 172.23.0.3
172.23.0.0/16 via 172.23.0.2 dev enp8s0
172.23.4.0/24 dev enp5s0 proto kernel scope link src 172.23.4.3
172.23.5.0/24 dev enp7s0 proto kernel scope link src 172.23.5.3 linkdown
192.168.0.0/24 dev enp4s0 proto kernel scope link src 192.168.0.3

ip route show table 3:

default via (redacted).1 dev enp6s0
(redacted).1 dev enp6s0 scope link src (redacted).117
172.23.0.0/24 dev enp8s0 proto kernel scope link src 172.23.0.3
172.23.0.0/16 via 172.23.0.2 dev enp8s0
172.23.4.0/24 dev enp5s0 proto kernel scope link src 172.23.4.3
172.23.5.0/24 dev enp7s0 proto kernel scope link src 172.23.5.3 linkdown
192.168.0.0/24 dev enp4s0 proto kernel scope link src 192.168.0.3

ip rule:

0:      from all lookup local
32764:  from all fwmark 0x3 lookup 3
32765:  from (redacted).117 lookup 3
32766:  from all lookup main
32767:  from all lookup default

nft monitor traceここで興味深いのは、クライアント(Windows)PCで8.8.8.8をpingするときの出力は次のとおりです。

trace id 8e85e085 ip mangle PREROUTING packet: iif "enp8s0" ether saddr dc:9f:db:16:42:b5 ether daddr 38:ea:a7:ab:f8:bc ip saddr 172.23.2.132 ip daddr 8.8.8.8 ip dscp cs0 ip ecn not-ect ip ttl 127 ip id 4170 ip length 60 icmp type echo-request icmp code 0 icmp id 1 icmp sequence 779
trace id 8e85e085 ip mangle PREROUTING rule ip protocol icmp ct mark set 0x00000003 mark set 0x00000003 counter packets 0 bytes 0 nftrace set 1 (verdict continue)
trace id 8e85e085 ip mangle PREROUTING verdict continue mark 0x00000003
trace id 8e85e085 ip mangle PREROUTING mark 0x00000003
trace id 8e85e085 ip mangle FORWARD packet: iif "enp8s0" oif "enp6s0" ether saddr dc:9f:db:16:42:b5 ether daddr 38:ea:a7:ab:f8:bc ip saddr 172.23.2.132 ip daddr 8.8.8.8 ip dscp cs0 ip ecn not-ect ip ttl 126 ip id 4170 ip length 60 icmp type echo-request icmp code 0 icmp id 1 icmp sequence 779
trace id 8e85e085 ip mangle FORWARD rule ip protocol icmp counter packets 0 bytes 0 nftrace set 1 (verdict continue)
trace id 8e85e085 ip mangle FORWARD verdict continue mark 0x00000003
trace id 8e85e085 ip mangle FORWARD mark 0x00000003
trace id 8e85e085 ip filter FORWARD packet: iif "enp8s0" oif "enp6s0" ether saddr dc:9f:db:16:42:b5 ether daddr 38:ea:a7:ab:f8:bc ip saddr 172.23.2.132 ip daddr 8.8.8.8 ip dscp cs0 ip ecn not-ect ip ttl 126 ip id 4170 ip length 60 icmp type echo-request icmp code 0 icmp id 1 icmp sequence 779
trace id 8e85e085 ip filter FORWARD rule ip protocol icmp counter packets 0 bytes 0 nftrace set 1 (verdict continue)
trace id 8e85e085 ip filter FORWARD rule counter packets 8 bytes 452 accept (verdict accept)
trace id 8e85e085 ip nat POSTROUTING packet: oif "enp6s0" ip saddr 172.23.2.132 ip daddr 8.8.8.8 ip dscp cs0 ip ecn not-ect ip ttl 126 ip id 4170 ip length 60 icmp type echo-request icmp code 0 icmp id 1 icmp sequence 779
trace id 8e85e085 ip nat POSTROUTING rule oifname "enp6s0" counter packets 0 bytes 0 nftrace set 1 masquerade (verdict accept)
trace id eae785df ip mangle PREROUTING packet: iif "enp6s0" ether saddr 00:01:5c:86:1a:47 ether daddr 00:e0:4c:68:12:d9 ip saddr 8.8.8.8 ip daddr (redacted).117 ip dscp cs0 ip ecn not-ect ip ttl 56 ip id 39719 ip length 60 icmp type echo-reply icmp code 0 icmp id 1 icmp sequence 779
trace id eae785df ip mangle PREROUTING rule iifname "enp6s0" counter packets 0 bytes 0 nftrace set 1 (verdict continue)
trace id eae785df ip mangle PREROUTING rule ct state established,related mark set ct mark (verdict continue)
trace id eae785df ip mangle PREROUTING rule mark != 0x00000000 counter packets 0 bytes 0 nftrace set 1 (verdict continue)
trace id eae785df ip mangle PREROUTING verdict return mark 0x00000003
trace id eae785df ip mangle PREROUTING mark 0x00000003
trace id eae785df ip filter INPUT packet: iif "enp6s0" ether saddr 00:01:5c:86:1a:47 ether daddr 00:e0:4c:68:12:d9 ip saddr 8.8.8.8 ip daddr (redacted).117 ip dscp cs0 ip ecn not-ect ip ttl 56 ip id 39719 ip length 60 icmp type echo-reply icmp code 0 icmp id 1 icmp sequence 779
trace id eae785df ip filter INPUT rule ip protocol icmp counter packets 0 bytes 0 nftrace set 1 (verdict continue)
trace id eae785df ip filter INPUT rule ct state { } accept (verdict accept)

出力の関連行は次のとおりですconntrack -L

icmp     1 15 src=172.23.2.132 dst=8.8.8.8 type=8 code=0 id=1 src=8.8.8.8 dst=(redacted).117 type=0 code=0 id=1 mark=3 use=1

アウトバウンド部分には私のクライアントのローカルIPソースと私がpingする外部サーバーの宛先がありますが、インバウンド部分には私のクライアントのローカルIPではなく転送を実行するコンピュータの外部IPがあります。 (これが問題を示すかどうかはわかりません。)

ご覧のとおり、echo-r​​equestパケットはパケットタグとconntrackタグを3に正しく設定し、IPルールとルーティングテーブル3に基づいて正しい出力インターフェイスを選択し、正しく偽装してエコーを受信した後に明確に到着します。返信してください。オンラインでした。 echo-r​​eplyパケットはconntrackタグ(まだ3つ)をパケットタグに正しくコピーします。しかし、ご覧のとおり、元々実行していたNATを逆転させないので、再渡されるのではなくINPUTチェーンに入ります。私のクライアントコンピュータに。

何か落ちたと確信しています。 NATの仕事を元に戻すというルールがあるべきだと思います。ただし、LAN-> WANでNATを実行する方法を説明するすべてのページには、必要な唯一の規則があることがわかります。インバウンドパケットのバックルーティングの初期アウトマスカレーディングルール(多くのガイドでは、インバウンド接続のポート転送などの他のルールを提供しますが、これは単純なアウトバウンド接続には関係ありません)。

私は何を見逃していますか?

答え1

nftables Wikiでは、次のように言います。

「[...]ルールがなくても、事前パス/ポストパスチェーンを登録する必要があります。これらのチェーンは、応答方向から着信パケットに対してNATエンジンを呼び出すためです。」https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)

フィルタタイプの事前ルーティングチェーンがありますが、NATタイプではないようです。chain PREROUTING { type nat hook prerouting priority -150 ; } ファイルtable ip nat { [...] }にセクションを追加してみてください/etc/nftable.conf

答え2

問題は、NATポストルーティングチェーンの優先順位が-100であることです。 ~によるとnftables wiki、iptablesのDNATは優先順位-100で実行されますが、iptablesの優先順位(+)100に対応するSNATが必要だと思います。これが役に立つことを願っています。

関連情報