Here is a better way to set up port forwarding, using a hook script (source).
In /etc/libvirt/hooks/qemu
:
#!/bin/sh
GUEST_NAME=
HOST_PORT=
GUEST_IPADDR=
GUEST_PORT=
if [ "$1" = "$GUEST_NAME" ]; then
if [ "$2" = start ]; then
iptables -t nat -A PREROUTING -p tcp --dport "$HOST_PORT" \
-j DNAT --to "$GUEST_IPADDR:$GUEST_PORT"
iptables -I FORWARD -d "$GUEST_IPADDR/32" -p tcp -m state \
--state NEW -m tcp --dport "$GUEST_PORT" -j ACCEPT
elif [ "$2" = stopped ]; then
iptables -t nat -D PREROUTING -p tcp --dport "$HOST_PORT" \
-j DNAT --to "$GUEST_IPADDR:$GUEST_PORT"
iptables -D FORWARD -d "$GUEST_IPADDR/32" -p tcp -m state \
--state NEW -m tcp --dport "$GUEST_PORT" -j ACCEPT
fi
fi
You should set the four variables at the top to fit your libvirt setup.
You will need to restart libvirt-bin, which on ubuntu is done with:
sudo sh -c 'service libvirt-bin stop; service libvirt-bin start'
then you will need to restart the guest. On Ubuntu, you will need to adjust /etc/apparmor.d/usr.sbin.libvirtd
to allow the hook script to execute:
Next to
/usr/sbin/* PUx,
append
/etc/libvirt/hooks/* PUx,
Then reload apparmor:
sudo service apparmor reload
There's probably a way to autoconfigure $GUEST_IPADDR
using virsh / dumpxml / iface-dumpxml, but I haven't found it. Alternatively, the IP can be set statically in the network xml: documentation.
As far as I can tell, network filters can only be used for restricting what happens on the virtual network, and they aren't useful for port forwarding.