Currently I'm using the following script to make several virtual machines access the Internet and allow some ports being forwarded through the host's NAT inside a host-only network.
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
The only thing is missing here is an ability to access any guest machine by it's EXTERNAL IP address (within local network of course). I'm getting "Connection refused" message every time I trying to connect to the open port of the same machine or another guest (but able to connect to the host from any guest). Internal (private) IPs works fine, I'm able to connect to any guest and host from anywhere within local network.
Tried adding something like
iptables -t nat -A PREROUTING -i $vnet_interface -d ${host_ip[$i]} -j DNAT --to-destination ${guest_ip[$i]}
but it seems that it is insufficient.
Best Answer
If I understand correctly, your problem is that your VM guests can't access themselves or the other guests by their external IP addresses. The problem you are having is clearly illustrated on this page (just imagine the router is your VM host, and the web server is one of your VM guests). You need to configure "Hairpin NAT".
The solution, to quote that same page, is that
In your case, such rules could look something like this:
where:
I'll leave it to you completely debug this, as complicated NAT setups tend to give me serious headaches.