Pages

Sunday, July 11, 2010

Bridged openvpn on ubuntu

At my work we use ubuntu "lucid lynx" as the operating system for openvpn. Our "lynx" is  a vmguest running on linx/qemu/kvm. We have linux and windows clients. Actually, all possible clients which support openvpn client mode.

First I setup our internet-facing shorewall firewall to allow 1194 and port-forward it to our internal openvpn (vm)hosts, using shorewall-rules. We use shorewall version 4.4.6.

#ACTION SOURCE DEST PROTO DEST_PORT ...
DNAT wan lan:192.168.11.3:1194 udp 1194 #network alpha
DNAT wan lan:192.168.22.3:1194 udp 1294 #network beta

We have a multi-isp setup, that is denoted by the wan (wide area network) under SOURCE. We also have two lans (local area networks) which use this shorewall machine as the gateway to the internet, using two different subnets to communicate within each lan. So I wrote two rules to port-forward from the firewall to the correct openvpn server.

This is called dNATing (destination network address translation + ing); in practical terms, an openvpn client knocks on a specific port on the firewall, giving the illusion that this whole business is between the firewall and the client, but in fact, the firewall is only passing messages to and fro between the openvpn server inside a lan and the remote client somewhere on the internet, regardless of whether the client itself is behind a firewall or directly on the internet. It just works.

As I have mentioned earlier we use openvpn, the specific version is 2.1.0.
I looked far and wide on the internet for openvpn bridging and only found this tutorial to be the easiest to setup. The weird thing is, that the tutorial supposed to be used with a N900 mobile phone from nokia.

1) Install the software. See the tutorial first.
2) I also setup the bridge first. As recommended by the tutorial.


auto lo br0
iface lo inet loopback

iface br0 inet static
address 192.168.11.3
network 192.168.11.0
broadcast 192.168.11.255
netmask 255.255.255.0
gateway 192.168.11.254
bridge_ports eth0
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off

iface eth0 inet manual
up ifconfig $IFACE 0.0.0.0 up
up ip link set $IFACE promisc on
down ip link set $IFACE promisc off
down ifconfig $IFACE down
# do this in /etc/network/interfaces


3) Next you need to create the keys and certificates. This is the least difficult part.


sudo cp -a /etc/openvpn/easy-rsa ~/

chown -R user ~/easy-rsa
cd ~/easy-rsa
sudo chmod g+w . ; source ./vars ## execute your new vars file
./clean-all ## setup the easy-rsa directory (deletes all keys)
./build-dh ## takes a while consider backgrounding
./pkitool –initca ## creates ca cert and key
./pkitool –server server ## creates a server cert and key
cd keys
openvpn –genkey –secret ta.key ## Build a TLS key
sudo cp {server,ca}.crt {server,ta}.key dh1024.pem /etc/openvpn


4) Enable ip forwarding in /etc/sysctl.conf

5) Create the up.sh and down.sh shell scripts to create and kill the tap devices when a openvpn client logs on or off. Mind you that more parameters are passed to the scripts by the openvpn server than what the tutorial lets on. I found this out by turning on the debugging facilities of the openvpn script in /etc/init.d/openvpn, like this:


#!/bin/sh
set -e -x
..



Fix the permissions of the up.sh and down.sh files with this:

user@ovpnubuntu~/ sudo chmod go+rwx /etc/openvpn/{up,down}.sh


6) Modify the server.conf to reflect your lan's settings; for instance change the ip address of the "local" parameter. In our case it's 192.168.11.3. Port 1194.

local 192.168.11.3 1194


Openvpn has a built-in dhcp server, that distributes local ip addresses to openvpn clients. Make sure this is provisioned in your main dhcp server, so there is no chance of ip address collisions.

# openvpn server configuration file - server.conf
mode server
tls-server

local 192.168.11.3 1194
proto udp

dev tap0
up "/etc/openvpn/up.sh br0"
down "/etc/openvpn/down.sh br0"

persist-key
persist-tun

#certs
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
tls-auth ta.key 0

#cipher and compression
cipher AES-256-CBC
comp-lzo

#DHCP
ifconfig-pool-persist ipp.txt
## settings for openvpn dhcp server
server-bridge 192.168.11.254 255.255.255.0 192.168.11.216 192.168.11.224
push "dhcp-option DNS 192.168.11.5" # DNS
push "dhcp-option WINS 192.168.11.5" # windows-flavor DNS
push "dhcp-option DOMAIN ad.local" # for windows active directory objects or samba4!
max-clients 8

#log security
user nobody
group nogroup
keepalive 10 60
status openvpn-status.log
log-append server.log
verb 5


7) Configure /etc/defaults/openvpn; if you need to change the parameters passed to the openvpn server, modify OPTARGS:


OPTARGS="--fast-io --verb 5" # fast io for fast connections; verb for verbose debug output


After that you'll be able to restart the openvpn server automagically when the server goes down and has to reboot for some reason.

8) Create some keys for openvpn clients; as described in the tutorial:cd ~/easy-rsa ; source ./vars ; ./pkitool {user1,user2,user3,user4,joe,satch,bob,marilyn}

8a) If for some reason you want to prevent people from getting to your keys and/or certificates in cleartext; you can use openssl to encrypt your certificates and keys, while sending them across some unencrypted medium.

In my case, I wanted to send myself the keys etc. via e-mail, but I'm ultra-paranoid about big-brother sticking its nose in my beeswax. So I tarred and compressed my files first.

tar cf ~/openvpn-keys-certs.tar ~/easy-rsa ; bzip -z9 ~/openvpn-keys-certs.tar


Then I proceeded with encrypting the bzip2 file:

openssl aes-256-cbc -in openvpn-keys-certs.tar.bz2 -out openvpn-keys-certs.tar.bz2.enc


This is a form of symmetric encryption, so that means if someone finds out your passphrase you recently wrote down on a piece of paper, anyone who finds that paper can decode your message. Use hard passwords with a handful of these "!@#$%^&*();<>' in different cases with numbers in them.
Theoretically everything is brute-forceable, if one ignores the cost to crack the code. Unless there is some invariant loop-hole in the encryption algorithm to crack the dictionary of the compression algorithm.

Decrypt with this command:

openssl enc -d -aes-256-cbc -in openvpn-keys-certs.tar.bz2.enc -out openvpn-keys-certs.tar.bz2 ; tar xjf openvpn-keys-certs.tar.bz2


8b) Use asymmetric encryption like gpg. Send the encrypted keys and certificates to the user using her public key. Let her worry about the private key and passphrase. There is gpg4win for windows users.

9) Write a template client configuration file.

# template client configuration file - client.ovpn.txt
# Specify that this is a client
client

# Bridge device setting
dev tap

# Host name and port for the server (default port is 1194)
# note: replace with the correct values your server set up
remote firewall_ip_addr 1194

# Client does not need to bind to a specific local port
nobind

# Keep trying to resolve the host name of OpenVPN server.
## The windows GUI seems to dislike the following rule.
##You may need to comment it out.
resolv-retry infinite

# Preserve state across restarts
persist-key
persist-tun

# SSL/TLS parameters files created previously
ca ca.crt
cert replace.crt
key replace.key

# Since we specified the tls-auth for server, we need it for the client
# note: 0 = server, 1 = client
tls-auth ta.key 1

# Specify same cipher as server
cipher AES-256-CBC

# Use compression
comp-lzo

# Log verbosity (to help if there are problems)
verb 3


Each client requires three 4 files in total in our setup to connect; a) The common shared (ca.crt) certificate with the server; b) The client certificate; c) The client key; d) A configuration file.

You need to activate the template by replacing some parameters in the template with some real values. For instance there is no "replace.crt" nor "replace.key". This must be changed to some file name intended to be used by some user. For instance "bob".

So, given that you already created the key and certificate for "bob", you can create a configuration file using the template like this:

sed 's/replace/bob/g' client.ovpn.txt > bob-client.ovpn ; sed -i 's/firewall_ip_addr/real_firewall_ip_addr/' bob-client.ovpn

No comments:

Post a Comment

Please help to keep this blog clean. Don't litter with spam.