Ubuntu
在 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。
用於 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。