web-dev-qa-db-ja.com

KVMゲストはDNAT後に自分自身に接続できません

ネットワークの説明

仮想ホスティング環境(KVM):

ゲスト:

Ubuntu 14.04.5 LTS \n \l
Linux ari 3.8.0-29-generic #42~precise1-Ubuntu SMP Wed Aug 14 15:31:16 UTC 2013 i686 i686 i686 GNU/Linux

ホスト:

Ubuntu 14.04.3 LTS \n \l
Linux Host 3.13.0-74-generic #118-Ubuntu SMP Thu Dec 17 22:52:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

通信網:

          eth0 |----------| virbr63                    eth0 |----------|
---------------|   Host   |---------------------------------|  ari     |
  11.22.33.44  |----------| 192.168.63.1       192.168.63.2 |----------|
  • 11.22.33.44はパブリックIPアドレスです
  • ariは仮想マシン(ゲスト)です
  • Hostは物理マシン(仮想マシンホスト)です
  • eth0Hostの物理ネットワークカードです
  • virbr63は仮想ネットワークアダプターです

ホストにはiptablesルールがあります:

-I PREROUTING -p tcp -d 11.22.33.44 --dport 80 -j DNAT --to 192.168.63.2:8888

mydomain.comが11.22.33.44に解決されるとしましょう。 ariは、11.22.33.44に着信するすべてのHTTPリクエストを処理しています。カールmydomain.comは、インターネット上のどこからでも機能します。

問題

ariからHTTP経由でmydomain.comにアクセスしようとすると、機能しません(curlがハングします)。

これは、失敗したcurlの試行が(ホスト上の)tcpdumpでどのように表示されるかを示しています。

Host$ Sudo tcpdump -i virbr63 port 8888
22:03:15.541155 IP 192.168.63.2.42740 > 192.168.63.2.8888: Flags [S], seq 786111635, win 14600, options [mss1460,sackOK,TS val 1662005624 ecr 0,nop,wscale 5], length 0
22:03:15.541173 IP 192.168.63.2.42740 > 192.168.63.2.8888: Flags [S], seq 786111635, win 14600, options [mss1460,sackOK,TS val 1662005624 ecr 0,nop,wscale 5], length 0

これは数秒ごとに繰り返されます。

これは、(外部からの)成功した​​curl試行が(ホスト上の)tcpdumpでどのように見えるかです:

Host$ Sudo tcpdump -i virbr63 port 8888
21:59:10.924031 IP external.xxx.47812 > 192.168.63.2.8888: Flags [S], seq 2881442181, win 29200, options [mss 1420,sackOK,TS val 4022859071 ecr 0,nop,wscale 7], length 0
21:59:10.924339 IP 192.168.63.2.8888 > external.xxx.47812: Flags [S.], seq 1044842547, ack 2881442182, win 14480, options [mss 1460,sackOK,TS val 1661944471 ecr 4022859071,nop,wscale 5], length 0
21:59:10.968371 IP external.xxx.47812 > 192.168.63.2.8888: Flags [.], ack 1, win 229, options [nop,nop,TS val 4022859117 ecr 1661944471], length 0
21:59:10.976415 IP external.xxx.47812 > 192.168.63.2.8888: Flags [P.], seq 1:72, ack 1, win 229, options [nop,nop,TS val 4022859117 ecr 1661944471], length 71
21:59:10.976683 IP 192.168.63.2.8888 > external.xxx.47812: Flags [.], ack 72, win 453, options [nop,nop,TS val 1661944484 ecr 4022859117], length 0
21:59:10.977985 IP 192.168.63.2.8888 > external.xxx.47812: Flags [P.], seq 1:909, ack 72, win 453, options [nop,nop,TS val 1661944484 ecr 4022859117], length 908
21:59:11.025271 IP external.xxx.47812 > 192.168.63.2.8888: Flags [.], ack 909, win 243, options [nop,nop,TS val 4022859175 ecr 1661944484], length 0
21:59:11.030033 IP external.xxx.47812 > 192.168.63.2.8888: Flags [F.], seq 72, ack 909, win 243, options [nop,nop,TS val 4022859175 ecr 1661944484], length 0
21:59:11.030375 IP 192.168.63.2.8888 > external.xxx.47812: Flags [F.], seq 909, ack 73, win 453, options [nop,nop,TS val 1661944497 ecr 4022859175], length 0
21:59:11.075205 IP external.xxx.47812 > 192.168.63.2.8888: Flags [.], ack 910, win 243, options [nop,nop,TS val 4022859223 ecr 1661944497], length 0
  • external.xxxは、リクエストを行っているIPアドレスの逆引きDNSです

これは監視設定なので、Hostの変更をできるだけ少なくするソリューションを探しています。できれば、ホストでの変更はなく、ari(ゲスト)にパケットを受け入れてネットワーク経由で応答をルーティングするように説得するだけです。

非ソリューション

私の問題を解決しないもの

Ari:8888に直接アクセスする

これは監視設定であり、全体の目的は11.22.33.44:80が機能するかどうかをテストすることであるため、これは役に立ちません。

別のゲスト(仮想マシン)からのアクセス

(同じネットワーク192.168.63.0/24からも)機能しますが、問題は解決しません。

私が試したものと機能しないもの

同様の質問

私は次の質問と回答を見てきました:

ローカルホストからのDNAT(127.0.0.1)

KVMゲストはホストに接続できませんが、その逆は機能します

accept_local

ari$ Sudo sysctl -w net.ipv4.conf.eth0.accept_local=1

それは問題を解決せず、tcpdumpの出力を変更しません。

route_localnet

ari$ Sudo sysctl -w net.ipv4.conf.eth0.route_localnet=1

それは問題を解決せず、tcpdumpの出力を変更しません。

rp_filter

ari$ Sudo sysctl -w net.ipv4.conf.eth0.rp_filter=0

それは問題を解決せず、tcpdumpの出力を変更しません。

ariの2番目の(仮想)ネットワークインターフェイス

IPアドレスeth0:1で2番目のネットワークインターフェース192.168.63.200を追加してみました。 192.168.63.2:8888から192.168.63.200にアクセスすると、同じ方法で失敗します。

17:42:08.746328 IP 192.168.63.200.41676 > 192.168.63.2.8888: Flags [S], seq 3211292625, win 14600, options [mss 1460,sackOK,TS val 1744488483 ecr 0,nop,wscale 5], length 0
17:42:08.746351 IP 192.168.63.200.41676 > 192.168.63.2.8888: Flags [S], seq 3211292625, win 14600, options [mss 1460,sackOK,TS val 1744488483 ecr 0,nop,wscale 5], length 0

編集:同様の解決策

Kupsonの答えの後、私はここで非常によく似た解決策を見つけました:

http://idallen.com/dnat.txt (「多くのクライアント-SNATが多すぎます」を検索してください)。それは持っています:

iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -d 172.16.0.0/24 -m conntrack --ctstate DNAT  -j SNAT --to 172.16.0.254
2
Mate

考えられる解決策の1つは、ホストでSNATを使用してパケットの送信元アドレスを変更し、それらを「ari」VMに転送することです。これは最もパフォーマンスの高いソリューションではありませんが、シンプルで多くのセットアップに十分対応できます。

# fixup chain
iptables -t nat -N fixup-snat
iptables -t nat -A fixup-snat -m conntrack --ctstate DNAT -j MASQUERADE

# please select proper network ranges and NIC names below
iptables -t nat -I POSTROUTING -s 192.168.63.0/24 -d 192.168.63.0/24 -o virbr63 -j fixup-snat

これを単一のiptablesルールにマージできます。わかりやすくするために、別のチェーンを使用することをお勧めします。

また、ブリッジインターフェイスでiptablesによるパケットの処理を無効にする必要があります。

sysctl -w net.bridge.bridge-nf-call-arptables=0
sysctl -w net.bridge.bridge-nf-call-ip6tables=0
sysctl -w net.bridge.bridge-nf-call-iptables=0

それらをDebianシステムで再起動しても存続させるには、/etc/sysctl.confファイルを編集するか、/etc/sysctl.d/ディレクトリに新しいファイルを作成してください。

1
kupson