NAT via iptables and virtual interface

13,390

Solution 1

With the answers of Christophe Drevet and DukeLion I was able to get the desired configuration working.

I'm going to answer myself explaining my solution. Please feel free to comment on this as I haven't done network stuff in a few years and might very well have missed something very important here.

The configuration below works perfectly and allows for adding more VMs, each using a different public IP address (IPs from 172.16.0.0 used here are "public").


Network Interfaces

VM-Host, eth0        -> 172.16.0.1
VM-Host, eth0:0      -> 172.16.0.2
VM-Host, br0         -> 192.168.10.1
Virt. machine, eth0  -> 192.168.10.2 (added to br0)
                        gateway: 172.16.0.2

iptables

Connection tracking:

iptables -I FORWARD -m conntrack -d 192.168.10.0/24 --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT

DNAT for the webserver on our VM:

iptables -t nat -A PREROUTING -p tcp -d 172.16.0.2 --dport 80 -j DNAT --to-destination 192.168.10.2:80

SNAT for our VM to reach the outside world:

iptables -t nat -I POSTROUTING -j SNAT --src 192.168.10.2 --to-source 172.16.0.2

Block all other ports on the VM:

iptables -A INPUT -d 172.16.0.2 -j REJECT --reject-with icmp-port-unreachable

Solution 2

to use DNAT like this you need your guest systems to have VM-host as default gateway.

Solution 3

I had a similar network configuration and I used this configuration :

localnetwork (192.168.0.0/24) <-> host eth0 (192.168.0.10)

host tun0 (192.168.1.150) <-> vm1 eth0 (192.168.1.200) gw 192.168.1.150
                          <-> vm2 eth0 (192.168.1.201) gw 192.168.1.150

All my VMs can ping each other and can access the outside network with this iptable rule :

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
SNAT       all  --  192.168.1.0/24       0.0.0.0/0            to:192.168.0.10

The outside network can access services on my VMs with these rules :

Chain PREROUTING (policy ACCEPT)
target  prot opt source     destination         
DNAT    tcp  --  0.0.0.0/0  192.168.0.10  tcp dpt:22200 to:192.168.1.200:22
DNAT    tcp  --  0.0.0.0/0  192.168.0.10  tcp dpt:22201 to:192.168.1.201:22
DNAT    tcp  --  0.0.0.0/0  192.168.0.10  tcp dpt:3389  to:192.168.1.202:3389
DNAT    tcp  --  0.0.0.0/0  192.168.0.10  tcp dpt:443   to:192.168.1.206:443
DNAT    tcp  --  0.0.0.0/0  192.168.0.10  tcp dpt:80    to:192.168.1.206:80

I configured the tun0 interface with these lines on debian in the file /etc/network/interfaces :

auto tun0
iface tun0 inet static
  address 192.168.1.150
  netmask 255.255.255.0
  pre-up tunctl -g uml-net -t tun0
  post-down tunctl -d tun0
Share:
13,390
Alex
Author by

Alex

Nerd, Techie, Enthusiast. Android lover. Student.

Updated on September 18, 2022

Comments

  • Alex
    Alex almost 2 years

    I'm trying to implement the following scenario: One VM-host, multiple guest VMs, each one gets its own IP-address (and domain).

    Our server has only one physical interface, so the intended use is to add virtual interfaces on eth0. To complicate our situation the provider uses port-security on their switches, so I can't run the guest interfaces in bridged mode, because then the switch detects a "spoofed" MAC-address and kills the interface (permanently, forcing me to call the support, which I'm sure will get them a little bit angry the third time ;) ).

    My first guess was to use iptables and NAT to forward all packages from one virtual interface to another one, but iptables doesn't seem to like virtual interfaces (at least I can't get it to work properly). So my second guess is to use the source IP of the packages to the public interface.

    Let's assume libvirt creates a virbr0-network with 192.168.100.0/24 and the guest uses 192.168.100.2 as IP-address.

    This is what I tried to use: iptables -t nat -I PREROUTING --src public_ip_on_eth0:0 -p tcp --dport 80 -j DNAT --to-destination 192.168.100.2:80

    That doesn't give me the intended results either (accessing the server times out).

    Is there a way to do what I'm trying to do, or even to route all traffic to a certain IP on a virtual interface to the VM's device?

    • jetboy
      jetboy about 12 years
      If you're getting a timeout, it could be that the request is making it to the VM, but the response isn't making it back out. You can check your server log (port 80 means a web server, right?) to see if the request's hitting the server.
  • Alex
    Alex about 12 years
    So you mean I need to setup the guest to use eth0:0's IP (or whatever virtual device I'm going to use) as default gateway and not 192.168.100.1, which is the virbrX device?