libvirt / KVM でゲストにポートを転送する

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を使用しています。

答え1

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 設定では、上で示した 3 番目のルールに似たルールが提供されますが、着信接続を受け入れるために不可欠な NEW 状態が省略されます。

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

/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 がリリースされるのが待ちきれません。

答え2

ポートリダイレクトをオンザフライで設定する方法がありますゲストがユーザーモードネットワークを使用している場合、私はここでそれについてブログに書きました:

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

詳細はそちらで確認できますが、便宜上、私が考え出した解決策を以下に示します。

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

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

答え3

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

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

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

[1] libvirtのドキュメントでは、これは一種のハックであると書かれていますが、

答え4

Ubuntu 20.04 では、次のスクリプトを作成しました。これは/etc/libvirt/hooks/allow-portfw(chmod +x) として保存されます。

#!/bin/bash

CHAIN=LIBVIRT_FWI
IPTCMD="iptables -L $CHAIN -vn"
FILTERCMD="grep -v -e Chain -e pkts -e reject-with -e DNAT"

while $IPTCMD | grep ESTABLISHED | grep -v DNAT >/dev/null
do
    IF=$($IPTCMD | $FILTERCMD | awk '{print $7}' | head -n1)
    NET=$($IPTCMD | $FILTERCMD | awk '{print $9}' | head -n1)
    iptables -D $CHAIN -o $IF -d $NET -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    iptables -I $CHAIN 1 -o $IF -d $NET -m conntrack --ctstate DNAT,RELATED,ESTABLISHED -j ACCEPT
done

エントリ状況は、自動的に作成される FORWARDING チェーンの DNAT フラグが NEW bw. に欠けていることです。

sudo iptables -L LIBVIRT_FWI -vn
Chain LIBVIRT_FWI (1 references)
 pkts bytes target     prot opt in     out     source               destination         
1741K 2661M ACCEPT     all  --  *      virbr0  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
   38  1972 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

私のスクリプトは、すべての定義に DNAT フラグを追加します。

そうすれば、iptablesにポートフォワーディングを追加しただけで、

iptables -A PREROUTING -i mylanIF -p tcp --dport 3389 -j DNAT --to-destination 192.168.122.110:3389

パッケージを使用してiptables-persistentこの状態を保存できます (ただし、ダンプから libvirt チェーンを削除する必要があります)

または、ufw他のファイアウォール スクリプトを使用します。

私のスクリプトはこのアドレスからの調査結果に基づいていますhttps://www.cyberciti.biz/faq/kvm-forward-ports-to-guests-vm-with-ufw-on-linux/

関連情報