I have a dedicated server running KVM virtualization with n public IP addresses dedicated to n-1 web-facing virtual machines. Now I'd like to set up some web-facing VM's that don't have a dedicated address, but instead will have 2 or 3 ports forwarded for them from the host machine.

Bridge configuration is:

brctl show

enter image description here

Let's say I would like to forward

  • to
  • to

First, I have enabled port forwarding on a host machine by uncommenting

# net.ipv4.ip_forward=1

in /etc/sysctl.conf, then I did

sysctl -p /etc/sysctl.conf
service network restart

Then, similar to the recipe in this question, I did:

iptables -t nat -A PREROUTING -p tcp -i br0 --dport 201 -j DNAT --to-destination
iptables -A FORWARD -p tcp -d --dport 201 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -i br0 --dport 801 -j DNAT --to-destination
iptables -A FORWARD -p tcp -d --dport 801 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

I ran ifconfig on a guest machine and checked that its interface eth0, indeed, has the IP address The interface inside of virtual machine is called eth0, is this right?

But it doesn't work:

nmap doesn't show an open port 201 nor 801, and ssh -l root -p 201 gets me

ssh: connect to host port 201: Connection refused

ip route on a host machine returns dev br0  proto kernel  scope link  src dev virbr0  proto kernel  scope link  src dev br0  scope link  metric 1004 
default via dev br0 

What am I doing wrong?

  • 1
    Did you enable forwarding? sysctl -w net.ipv4.ip_forward=1 net.ipv4.conf.br0.forwarding=1 net.ipv4.conf.virbr0.forwarding=1 – Patrick Apr 13 '14 at 3:39
  • @Patrick Ack! I thought I did, but I actually didn't! Now, I made sure I did, but the problem persists. I have revised my question. – Nickolai Leschov Apr 13 '14 at 15:26
  • @Patrick I think I'm not getting exactly when, if at all, I should be using virbr0-nic instead of eth0? – Nickolai Leschov Apr 13 '14 at 15:31

When you forward traffic to a different prot you need to add postrouting SNAT rule (or masquerade, it doesn't matter). Also you made some mistakes at forward rule. So try this:

iptables -t nat -A PREROUTING -p tcp -i br0 --dport 201 -j DNAT --to-destination
iptables -A FORWARD -p tcp -d --dport 22 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -d -p tcp --dport 22 -j SNAT --to-source

You have to enable loopback routing. I did this on my router with the following:

iptables -A FORWARD -o eth1 -d $IP -j ACCEPT

iptables -A FORWARD -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

In my setup, eth0 is the internet interface, $IP is the internet IP, and eth1 is the internal interface.

The key here is that you need a FORWARD rule for traffic going out your internal interface with the external destination IP. It's a bit confusing logically because this rule is applied before the DNAT.

The second rule just accepts internal traffic to be forwarded in the first place, you can achieve this in different ways.

I'm not sure if additional special things apply here due to the virtual networking portion, you might need ebtables to make it work too.

  • Do I have to do this on the host machine (I'm providing internet connection to VM's here), in addition to the rules I have set up in my question? I fail to see which does what. I wonder what would eth0 and eth1 be, on my system: I guess, eth0 and virbr0-nic? – Nickolai Leschov Apr 14 '14 at 20:57
  • It would be on whichever machine is holding your external IP, whether that's a VM or the host. If it's a VM, the routing will probably be a little different, but similar. – cscracker Apr 14 '14 at 21:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.