%20%E3%81%A8%20NAT%20%E3%81%8A%E3%82%88%E3%81%B3%20VM%20%E3%81%AE%E3%83%96%E3%83%AA%E3%83%83%E3%82%B8%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9F%20Linux%20%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0.png)
私のセットアップ:
このセットアップには、2 つのネットワーク アダプターを備えた仮想マシン (VM) のホスト システムである物理マシンが 1 台だけあります。
1 つの NIC (eth0) は内部ネットワーク (LAN サブネット、例: 10.xxx/24) に接続され、内部トラフィックに使用されます。
もう一方の NIC (eth1) はパブリック インターネットに接続されています (パブリック ルーティング可能な IP が設定されています)。この接続は、パブリック インターネット トラフィックを VM の内部 IP にポート転送し (着信トラフィック)、VM が NAT 経由でパブリック インターネットにアクセスできるようにする (発信トラフィック) ために使用されます。
仮想マシンはLANサブネット内のIPアドレスを使用します(10.xxx/24、eth0と同じ)
VM (vnet0、vnet1、...) と LAN-NIC (eth0) の仮想ネットワーク インターフェイス用にブリッジ デバイス (br0) を設定しました。つまり、次のようになります。
- br0 は LAN サブネット (10.xxx/24) に IP アドレスを持っています
- eth0がブリッジに追加される
- vnet0、vnet1、...(VMによって使用される)はブリッジに動的に追加されます
問題点
LAN 内の通信は正常に動作します。また、VM ホストはパブリック IP 経由でアクセス可能であり、インターネットにアクセスできます。
私の問題は、VM がパブリック インターネットにもアクセスできるようにするための NAT 構成です。
シンプルな (S)NAT ルールを使用しようとしました:
iptables -t nat -I POSTROUTING -s 10.x.x.x/24 ! -d 10.x.x.x/24 -j SNAT --to-source y.y.y.102
一方、yyy102 は 2 番目の NIC (eth1) のパブリック ルーティング可能な IP です。
「ip_forward」と「bridge-nf-call-iptables」を有効にする必要があることがわかりました。
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
そうしないと、ブリッジされたパッケージは iptables によって処理されません。
現在、VM からのパケットは、次の iptables チェーンを通過するようです。
- 「FORWARD」(通常) - そこで受け入れます(-j ACCEPT、カウンターが上がります)
- 「PREROUTING」(nat) - そこで受け入れます(ポリシー ACCEPT、カウンターが上がります)
- 「POSTROUTING」(nat) - SNATルールに一致する
しかし、これまでのところ、何らかの理由で、すべてのパケットが PRE/POSTROUTING に到着するわけではないようです。
しかし、もっと興味深いのは、tcpdump -i eth0
パケットtcpdump -i eth1
(VM 内から外部 IP に ping を実行しようとした) が間違ったインターフェイス eth0 (=LAN-NIC) 経由で送信されているように見えることです。NAT ルールも適用されたため、送信元アドレスが他の NIC (eth1) の IP に変更されました。
質問:
パブリック IP を送信元アドレスとして NAT されたパケットを正しい NIC (eth1) 経由で出力するようにシステムを構成するにはどうすればよいですか?
何らかの方法で eth1 をブリッジ (br0) に追加する必要がありますか? その場合、パブリック IP アドレスを正しく割り当てるにはどうすればよいですか? 通常、IP はブリッジ デバイスで設定する必要があります。ブリッジにエイリアス アドレス (br0:0 のパブリック IP) を割り当てる必要がありますか?
構成の詳細
ホスト システム上のルーティング構成:
# ip r
default via y.y.y.126 dev eth1
10.x.x.0/24 dev br0 proto kernel scope link src 10.x.x.11
y.y.y.96/27 dev eth1 proto kernel scope link src y.y.y.102
- IP: yyy126 はパブリックインターネット用のルーターです。
- IP: yyy102はホストマシンのパブリックIPです
- IP: 10.xx11はホストマシンのLAN IPです
- サブネット: 10.xx0/24はLANです
- サブネット: yyy96/27 はパブリック IP サブネットです
NIC 構成:
# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.x.x.11 netmask 255.255.255.0 broadcast 10.x.x.255
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 0 (Ethernet)
RX packets 2139490 bytes 243693436 (232.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29085 bytes 2398024 (2.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 1000 (Ethernet)
RX packets 2521995 bytes 290600491 (277.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 383089 bytes 48876399 (46.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xdfa60000-dfa7ffff
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet y.y.y.102 netmask 255.255.255.224 broadcast y.y.y.127
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 1000 (Ethernet)
RX packets 2681476 bytes 597532550 (569.8 MiB)
RX errors 0 dropped 130 overruns 0 frame 0
TX packets 187755 bytes 21894113 (20.8 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xdfa00000-dfa1ffff
ブリッジ構成:
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.002590eb1900 no eth0
vnet0
そして iptables ルール:
# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
723 106K DROP udp -- * * y.y.y.0/24 0.0.0.0/0 udp spt:5404
586 40052 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
5 420 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
2 458 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 458 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1343 173K ACCEPT tcp -- * * 10.x.x.2 0.0.0.0/0 tcp spt:3389
1648 127K ACCEPT tcp -- * * 0.0.0.0/0 10.x.x.2 tcp dpt:3389
18 1040 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
18 1040 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 525 packets, 84016 bytes)
pkts bytes target prot opt in out source destination
# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 13 packets, 1218 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 5 packets, 420 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 13 packets, 880 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 14 packets, 920 bytes)
pkts bytes target prot opt in out source destination
5 300 SNAT all -- * * 10.x.x.0/24 !10.x.x.0/24 to:y.y.y.102
以下は、LAN インターフェイス カードでキャプチャされた NAT パケット (VM からの ping) です。
# tcpdump -i eth0
12:53:55.243350 IP y.y.y.102 > y.y.y.110: ICMP echo request, id 2, seq 5, length 40
「ip ルール」の出力:
# ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
答え1
VM の IP アドレスが 10.xxx/24 (ネットマスク 255.255.255.0) であることを確認します。
VMのデフォルトゲートウェイとして10.xx11(br0 IPアドレス)を設定します
物理ホストでIP転送を有効にする
SNAT を有効にするには:
iptables -t nat -A POSTROUTING -s 10.x.x.x/24 -o eth1 -j SNAT --to y.y.y.102
答え2
iptables -t nat -I POSTROUTING -s 10.xxx/24 ! -d 10.xxx/24 -j SNAT --to-source yyy102
これを変更する必要があります
iptables -t nat -I POSTROUTING --out-interface eth1 -j SNAT --to-source y.y.y.102
最初のルールによると、宛先が 10.xxx のパッケージのみを処理する必要があります。では、外部からネットワークへのトラフィックはどうでしょうか? (ソース - 世界中から、宛先はパブリック IP です :)
パブリック IP を送信元アドレスとして NAT されたパケットを正しい NIC (eth1) 経由で出力するようにシステムを構成するにはどうすればよいですか?
上記を読んでください。NAT ルールを変更するだけです。
何らかの方法で eth1 をブリッジ (br0) に追加する必要がありますか? その場合、パブリック IP アドレスを正しく割り当てるにはどうすればよいですか? 通常、IP はブリッジ デバイスで設定する必要があります。ブリッジにエイリアス アドレス (br0:0 のパブリック IP) を割り当てる必要がありますか?
何を、なぜ行うのかを理解していない場合は、絶対に行わないでください。内部インターフェイスと外部インターフェイスを分離してください。ルーティングのみを許可してください。
私は 5 年以上にわたってライブ (本番) 構成について説明してきました。OpenVPN トンネルを介したブリッジ リンクを含む 3 台のホスト サーバーと 25 台の VM でスムーズに動作しています。
答え3
Silvio の投稿は、同様の構成を機能させるのに役立ちました。彼の投稿に加えて、私が行う必要があったことがいくつかあります。
新しいバージョンの Linux カーネル (Redhat 7 など) では、ブリッジ カーネル モジュールを有効にする必要があります。
modprobe br_netfilter
そして、その変更をサーバーの再起動後も維持するには、/etc/modules-load.d/.confというファイルに同じ行を追加します。
br_netfilter を有効にしたら、VM への iptable 転送ルールも有効にする必要がありました。例:
iptables -I FORWARD -d 10.x.x.x/24 -j ACCEPT iptables -I FORWARD -s 10.x.x.x/24 -j ACCEPT
サーバー ホスティング施設内では 1 つのルートのみ必要だったため、SNAT の代わりにマスカレード ルールを使用しました。
iptables -t nat -A POSTROUTING -s <single-local-vm-ip>/32 -d <my-destination-subnet>/24 -p tcp -j MASQUERADE --to-ports 1024-65535