web-dev-qa-db-ja.com

libvirtのゲストへのポートの転送/ KVM

NATを使用している場合、libvirt/KVMを実行しているサーバーのポートをVMの指定されたポートに転送するにはどうすればよいですか?

たとえば、ホストのパブリックIPは1.2.3.4です。ポート80を10.0.0.1に、ポート22を10.0.0.2に転送したい。

Iptablesルールを追加する必要があると思いますが、どこが適切で何を正確に指定する必要があるのか​​わかりません。

Iptables -Lの出力

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere            udp dpt:domain 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:domain 
ACCEPT     udp  --  anywhere             anywhere            udp dpt:bootps 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:bootps 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             10.0.0.0/24         state RELATED,ESTABLISHED 
ACCEPT     all  --  10.0.0.0/24          anywhere            
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Ifconfigの出力

eth0      Link encap:Ethernet  HWaddr 00:1b:fc:46:73:b9  
          inet addr:192.168.1.14  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::21b:fcff:fe46:73b9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:201 errors:0 dropped:0 overruns:0 frame:0
          TX packets:85 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:31161 (31.1 KB)  TX bytes:12090 (12.0 KB)
          Interrupt:17 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

virbr1    Link encap:Ethernet  HWaddr ca:70:d1:77:b2:48  
          inet addr:10.0.0.1  Bcast:10.0.0.255  Mask:255.255.255.0
          inet6 addr: fe80::c870:d1ff:fe77:b248/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:468 (468.0 B)

Ubuntu 10.04を使用しています。

35
steveh7

Ubuntu用libvirtの最新の安定版リリースはバージョン0.7.5です。これには、自動ネットワーク構成を容易にするいくつかの新しい機能(スクリプトフックやネットワークフィルターなど)がありません。つまり、Ubuntu 10.04 Lucid Lynxでlibvirt 0.7.5のポート転送を有効にする方法は次のとおりです。

これらのiptablesルールがうまくいくはずです:

iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

デフォルトのKVM NAT configは、上記の3番目と同様のルールを提供しますが、着信接続を受け入れるために不可欠なNEW状態を省略します。

これらのルールを追加するための起動スクリプトを作成し、注意しない場合、libvirt 0.7.5は独自のルールを挿入することでそれらを上書きします。したがって、これらのルールが起動時に適切に適用されるようにするには、libvirtが初期化されていることを確認する必要がありますbeforeルールを挿入します。

/etc/rc.localのexit 0行の前に、次の行を追加します。

(
# Make sure the libvirt has started and has initialized its network.
while [ `ps -e | grep -c libvirtd` -lt 1 ]; do
        sleep 1
done
sleep 10
# Set up custom iptables rules.
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT
) &

上記のsleep 10は、独自のルールを追加する前にlibvirtデーモンがiptablesルールを初期化する機会を得たことを確認するためのハックです。彼らがUbuntu用のlibvirtバージョン0.8.3をリリースするまで待つことができません。

38

ゲストがユーザーモードネットワークを使用しているときにポートリダイレクションをオンザフライで設定する方法があります

http://blog.adamspiers.org/2012/01/23/port-redirection-from-kvm-Host-to-guest/

詳細はここで確認できますが、便宜上、私が考え出した解決策を次に示します。

virsh qemu-monitor-command --hmp sles11 'hostfwd_add ::2222-:22'

このワンライナーは他の回答よりもはるかに簡単ですが、一部のシナリオ(ユーザーモードのネットワークスタック)でのみ機能します。

18
Adam Spiers

これを行うためのより「公式な」[1]方法は、libvirt Webサイトで説明されているようにフックスクリプトを作成することです。

http://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections

...基本的に、このスクリプトはKVMゲストが起動したときに呼び出されます。スクリプト自体は、適切なiptableルール(上記のIsaac Sutherlandの回答と同様)を「NEW」接続で追加しますホストとポートの正しい値でスクリプトを変更する必要があることに注意してください。

[1] libvirtのドキュメント自体には、これは一種のハックであると書かれていますが、図に進んでください

5
Antony Nguyen

KVM(libvirt)with "default network"(virbr0)を使用してポート転送を行うことができる「唯一の」方法は、@ Antony Nguyenによって通知されたハック/回避策を使用することです。 libvirt-hook-qem を使用できます。

このスレッドには、libvirt-hook-qemu: https://superuser.com/a/1475915/19584 を使用して、CentOS 7(および他のディストリビューション)でこの問題を解決する方法の完全な説明があります。

0
Eduardo Lucio