iptables NAT 和虚拟机网络

iptables NAT 和虚拟机网络

目前,我正在使用以下脚本使多个虚拟机访问互联网,并允许某些端口在仅主机网络内通过主机的 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

这里唯一缺少的是通过外部 IP 地址(当然是在本地网络内)访问任何客户机的能力。每次我尝试连接到同一台机器或其他客户的开放端口时,都会收到“连接被拒绝”消息(但可以从任何客户机连接到主机)。内部(私有)IP 工作正常,我可以从本地网络内的任何地方连接到任何客户机和主机。尝试添加类似

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

但似乎还不够。

答案1

如果我理解正确的话,您的问题是您的 VM 来宾无法通过其外部 IP 地址访问自己或其他来宾。您遇到的问题在这一页(想象一下路由器是您的 VM 主机,而 Web 服务器是您的 VM 客户机之一)。您需要配置“Hairpin NAT”。

解决方案,引用同一页,是

需要在 [VM 主机] 上引入额外的 NAT 规则,以强制所有回复流量都流经 [VM 主机],尽管客户端和服务器位于同一子网。

在你的情况下,这些规则可能看起来像这样:

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

我会让你完全调试这个,因为复杂的 NAT 设置往往会给我带来严重的麻烦。

答案2

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

iptables -P 输入删除

默认情况下转发也是不好的。您可以始终为来自特定接口的流量设置允许所有规则,以便始终允许其输入或转发,这是可以的。

相关内容