Forwarding Incoming Connections
By default, guests that are connected via a virtual network with can make any outgoing network connection they like. Incoming
connections are allowed from the host, and from other guests connected to the
same libvirt network, but all other incoming connections are blocked by
iptables rules.
If you would like to make a service that is on a guest behind a NATed virtual
network publicly available, you can setup libvirt's "hook" script for qemu to
install the necessary iptables rules to forward incoming connections to the
host on any given port HP to port GP on the guest GNAME:
1) Determine a) the name of the guest "G" (as defined in the libvirt domain
XML), b) the IP address of the guest "I", c) the port on the guest that will
receive the connections "GP", and d) the port on the host that will be
forwarded to the guest "HP".
(To assure that the guest's IP address remains unchanged, you can either
configure the guest OS with static ip information, or add a element
inside the element of the network that is used by your guest. See the
libvirt network XML documentation address section for defails and an example.)
2) Stop the guest if it's running.
3) Create the file /etc/libvirt/hooks/qemu (or add the following to an already
existing hook script), with contents similar to the following (replace GNAME,
IP, GP, and HP appropriately for your setup):
Use the basic script below or see an "advanced" version, which can handle
several different machines and port mappings here (improvements are welcome) or
here's a python script which does a similar thing and is easy to understand and
configure (improvements are welcome):
#!/bin/bash
# IMPORTANT: Change the "VM NAME" string to match your actual VM Name.
# In order to create rules to other VMs, just duplicate the below block and configure
# it accordingly.
if [ "${1}" = "VM NAME" ]; then
# Update the following variables to fit your setup
GUEST_IP=
GUEST_PORT=
HOST_PORT=
if [ "${2}" = "stopped" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -D FORWARD -o virbr0 -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
if [ "${2}" = "start" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -I FORWARD -o virbr0 -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
fi
4) chmod +x /etc/libvirt/hooks/qemu
5) Restart the libvirtd service.
6) Start the guest.
(NB: This method is a hack, and has one annoying flaw in versions of libvirt
prior to 0.9.13 - if libvirtd is restarted while the guest is running, all of
the standard iptables rules to support virtual networks that were added by
libvirtd will be reloaded, thus changing the order of the above FORWARD rule
relative to a reject rule for the network, hence rendering this setup
non-working until the guest is stopped and restarted. Thanks to the new
"reconnect" hook in libvirt-0.9.13 and newer (which is used by the above script
if available), this flaw is not present in newer versions of libvirt (however,
this hook script should still be considered a hack).