Iptables – Forward traffic into docker container/VM

dockeriptablesnetworkingvirtualbox

I have a pretty beefy machine at my disposal running Ubuntu 16.04 Server. It's running several docker containers and virtual machines (using VirtualBox) referred to as VMs hereafter. At the moment the host has assigned one IP address (say, 192.168.1.10) and the services on the VMs are accessed by NATing (e.g. 192.168.1.10:80 -> 172.17.0.2:80), which is unsatisfactory.
Instead, I'd like to bind multiple IP addresses (say, 192.168.1.100-110) to the hosts interface and forward the traffic hitting the additional IP addresses into the VMs. Which results in a mapping <public IP> <--> <private IP>.

I've been able to accomplish this first part by adding

[...]
up ip addr add 192.168.1.1xx/24 dev ens3 label ens3:0
down ip addr del 192.168.1.1xx/24 dev ens3 label ens3:0
[...]

entries into my /etc/network/interfaces file (where ens3 obviously is the name of the host network interface). That means the additional IP addresses are up an running.

But the second part causes me headaches. So far I've only considered iptables based solutions, as it seems most appropriate and all guides I've read so far used it also.
So what I did was activating IP forwarding by adding net.ipv4.ip_forward=1 to /etc/sysctl.conf.

Then, I issued the following commands to do the forwarding:

iptables -t nat -A POSTROUTING -d 172.17.0.2 -j SNAT --to-source 192.168.1.100
iptables -t nat -A PREROUTING -d 192.168.1.100 -j DNAT --to-destination 172.17.0.2

172.17.0.2 is the private IP of one of the VMs. It's running a webserver at port 8000. telnet 172.17.0.2 8000 establishes a connections, which tells me that the webserver is running. But telnet 192.168.1.100 8000 doesn't work.
Almost all tutorials on iptables deal with forwarding one port or a range of ports but there are only few that deal with all the traffic on an interface.
Can anyone spot my mistake? Or does anyone have good advice for alternative tools that get the job done?

Best Answer

Your NAT rule should work:

iptables -t nat -A PREROUTING -d 192.168.1.100 -j DNAT --to-destination 172.17.0.2

However, you need to add another rule if you are requesting some service from the same machine (locally):

iptables -t nat -A OUTPUT -d 192.168.1.100 -j DNAT --to-destination 172.17.0.2

The NAT rule can be applied to specific port(s) of specific protocol or to all protocols and ports (as the case here).