Ubuntu

在 libvirt / KVM 中將埠轉發給來賓

  • November 17, 2021

使用 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。

用於 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 規則的 hack 。我等不及他們為 Ubuntu 發布 libvirt 版本 0.8.3。

引用自:https://serverfault.com/questions/170079