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
  • 595
  • 1
  • 6
  • 11
  • external - you mean internet IP? or just your LAN (external to VMs)? Can you allocate those external addresses to your VMs to set up bridged networking? – Art Shayderov Feb 10 '11 at 22:23
  • I can only get one Internet IP address, that's why I didn't use bridged networking mode. – wei Feb 12 '11 at 05:27

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,367
  • 1
  • 23
  • 31
  • 1
    Trusty has a line `/etc/libvirt/hooks/** rmix,` in apparmor config file by default, and it seems to has the same effect. I could run the script without modifying apparmor configuration. – Amir Ali Akbari Feb 10 '15 at 13:59
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
  • 293
  • 2
  • 8
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,493
  • 2
  • 30
  • 49
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
  • 18,482
  • 6
  • 48
  • 63
  • I guess I didn't say it ver clearly. The host is not in a NAT, it has an external IP address. Unfortunately, the guest networking is behind the NAT set up by libvirt. – wei Feb 10 '11 at 16:55
  • ah, then it's another matter. basically libvirt manages it's own NAT solution, which can be edited. – dyasny Feb 10 '11 at 17:47
  • yeah, that's what I have been told, it can be edited. But I am just can't find any reference about it, the nwfilter xml configuration files just seem like bizarre to me, the documentation on libvirt website isn't very helpful either. – wei Feb 10 '11 at 19:51
  • If you have bridged networking you can just abandon the default libvirt NAT and setup anything you want. As dyasny said, treat VM as you would a physical machine. I have KVM host and interface with external IP is assigned to a VM which is configured as a gateway. If that suits you needs I can post the configuration (ubuntu-style). – Art Shayderov Mar 14 '11 at 14:27