iptables NAT & virtual machine networking

6,048

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

an additional NAT rule needs to be introduced on the [VM host] to enforce that all reply traffic flows through the [VM host], despite the client and server being on the same subnet.

In your case, such rules could look something like this:

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

where:

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

I'll leave it to you completely debug this, as complicated NAT setups tend to give me serious headaches.

Share:
6,048

Related videos on Youtube

Dopamine
Author by

Dopamine

Updated on September 17, 2022

Comments

  • Dopamine
    Dopamine over 1 year

    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.

    • iSee
      iSee over 13 years
      Try running tcpdump or wireshark on the both the host machine and guest machine to see what's happening. Also, you might want to label your question virtualbox since there might be something VirtualBox specific, e.g. the way the network card of the guest is configured. By the way, if I remember correctly, VirtualBox had something for port forwarding.
    • Zaid Amir
      Zaid Amir over 13 years
      Do you understand what the script does, or did you just copy it from somewhere and tried to use it in your environment? There are many things in it that don't make much sense.
    • Dopamine
      Dopamine over 13 years
      There is nothing VirtualBox-specific here.
    • Dopamine
      Dopamine over 13 years
      That script is written completely from scratch only for my own system using several iptables tutorials. Unfortunately I'm not an iptables-guru yet.