Iptables – KVM – Access from an external computer to the Virtual Machine

iptableskvm-virtualizationlinux-networkingvirshvirtual-machines

I have the following setup:

Notebook (IP: 192.168.1.100)
Host: (IP:192.168.1.129)

Both Notebook and Host are connected to a router (Internet IP:192.168.1.1)ยจ

The host (Host) has two virtual machine on it (Development, Office). The host since it uses a DHCP server(KVM), assigns the following IP addresses to the VM's

Development: 192.168.122.45
Office: 192.168.122.46

The DHCP server for the host hast the IP address 192.168.122.1

Now I like to access the Development VM from my Notebook (192.168.1.100) on port 5900 to remotely work on this VM.

I used some iptables roules to achieve this on the host, where the VM's are located:

iptables -t nat -I PREROUTING -p tcp -d 192.168.1.129 --dport 5900 -j DNAT --to-destination 192.168.122.45
iptables -I FORWARD -m state -d 192.168.122.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

Unfortunately I didn't get a connection with Spice to the Development VM.

 spice://192.168.1.129:5900

I edited my VM with

virsh edit VM-Development

and configured like this:

<graphics type='spice' port='5900' autoport='no' listen='127.0.0.1' keymap='de-ch'>
   <listen type='address' address='127.0.0.1'/>

After I made the iptables roules the XML-configuration files contains a new entry:

<video>
    <model type='qxiptables -t nat -I PREROUTING -p tcp -d 192.168.1.129 --dport 5900 -j DNAT --to-destination 192.168.122.45 iptables -I FORWARD -m state -d 192.168.122.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT l' ram='65536' vram='65536' vgamem='16384' heads='1'/>
        <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>

What's wrong? I used several hints, but I can't get it work. I also looked that the router has the port 5900 open.

Best Answer

You can use ssh HOST nc as a proxy:

Host *.saturnin.* *.saturnin bb-*
   ProxyCommand ssh -q -A saturnin.lab.eng.brq.redhat.com nc %h %p
   IdentityFile ~/.ssh/bot_rsa
   User root

Drawback: this requires having entries in /etc/hosts on the host.

Alternatively I am using nc with sed to get local name/IP:

Host tbb-*
   ProxyCommand ssh -q -A saturnin.lab.eng.brq.redhat.com sednc 's/^tbb-//' %h %p
   IdentityFile ~/.ssh/bot_rsa
   User root

Host 192.168.*.cimrman.* 192.168.*.cimrman
   ProxyCommand ssh -q -A cimrman.lab.eng.brq.redhat.com sednc 's/\.cimrman.*//' %h %p
   IdentityFile ~/.ssh/bot_rsa
   User root

sednc looks like this:

#!/bin/bash

if [[ $1 == -h || $1 == --help ]]; then
  cat <<END
sednc - nc to a HOST:PORT with HOST modified by an sed command SEDEXP

USAGE: sednc SEDEXP HOST [PORT]

Example:

    sednc 's/^bb-//' bb-rawhide

This is to be used with ssh to connect to a VMs inside a host. Add line like this to your .ssh/config:

    Host bb-*
        ProxyCommand ssh -q -A HOST sednc 's/^bb-//' %h %p

END
  exit 0
fi

HOST="$2"
TRANSLATED="$(sed -e "$1" <<<"$2")"

#echo "$TRANSLATED">&2
nc "$TRANSLATED" "${3:-"22"}"