Forwarding ports to guests in libvirt / KVM

The latest stable release for libvirt for Ubuntu is version 0.7.5, which doesn’t have some newer features (i.e. script hooks and network filters) which make automatic network configuration easier. That said, here’s how to enable port forwarding for libvirt 0.7.5 on Ubuntu 10.04 Lucid Lynx.

These iptables rules should do the trick:

iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

The default KVM NAT config provides a rule similar to the 3rd I gave above, but it omits the NEW state, which is essential for accepting incoming connections.

If you write a startup script to add these rules and you’re not careful, libvirt 0.7.5 overrides them by inserting its own. So, in order to make sure these rules are applied properly on startup, you need to make sure libvirt has initialized before you insert your rules.

Add the following lines to /etc/rc.local, before the line exit 0:

(
# Make sure the libvirt has started and has initialized its network.
while [ `ps -e | grep -c libvirtd` -lt 1 ]; do
        sleep 1
done
sleep 10
# Set up custom iptables rules.
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT
) &

The sleep 10 above is a hack to make sure the libvirt daemon has had a chance to initialize its iptables rules before we add our own. I can’t wait until they release libvirt version 0.8.3 for Ubuntu.

Leave a Comment