Home | Small business | Service providers | Hardware vendors

The bridges of virtual county

Every so often, a physical host that runs a little host-local network full of little virtual machines is outgrown by the virtual machine community it hosts.

Now, usually, this is not a problem, add another host, bridge the virtual network on the old host to the virtual network on the new one via the real, physical network between them, and … taaaa-daaaaam … you’ve just got yourself some shiny virtualisation space to add more VMs to.

However, every so often it also comes to be that these two hosts do not – for one reason or another – share a LAN, not even a datacenter, but are divided by the scary span of internet at large.

Well, here’s to VPN, our solution of choice for such cases.

So … given two physical hosts, P1 and P2, hundreds of miles apart, each hosting a local virtual network with a few VMs, running on minimalistic libvirt – QEMU – KVM virtualisation stack, we will connect these two virtual networks into a single LAN.

Assume each the virtual network on each host is 192.168.100.0/24, and the virtual network interface on the host is virbr0 (which is a bridge, actually, that the vnet* interfaces of each VM attach to).

First of all, if we stick to the /24 network, it is prudent to divide its address space between P1. For the sake of examples below, we will make P1 host virtual IP addresses in the range 192.168.100.[1 - 100], while P2 will host virtual addresses in the range 192.168.100.[101 - 200].

Move on, reconfigure VM IPs on both hosts accordingly.

Alternatively, you might want to move one of the hosts to another subnet alltogether, and make the joined network /23 or somesuch.

Anyhow. I assume you are familiar with basics of OpenVPN key management: prepare your server and client certificates and keys, . Otherwise, you might want to consult OpenVPN’s Easy RSA about that …

So, at this point you should have the following crypto baggage with you:

ca.crt # the CA certificate
dh1024.pem # Diffie-Helman parameters
server.key # server private key
server.crt # server cert
client.key # client private key
client.crt # client cert
ta.key # shared-secret key

Now, it’s time for our all time favourite, an arbitrary decision: designated on of your machines a server, and the other one a client. For this tutorial’s sake, P1 will act as a server.

On the server side, install the whole OpenVPN shebang:

apt-get install openvpn

Create the hook scripts to be called when the VPN connection is established and torn down, respectively, and make them executable:

cat >/etc/openvpn/cnxup.sh < #!/bin/sh
BR=\$1
DEV=\$2
MTU=\$3
/sbin/ip link set "\$DEV" up promisc on mtu "\$MTU"
/sbin/brctl addif "\$BR" "\$DEV"
EOF
cat >/etc/openvpn/cnxdown.sh < #!/bin/sh
BR=\$1
DEV=\$2
/sbin/brctl delif "\$BR" "\$DEV"
/sbin/ip link set "\$DEV" down
EOF
chown a+x /etc/openvpn/*.sh

Now, configure the VPN, server side:
cat >/etc/openvpn/server.conf < mode server
tls-server
local your-P1-public-IP-here
port 1194
proto udp
dev tap0
up "/etc/openvpn/cnxup.sh virbr0 tap0 1500"
down "/etc/openvpn/cnxdown.sh virbr0 tap0"
persist-key
persist-tun
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
tls-auth ta.key 0
cipher BF-CBC
comp-lzo
ifconfig-pool-persist ipp.txt
server-bridge 192.168.1.1 255.255.255.0 192.168.1.201 192.168.1.201
max-clients 1
user nobody
group nogroup
keepalive 10 120
status server.log
verb 3
EOF

Note that tap0 interface will be always used by the VPN, and will be attached to virbr0 bridge on connection. We also only allow a single client to connect, and that client will be assigned the address 192.168.1.201 when it successfully connects.

Finally, copy the relevant certificates and keys:

cp ca.crt server.crt server.key ta.key dh1024.pem /etc/openvpn/

Restart the server:

/etc/init.d/openvpn restart

Move on to the client, P2:

Again, install the OpenVPN packages, and create the same connection scripts. Now, configure the client:

cat >/etc/openvpn/client.conf < client
dev tap0
up "/etc/openvpn/up.sh virbr0 tap0 1500"
down "/etc/openvpn/down.sh virbr0 tap0"
remote your-P1-public-IP-here
nobind
resolv-retry infinite
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1
cipher BF-CBC
comp-lzo
verb 3
EOF

Add the crypto salt and start the client:

cp ca.crt client.crt client.key ta.key /etc/openvpn/
/etc/init.d/openvpn restart

There. You have just established a VPN connection between P1 and P2, and have bridged the (formerly) host-local virtual networks into a single subnet. Try communicating between your VMs on different hosts now.