14

The host has a single external IP available, so I set my KVM guests up with NAT.

How do I set up a port forwarding to forward some of the requests from the outside to the guests?

I couldn't find any documentation on this. The closest answer is probably this answer,but then it's also mentioned there is easier way to do this in libvirt 0.8.3. Does anyone know of a more current way to do this?

wei
  • 605

4 Answers4

16

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.

Tobu
  • 4,495
3

I'm in a similar situation. I have a Windows Server running in KVM in the private NATed network which is connected on the host via the interface virbr0. I want to do access the VM via remote desktop. So I have to forward the traffic to port 3389 (RDP) to the VM port 3389. I have achieved this with some iptable rules.

/sbin/iptables -t nat -A PREROUTING -p tcp -d HOST-IP --dport 3389 -j DNAT --to-destination VM-IP:3389

/sbin/iptables -I FORWARD -m state -d VM-NET/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

HOST-IP, VM-IP, and VM-NET have to be adopted of course. However messing with iptables and libvirt is tricky. Right now I'm searching for an solution to get internet access on my VM which I have lost due to messing with the iptable rules :-(

spa
  • 303
1

I believe that the answer you reference still shows appropriate iptables rules. However, now you could use a script hook to create and destroy rules when virtual machines are started and stopped. Like Isaac said in the previous answer, there are also network filters in current libvirt but I'm not sure how or even if they can be used to open ports for NATed guests.

sciurus
  • 12,958
  • 3
  • 33
  • 51
0

how is the guest networking set up? if it's bridged, all you need to do is forward the ports to the guests' IPs. If your guests are behind yet another NAT, the one libvirt sets up, then it gets complicated

but in any case, here you simply treat the VMs as you would a physical machine

dyasny
  • 19,257