web-dev-qa-db-ja.com

なぜiptables NATがネットワーク名前空間で分離された透過プロキシ設定で発生しないのですか?

ホストに透過プロキシネットワークをセットアップしようとしています。

実際のクライアントとプロキシのターゲットは封じ込めですが、この実験では、netns(ネットワーク名前空間)で区切られた環境を使用します。

クライアントトラフィックをプロキシに透過的にリダイレクトするには、ポリシールーティングを使用します。

 Client (C)         Proxy (P)
 10.10.1.1/24      10.10.2.1/24
     veth0             veth0
      |                 |
   veth pair         veth pair
      |                 |
  -----------(Host)--------------
 client-veth0       proxy-veth0
 10.10.1.2/24      10.10.2.2/24
      |                 |            172.16.202.30
      +-----------------+-------------- enp4s0 ---- INTERNET

# Policy Routing on Host
# [Client->Proxy]
# ip rule:  from 10.10.1.0/24 iif client-veth0 lookup 100
# ip route: (100) default via 10.10.2.1 dev proxy-veth0
# [Proxy->Internet]
# ip route: (master) default via 172.16.202.1 dev enp4s0 proto static metric 100
# iptables: -t nat -A POSTROUTING -s 10.10.1.1/32 -o enp4s0 -j MASQUERADE
# [Internet->Proxy]
# ip rule:  from all to 10.10.1.0/24 iif enp4s0 lookup 100
# ip route: (100) default via 10.10.2.1 dev proxy-veth0
# [Proxy->Client]
# ip rule:  from all to 10.10.1.0/24 iif proxy-veth0 lookup 101
# ip route: (101) default via 10.10.1.1 dev client-veth0

問題は、クライアントから8.8.8.8にpingを実行すると、クライアントnetns内で、source ip masqueradingが発生しないiptablesマスカレードルールが一致せず、デフォルトで承諾。 enp4s0のtcpdumpは172.16.202.30 --> 8.8.8.8を表示すると思いますが、ソースIPマスカレードなしで10.10.1.1 --> 8.8.8.8を表示します。

SNATが発生しないことを明確にするために、インターネット回線でpcapを記録しました。 client_to_goolgeは、enp4s0外の別のマシンから記録されます。

$ tcpdump -r client_to_google -n
reading from file client_to_google, link-type EN10MB (Ethernet)
23:35:40.852257 IP 10.10.1.1 > 8.8.8.8: ICMP echo request, id 14867, seq 1, length 64
23:35:41.865269 IP 10.10.1.1 > 8.8.8.8: ICMP echo request, id 14867, seq 2, length 64

Iptables mangleテーブルをチェックすると、パケットは指定されたポリシーで流れます。

  PREROUTING: client-veth0, 10.10.1.1 --> 8.8.8.8
  POSTROUTING: proxy-veth0, 10.10.1.1 --> 8.8.8.8
  PREROUTING: proxy-veth0, 10.10.1.1 --> 8.8.8.8
  POSTROUTING: enp4s0, 10.10.1.1 --> 8.8.8.8

ただし、このproxy-veth0のようにiptables: -t nat -A POSTROUTING -s 10.10.10.1/32 -o proxy-veth0 -j MASQUERADEの出力インターフェイスのマスカレードルールを変更すると、マスカレードが発生します。つまり、10.10.2.2 --> 8.8.8.8パケットがキャプチャされます。

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
...
11       0     0 MASQUERADE  all  --  *      enp4s0  10.10.1.1            0.0.0.0/0
12       1    84 MASQUERADE  all  --  *      proxy-veth0  10.10.1.1            0.0.0.0/0

上記の表は、ルール#11 enp4s0出力条件がトリガーされなかったことを示しています。ルール#12は、ルール#11でのいくつかのテストの後に挿入されました。ルール#12は、proxy-veth0出力条件がトリガーされたことを示しています。 enp4s0マスターnicとproxy-veth0仮想インターフェイスとiptablesの間に違いはありますか?

コメントをいただければ幸いです。ありがとうございます。

1
Chul-Woong Yang

透過プロキシは少なくともICMPのルーターとして機能しているので、ICMPエコーを(veth0)からの経路でルーティングします。

問題を見つける

あなたの設定を再現して問題を目撃するとき、私は [〜#〜] trace [〜#〜] をホストに追加しましたiptables(レガシー、これは iptables-nftのバージョン )とわずかに異なる場合があります(フィルターテーブル(iptables -S )トレースに含めるには):

iptables -t raw -A PREROUTING -j TRACE

そして、単一のpingがカーネルログに表示されます(Hostが実際の初期ホストではない場合のヒント:sysctl -w net.netfilter.nf_log_all_netns=1):

TRACE: raw:PREROUTING:policy:2 IN=client-veth0 OUT= MAC=66:f2:08:79:d0:df:be:1e:05:c1:c1:4b:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=7200 DF PROTO=ICMP TYPE=8 CODE=0 ID=3508 SEQ=1 
TRACE: nat:PREROUTING:policy:1 IN=client-veth0 OUT= MAC=66:f2:08:79:d0:df:be:1e:05:c1:c1:4b:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=7200 DF PROTO=ICMP TYPE=8 CODE=0 ID=3508 SEQ=1 
TRACE: filter:FORWARD:policy:1 IN=client-veth0 OUT=proxy-veth0 MAC=66:f2:08:79:d0:df:be:1e:05:c1:c1:4b:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=7200 DF PROTO=ICMP TYPE=8 CODE=0 ID=3508 SEQ=1 
TRACE: nat:POSTROUTING:policy:2 IN=client-veth0 OUT=proxy-veth0 MAC=66:f2:08:79:d0:df:be:1e:05:c1:c1:4b:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=7200 DF PROTO=ICMP TYPE=8 CODE=0 ID=3508 SEQ=1 
TRACE: raw:PREROUTING:policy:2 IN=proxy-veth0 OUT= MAC=16:c9:3c:d4:ad:8c:8a:84:06:5d:88:e2:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=7200 DF PROTO=ICMP TYPE=8 CODE=0 ID=3508 SEQ=1 
TRACE: filter:FORWARD:policy:1 IN=proxy-veth0 OUT=enp4s0 MAC=16:c9:3c:d4:ad:8c:8a:84:06:5d:88:e2:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=61 ID=7200 DF PROTO=ICMP TYPE=8 CODE=0 ID=3508 SEQ=1 

同時に、ホストで conntrack -E を実行すると、一致が表示されます。

# conntrack -E
    [NEW] icmp     1 30 src=10.10.1.1 dst=8.8.8.8 type=8 code=0 id=3508 [UNREPLIED] src=8.8.8.8 dst=10.10.1.1 type=0 code=0 id=3508

どうした:

  • conntrack(NATを処理する)は、ルートについては考慮しません(例:conntrackデータベースにはインターフェースがありません)。アドレスについてのみです。
  • natテーブルはNEW状態のパケットのみを表示し、
  • conntrackがデータベースに新しいエントリを追加したのは、パケットがclient-veth0からproxy-veth0:POSTROUTINGルールに一致しない、
  • proxy-veth0からenp4s0へのルーティング時の2番目のラウンドは、パケットがconntrackおよびnatテーブルが再度呼び出されませんでした
  • パケットは、NATされていないインターネットに送信されます。

このconntrackの制限により、これまでのユースケースの一部が妨げられたため、追加機能が追加されました。

conntrackゾーン

ゾーンは、さまざまなハッシュに組み込まれ、接続タプルに加えてエントリを区別するために使用される、ネットワークデバイスに関連付けられた数値識別子です。

[...]

これは主に、同じアドレスを使用して複数のプライベートネットワークを接続するときに(残念ながらまれに発生します)、パケットを一連のvethデバイスとSNATの各ネットワークを介して一意のアドレスに渡し、その後「メイン」ゾーンを通過して、通常の非衝突パケットのように処理されるか、またはNATが発信インターフェイスに基づいてもう一度適用されます。

NAT処理を含む)conntrack機能をソートして複製することができますが、手動で実行して問題を一致させる必要があります。ここでルーティングトポロジー。

したがって、ここではconntrackの視点でのクライアント<->プロキシトラフィックを他のトラフィックから分割する必要があります。

プロキシ<->インターネットトラフィックも一般的なホストトラフィックから分割することをお勧めしますが、rawテーブルではゾーンをパケット、非NATトラフィックのみを認識するため、インターネット応答はすべて宛先172.16.202.30で到着します。とにかく、クライアント<->プロキシフローのように、両方の間でフローが重複することはないため、実際には必要ありません。

  • ゾーン0(0は特別なゾーンがないことを意味します):プロキシ<->インターネットトラフィックを伴う一般的なホストトラフィック。

    特別なことは何もありません。これがデフォルトです。

  • ゾーン1:クライアント<->プロキシトラフィック。 CT --zone ターゲットが使用されます。ここでの値は任意に選択され、この場合他の場所では必要ありません。

    iptables -t raw -A PREROUTING -i client-veth0 -j CT --zone 1
    iptables -t raw -A PREROUTING -i proxy-veth0 -d 10.10.1.0/24 -j CT --zone 1
    

正しい結果(両方のツールの出力をマージした)は次のとおりです。

TRACE: raw:PREROUTING:rule:2 IN=client-veth0 OUT= MAC=4e:e7:2f:3f:a3:6c:4a:b9:40:66:60:32:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
TRACE: raw:PREROUTING:policy:4 IN=client-veth0 OUT= MAC=4e:e7:2f:3f:a3:6c:4a:b9:40:66:60:32:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
TRACE: nat:PREROUTING:policy:1 IN=client-veth0 OUT= MAC=4e:e7:2f:3f:a3:6c:4a:b9:40:66:60:32:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
TRACE: filter:FORWARD:policy:1 IN=client-veth0 OUT=proxy-veth0 MAC=4e:e7:2f:3f:a3:6c:4a:b9:40:66:60:32:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
TRACE: nat:POSTROUTING:policy:2 IN=client-veth0 OUT=proxy-veth0 MAC=4e:e7:2f:3f:a3:6c:4a:b9:40:66:60:32:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
    [NEW] icmp     1 30 src=10.10.1.1 dst=8.8.8.8 type=8 code=0 id=4079 [UNREPLIED] src=8.8.8.8 dst=10.10.1.1 type=0 code=0 id=4079 zone=1
TRACE: raw:PREROUTING:policy:4 IN=proxy-veth0 OUT= MAC=86:c8:4b:5f:16:fc:ba:76:80:0f:20:7d:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
TRACE: nat:PREROUTING:policy:1 IN=proxy-veth0 OUT= MAC=86:c8:4b:5f:16:fc:ba:76:80:0f:20:7d:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
TRACE: filter:FORWARD:policy:1 IN=proxy-veth0 OUT=enp4s0 MAC=86:c8:4b:5f:16:fc:ba:76:80:0f:20:7d:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=61 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
TRACE: nat:POSTROUTING:rule:1 IN=proxy-veth0 OUT=enp4s0 MAC=86:c8:4b:5f:16:fc:ba:76:80:0f:20:7d:08:00 SRC=10.10.1.1 DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=61 ID=58185 DF PROTO=ICMP TYPE=8 CODE=0 ID=4079 SEQ=1 
    [NEW] icmp     1 30 src=10.10.1.1 dst=8.8.8.8 type=8 code=0 id=4079 [UNREPLIED] src=8.8.8.8 dst=172.16.202.30 type=0 code=0 id=4079
TRACE: raw:PREROUTING:policy:4 IN=enp4s0 OUT= MAC=5e:e8:0c:bf:96:d9:b2:e7:bc:df:1f:8e:08:00 SRC=8.8.8.8 DST=172.16.202.30 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=12099 PROTO=ICMP TYPE=0 CODE=0 ID=4079 SEQ=1 
TRACE: filter:FORWARD:policy:1 IN=enp4s0 OUT=proxy-veth0 MAC=5e:e8:0c:bf:96:d9:b2:e7:bc:df:1f:8e:08:00 SRC=8.8.8.8 DST=10.10.1.1 LEN=84 TOS=0x00 PREC=0x00 TTL=61 ID=12099 PROTO=ICMP TYPE=0 CODE=0 ID=4079 SEQ=1 
 [UPDATE] icmp     1 30 src=10.10.1.1 dst=8.8.8.8 type=8 code=0 id=4079 src=8.8.8.8 dst=172.16.202.30 type=0 code=0 id=4079
TRACE: raw:PREROUTING:rule:3 IN=proxy-veth0 OUT= MAC=86:c8:4b:5f:16:fc:ba:76:80:0f:20:7d:08:00 SRC=8.8.8.8 DST=10.10.1.1 LEN=84 TOS=0x00 PREC=0x00 TTL=60 ID=12099 PROTO=ICMP TYPE=0 CODE=0 ID=4079 SEQ=1 
TRACE: raw:PREROUTING:policy:4 IN=proxy-veth0 OUT= MAC=86:c8:4b:5f:16:fc:ba:76:80:0f:20:7d:08:00 SRC=8.8.8.8 DST=10.10.1.1 LEN=84 TOS=0x00 PREC=0x00 TTL=60 ID=12099 PROTO=ICMP TYPE=0 CODE=0 ID=4079 SEQ=1 
TRACE: filter:FORWARD:policy:1 IN=proxy-veth0 OUT=client-veth0 MAC=86:c8:4b:5f:16:fc:ba:76:80:0f:20:7d:08:00 SRC=8.8.8.8 DST=10.10.1.1 LEN=84 TOS=0x00 PREC=0x00 TTL=59 ID=12099 PROTO=ICMP TYPE=0 CODE=0 ID=4079 SEQ=1 
 [UPDATE] icmp     1 30 src=10.10.1.1 dst=8.8.8.8 type=8 code=0 id=4079 src=8.8.8.8 dst=10.10.1.1 type=0 code=0 id=4079 zone=1

ここで、新しいフローからの単一の最初のパケットは、2回のiptables 'natテーブルをトリガーしますが、最初は効果がありません。実際、conntrackは、最初のフローに追加の属性zone=1があるため、2つのフローがあると見なします。

1
A.B

これは通常のiptablesですNAT動作です。tcpdumpを使用して現在テストしているので、仮想マシンごとに3つの仮想マシンを使用して、SNATルールを設定しました

vm1(10.10.1.1)---> vm2(10.10.2.2)---> vm3(1.2.3.4)(パブリックIPアドレス)

次に、10.10.1.1から8.8.8.8にpingを実行し、3台すべてのマシンでtcpdumpを実行すると、結果は次のようになりました:vm2 10.10.1.1 ---> 8.8.8.8 on vm3 10.10.2.2 ---> 8.8.8.8

理論的には、私がvm4を持っている場合、1.2.3.4 ---> 8.8.8.8と表示されます。

プロキシ設定を見せていただけますか?

ボリス

0
Boris