iptables NAT和虚拟机networking

目前,我正在使用以下脚本使多个虚拟机访问Internet,并允许某些端口通过主机专用networking内的主机NAT进行转发。

host_interface=eth0 # name of host machine interface connected to the Internet vnet_interface=vboxnet0 # name of host machine's local network interface host_ip[0]=... # array contains external IP addresses for every guest guest_ip[0]=... # array contains internal IP addresses for every guest guest_ports[0]=21,22,80,443 # array of port lists for every guest iptables -P INPUT ACCEPT iptables -F INPUT iptables -P OUTPUT ACCEPT iptables -F OUTPUT iptables -P FORWARD ACCEPT iptables -F FORWARD iptables -t nat -F echo "1" > /proc/sys/net/ipv4/ip_forward for i in ${!host_ip[*]} do iptables -t nat -A PREROUTING -i $host_interface -d ${host_ip[$i]} -p tcp -m multiport ! --dports "${guest_ports[$i]}" -j ACCEPT iptables -t nat -A PREROUTING -i $host_interface -d ${host_ip[$i]} -j DNAT -p tcp -m multiport --dports "${guest_ports[$i]}" --to-destination ${guest_ip[$i]} done # forward all packets from already established connections iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT for i in ${!guest_ip[*]} do # allow forwarding new connections from host to guest iptables -A FORWARD -i $host_interface -o $vnet_interface -d ${guest_ip[$i]} -m state --state NEW -j ACCEPT # allow forwarding new connections from guest to host iptables -A FORWARD -i $vnet_interface -o $host_interface -s ${guest_ip[$i]} -m state --state NEW -j ACCEPT iptables -t nat -A POSTROUTING -o $host_interface -s ${guest_ip[$i]} -j SNAT --to-source ${host_ip[$i]} done 

这里唯一缺less的是通过它的EXTERNAL IP地址(当然是在本地networking内)访问任何访客机器的能力。 每次尝试连接到同一台计算机或另一个guest虚拟机的打开端口(但能够从任何guest虚拟机连接到主机)时,都会收到“连接被拒绝”消息。 内部(专用)IP工作正常,我可以从本地networking的任何地方连接到任何客人和主机。 试图添加类似的东西

 iptables -t nat -A PREROUTING -i $vnet_interface -d ${host_ip[$i]} -j DNAT --to-destination ${guest_ip[$i]} 

但似乎是不够的。

如果我理解正确,您的问题在于您的VM guest虚拟机无法通过外部IP地址访问自己或其他guest虚拟机。 您所遇到的问题已清楚地显示在此页面上 (只要想象一下路由器是您的VM主机,而Web服务器就是您的VM guest虚拟机之一)。 你需要configuration“发夹NAT”。

引用同一页面的解决scheme就是这样

需要在[VM主机]上引入额外的NAT规则,以强制所有回复通信stream经[VM主机],尽pipe客户机和服务器在同一子网上。

就你而言,这样的规则可能看起来像这样:

 iptables -t nat -A PREROUTING -s $host_only_network -d ${guest_ip[$i]} -o $vnet_interface -p tcp -m multiport --dports "${guest_ports[$i]}" -j MASQUERADE 

哪里:

 host_only_network=192.168.1.0/24 # replace with whatever applies to your guest network 

我会留给你完全debugging,因为复杂的NAT设置往往让我非常头疼。

将您的input策略设置为默认接受是一个非常糟糕的主意,您应该使用

iptables -P INPUT DROP

也默认转发是不好的。 您始终可以为来自特定接口的stream量设置允许所有规则,以便在input或转发时始终允许这是允许的。