nftables, masquerade: パケットが無効なアウトバウンドインターフェイスを通過する

nftables, masquerade: パケットが無効なアウトバウンドインターフェイスを通過する

私がしたことはとても簡単でした。ポート転送を使用し、POSTROUTINGチェーンで偽装を有効にしました。

table inet nat {
    chain prerouting {
        type nat hook prerouting priority -100; policy accept;
        ip daddr 198.51.100.105 counter dnat to 10.8.0.105 comment "host.example.com"
    }
    
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        counter masquerade
    }
}

マイコンピュータには次のインターフェイスがあります。

1: lo
2: ens18
3: ens19
4: wg0

パスは次のとおりです。

default via 203.0.113.1 dev ens18 onlink
10.8.0.0/24 dev wg0 proto kernel scope link src 10.8.0.1
198.51.100.0/24 dev ens19 proto kernel scope link src 198.51.100.3
203.0.113.0/24 dev ens18 proto kernel scope link src 203.0.113.134

ルールは次のとおりです。

0:      from all lookup local
32764:  from all to 198.51.100.0/24 lookup subnets
32765:  from 198.51.100.0/24 lookup subnets
32766:  from all lookup main
32767:  from all lookup default

出力はip route get 198.51.100.105次のとおりです

local 198.51.100.105 dev lo table local src 198.51.100.3 uid 0
    cache <local>

出力ip route show table subnets

default via 198.51.100.1 dev ens19
198.51.100.0/24 dev ens19 scope link src 198.51.100.3

今pingするとき人々外部VPSまたは自宅のDSLアドレスから198.51.100.105ICMPパケットが受信されただけでなく、次のアドレスにも応答したことを確認できます。

ICMPリクエスト

root@debian:~# tcpdump -i ens19 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens19, link-type EN10MB (Ethernet), snapshot length 262144 bytes
21:35:51.686208 IP 192.0.2.2 > 198.51.100.105: ICMP echo request, id 14855, seq 1, length 64

ICMP応答

root@debian:~# tcpdump -i ens18 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens18, link-type EN10MB (Ethernet), snapshot length 262144 bytes
21:35:38.797502 IP 198.51.100.105 > 192.0.2.2: ICMP echo reply, id 5107, seq 1, length 64

しかし、見てわかるように、応答は間違ったインターフェイスから来ます。でなければなりませんが、ens19すでに使用中ですが、ens18その理由がわかりません。

  1. パス/ルールに従わないのはなぜですか?サブネットは198.51.100.0/24何の関係もなく、ens18他のVLANも同様です。

  2. nftablesは偽装されたパケットに対して他のアウトバウンドインターフェイスを強制できませんか?

助けてくれてありがとう。

編集する:出力は次のようにip -br link; ip -4 -br addr; ip -4 route; ip rule; ip rule show table subnetsなります。

ip -br link; ip -4 -br addr; ip -4 route; ip rule; ip rule show table subnets
lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
ens18            UP             a6:ea:02:1c:XX:XX <BROADCAST,MULTICAST,UP,LOWER_UP>
ens19            UP             ac:71:fe:18:XX:XX <BROADCAST,MULTICAST,UP,LOWER_UP>
wg0              UNKNOWN        <POINTOPOINT,NOARP,UP,LOWER_UP>
lo               UNKNOWN        127.0.0.1/8
ens18            UP             203.0.113.134/24
ens19            UP             198.51.100.3/24 198.51.100.100/24 198.51.100.101/24 198.51.100.102/24 198.51.100.103/24 198.51.100.104/24 198.51.100.105/24
wg0              UNKNOWN        10.8.0.1/24
default via 203.0.113.1 dev ens18 onlink
10.8.0.0/24 dev wg0 proto kernel scope link src 10.8.0.1
198.51.100.0/24 dev ens19 proto kernel scope link src 198.51.100.3
203.0.113.0/24 dev ens18 proto kernel scope link src 203.0.113.134
0:      from all lookup local
32764:  from all to 198.51.100.0/24 lookup subnets
32765:  from 198.51.100.0/24 lookup subnets
32766:  from all lookup main
32767:  from all lookup default
32764:  from all to 198.51.100.0/24 lookup subnets
32765:  from 198.51.100.0/24 lookup subnets

ラインバッカー

コマンド出力wg:

interface: wg0
  public key: XrSd2TftIpiL3zhXXX=
  private key: (hidden)
  listening port: 51820

peer: gZ89rFX6DvBtdeuYXXX=
  endpoint: 233.252.0.0:39126
  allowed ips: 10.8.0.0/24
  latest handshake: 20 seconds ago
  transfer: 3.42 MiB received, 4.08 MiB sent

コマンド出力:systemctl status [email protected]

[email protected] - WireGuard via wg-quick(8) for wg0
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; preset: enabled)
     Active: active (exited) since Sat 2023-08-05 23:42:48 CEST; 14h ago
       Docs: man:wg-quick(8)
             man:wg(8)
             https://www.wireguard.com/
             https://www.wireguard.com/quickstart/
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
    Process: 690 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
   Main PID: 690 (code=exited, status=0/SUCCESS)
        CPU: 27ms

Aug 05 23:42:48 debian systemd[1]: Starting [email protected] - WireGuard via wg-quick(8) for wg0...
Aug 05 23:42:48 debian wg-quick[690]: [#] ip link add wg0 type wireguard
Aug 05 23:42:48 debian wg-quick[690]: [#] wg setconf wg0 /dev/fd/63
Aug 05 23:42:48 debian wg-quick[690]: [#] ip -4 address add 10.8.0.1/24 dev wg0
Aug 05 23:42:48 debian wg-quick[690]: [#] ip link set mtu 1420 up dev wg0
Aug 05 23:42:48 debian systemd[1]: Finished [email protected] - WireGuard via wg-quick(8) for wg0.

サーバー:/etc/wireguard/wg0.conf

[Interface]
Address = 10.8.0.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = 8BspU4XXX=

[Peer]
PublicKey = gZ89rFX6DvBtdeuYXXX=
AllowedIPs = 10.8.0.0/24
Endpoint = 233.252.0.0:58642

ピア: /etc/wireguard/wg0.conf

[Interface]
# Client Private Key
PrivateKey = iO00+qQDXXX=
Address = 10.8.0.107/24

[Peer]
# Server Public Key
PublicKey = XrSd2TftIpiL3zhXXX=
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
Endpoint = 198.51.100.3:51820

答え1

注意と調整(混乱によるものかもしれません):

  • WireGuardピアが一致するために10.8.0.107の代わりに10.8.0.105を使用するとします。nftablesルールセット。
  • 233.252.0.0はシミュレーションで問題を引き起こす可能性があります(特に次の場合)。仲間)マルチキャストアドレスだからです。以下では192.0.2.233を使用します(192.0.2.2とネットワーク関係はありません)。

この質問は、ローカルトラフィックだけでなく転送にdnatルールを使用する問題を解決することです。最後に修正されたWireGuardトンネルエンベロープにも隠された問題があります。

pingテスト(事前ルーティングで発生する実際のdnatとレスポンスで発生するマスキング解除を含む)によるルーティングスタックの動作は、カーネルにどのパスを問い合わせるかを問い合わせる次の2つのコマンドにまとめることができます。使用:

# ip route get from 192.0.2.2 iif ens19 to 10.8.0.105
10.8.0.105 from 192.0.2.2 dev wg0 
    cache iif ens19 
# ip route get from 10.8.0.105 iif wg0 to 192.0.2.2
192.0.2.2 from 10.8.0.105 via 203.0.113.1 dev ens18 
    cache iif wg0 

ここでは、応答が間違ったインターフェイスを使用していることがわかります。アドレスが書き換えられます。つながるアイテムの内容:上記に表示されていなくても、198.51.100.105です。

これは不足しているルールが原因で発生します。any from(returns)ワークグループ0テーブルを使用する必要がありますサブネット。次に修正されました:

ip rule add iif wg0 lookup subnets

これも問題を解決しました。rp_filter=1RTNETLINK answers: Invalid cross-device link上記の最初のパステストは通常​​追加する必要がありますが、失敗します。ワークグループ0パスもこの表にあります。

今与えられた:

# ip route get from 10.8.0.105 iif wg0 to 192.0.2.2
192.0.2.2 from 10.8.0.105 via 198.51.100.1 dev ens19 table subnets 
    cache iif wg0 

これで、pingテストは正常に動作します。


追加の隠しWireGuardエンベロープルーティングの問題があります。

コンビネーション:

  • 有効ではありません厳格なリバースパス転送(RFC 3704)
  • ピアが最初にサーバーに接続するようにします(最後の追加の質問を参照)。
  • (少なくとも)カーネルの実装は、もともと接触していたのと同じソースを使用して応答する必要があると判断します。

WireGuardの動作を許可しますping 10.8.0.1仲間応答が受信され、その後のWireGuardトラフィックは同じエンベロープアドレスを使用し続けることができます。

ローカル(ルーティングされていない)フローのソースアドレスが宣言されていない場合、ルーティングスタックは指定されたパスにどのアドレスを使用するべきかを把握する必要があります。これは、ソケットが通常バインドされていないままであるUDPの場合に特に重要です(つまり、ソースは0.0.0.0、つまりINADDR_ANYです)。 TCPサーバーの場合、後で作成された冗長ソケットはaccept(2)0.0.0.0にバインドされなくなり、正しいアドレスにバインドされるため、これは問題になりません。次に、このアドレスをルーティングスタックに提供します。ここで、WireGuard は UDP と INADDR_ANY を使用します。特に198.51.100.3にバインドされていません。これは、ソース0.0.0.0として表示され、発信元IPアドレスの確認がカーネルのルーティングスタックに残されることを意味します。

もし仕える人WireGuardは常に最初のパケットを開始します(代わりに仲間これにより、198.51.100.3の代わりに203.0.113.134が使用されます。ルーティングスタックには特定の項目はありません。IPルール0.0.0.0の場合:IPルール 32765: from 198.51.100.0/24 lookup subnets一致するものはなく、特別なポリシールーティングは適用されません。最後に、UDPパケットはens18を使用して203.0.113.134に進みます。

カーネル実装は、少なくともクエリされたのと同じアドレスを使用し続けるようです。これは信頼できず、UDPサービスを使用したマルチホーミングには特別なサポートが必要です(例:IP_PKTINFO)したがって、アプリケーションで。

WireGuardが追求した結果:

# ip route get from 198.51.100.105 to 192.0.2.233
192.0.2.233 from 198.51.100.105 via 198.51.100.1 dev ens19 table subnets uid 0 
    cache 

少なくともトラフィックを最初に開始した実際の結果であれば、次のようになります。

# ip route get from 0.0.0.0 to 192.0.2.233
192.0.2.233 via 203.0.113.1 dev ens18 src 203.0.113.134 uid 0 
    cache 

WireGuardトンネルマルチホーミングルーティング自体を実際に変更するには、L4固有のプロトコルルーティングルールを使用できます。

ip rule add iif lo ipproto udp sport 51820 lookup subnets

iif loローカルで開始された(配信されていない)トラフィックを表す特別な構文であり、インターフェイスに依存しませんlo。)

与える:

# ip route get from 0.0.0.0 ipproto udp sport 51820 to 192.0.2.233
192.0.2.233 via 198.51.100.1 dev ens19 table subnets src 198.51.100.3 uid 0 
    cache 

INADDR_ANYをソースとして使用するにもかかわらず、UDPソースポート51820が選択されます。サブネットルーティングテーブル。

関連情報