OpenVPN

johnw's picture

Intro

This isn't a general howto on VPN technology, it isn't even a howto on OpenVPN. You can find those kind of things elsewhere, and hopefully the references I include contain some useful pointers to suitable sites. This is the story of a particular problem I wanted to solve. If you're trying to set up a bridged OpenVPN system perhaps this will be of use to you. Or perhaps it won't. I'm sure when I want to do this again in six months time it'll be of use to me though! :) I needed to access a remote LAN in a small office elsewhere. My main wish was to get direct access to a CVS repository on one of the servers there, but I also thought it would be nice to be able to use a local Windows client to browse shared directories on a remote Windows server.

The 'lab'

Since I could only travel occasionally to the remote site, first of all I set up a 'lab' to try to encounter as many of the problems as I could before deploying. Since I don't have two adsl lines, I couldn't fully simulate the final system, so this was what I started with:

PC A
192.168.3.102
  |
  |
192.168.3.103
pc B
192.168.4.103
  |
  |
192.168.4.33
pc C

My intent was to make the 192.168.3.x subnet equivalent to the Internet, and 192.168.4.x equivalent to the remote LAN, protected by a firewall running in pc B. At this point all 3 PCs had no software installed and each had the BIOS set to boot first from the CD drive.

Why Xubuntu

Why not? :) I'm a fan of Ubuntu, especially since the release of Dapper in June 2006, which worked much more smoothly for me than Breezy before it. And because I'm generally working on slower hardware with less memory, I like Xubuntu. No doubt many other distros would work at least as well for this experiment. The 192.168.3.x subnet was also connected to a router to the Internet (not shown in the diagram). A connection to the Internet probably wasn't essential, it's just the way that I'm used to doing it. So first I installed Xubuntu on pc A and pc B, using the alternate 6.06.1 CD.

Why OpenVPN

OpenVPN (

http://www.openvpn.net/

) seems to me elegant and modular. I had a free choice of which software to use. Obviously if both ends of the link had not been under my control I would have had to look at whatever vpn technology was needed to connect to an existing server. But, in chorus with so many other people on the 'net, I'm not an expert, Do Your Own Research! :)

Why bridging, not routing

I'm not at all sure whether I made the right choice here. Routing is described by others as a more scalable solution, but, with just one client connecting to a rather small and underutilised LAN, scalability was of little importance to me. My impression is that you should only resort to a bridged VPN if you find that you can't do what you want with routing. And maybe my failure to do what I wanted with routing was only due to my incompetence, not something fundamental. Still, now that it's working, so far I'm happy with it.

Installing Openvpn

Below I've given command line instructions just because it's easier to describe it that way. Of course you can do this with Synaptic if you prefer a gui. First step was on pc A:

$ sudo apt-get install openvpn 

Obviously you need the openvpn package! Later I'll return to why you also need openssl and bridge-utils.

$ sudo apt-get install openssl bridge-utils

Creating certificates

You don't need to create certificates. Some months back I tried using the Windows version of OpenVPN to do what I wanted and on that occasion I used static keys because I was discouraged by the complexity of certificates. I was wrong. Certificates are surprisingly easy. Read

http://openvpn.net/howto.html#pki

if you want more detail. Perhaps gui tools are available for this, but the command line version is easy enough. I started by copying the files for generating the certificates, not wishing to overwrite the original ones. I could have copied them anywhere, but I felt a directory under /etc/openvpn would be sensible.

$ sudo -i
# cd /etc/openvpn
# mkdir easy-rsa
# cd easy-rsa
# cp -p -v /usr/share/doc/openvpn/examples/easy-rsa/2.0/ .

(Mention cockup of pkitools.gz instead of pkitools -- needs gunzip) (Mention what happens if you're not psychic and therefore don't realise you need to install openssl)

Installing a firewall

This step is purely for the lab experiment. In the real world pc B is a router. (Add notes on installing Firestarter on pc B)

Installing Xubuntu on pc C

Now that Firestarter was installed, the 192.168.4.x network could reach the Internet through pc B, so I was now ready to install Xubuntu on pc C. With Xubuntu installation complete, this pc was now ready to play the role of the remote server. To make the experiment as realistic as possible, I wanted to do as much as possible on pc C remotely, pretending the keyboard and screen weren't on the next desk! So I installed an SSH server.

$ sudo apt-get install openssh-server

This listens on port 22. To access it from "outside", in other words the 192.168.3.x network, I needed to get Firestarter to forward port 22 to pc C. With that done, I could log in to pc C from pc A, using ssh. From here onwards I never needed to have direct access to pc C.

Setting up the server

$ sudo apt-get install openvpn 

/etc/openvpn/server.conf:

port 1194
proto udp
dev tap0
ca keys/ca.crt
cert keys/server.crt
key keys/server.key # This file should be kept secret
dh keys/dh1024.pem
server-bridge 192.168.4.33 255.255.255.0 192.168.4.41 192.168.4.80
keepalive 10 120
persist-key
persist-tun
status openvpn-status.log
verb 3

Now for the dangerous bit, where I risked losing contact with pc C. First I saved a copy of the file I was about to modify and created a new version.

# cd /etc/network
# cp -p -v interfaces interfaces.old
# cp -p -v interfaces interfaces.new

I then modified interfaces.new, adding the 2nd part for openvpn (the first part I left as it was). /etc/network/interfaces.new:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
    address 192.168.4.33
    netmask 255.255.255.0
    network 192.168.4.0
    broadcast 192.168.4.255
    gateway 192.168.4.103
    # dns-* options are implemented by the resolvconf package, if installed
    dns-nameservers 192.168.4.103

# added for openvpn
auto br0
iface br0 inet static
    address 192.168.4.33
    netmask 255.255.255.0
    network 192.168.4.0
    broadcast 192.168.4.255
    bridge ports eth0 tap0
    gateway 192.168.4.103
    dns-nameservers 192.168.4.103
    pre-up /usr/sbin/openvpn --mktun --dev tap0
    pre-up ifconfig eth0 0.0.0.0 up
    pre-up ifconfig tap0 0.0.0.0 up
    pre-up brctl addbr br0
    pre-up brctl addif br0 eth0
    pre-up brctl addif br0 tap0
    ifconfig br0 192.168.4.33 netmask 255.255.255.0 broadcast 192.168.4.255
    post-down ifconfig eth0 0.0.0.0 down
    post-down ifconfig tap0 0.0.0.0 down
    post-down brctl delif br0 eth0
    post-down brctl delif br0 tap0
    post-down brctl delbr br0
    post-down /usr/sbin/openvpn --rmtun --dev tap0

(Need more here about overwriting interfaces with interfaces.new and rebooting)

Setting up the client

client
dev tap
proto udp
remote 192.168.3.103 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca keys/ca.crt
cert keys/client102.crt
key keys/client102.key
ns-cert-type server
log openvpn.log
verb 3

Troubleshooting

Hopefully for you this will Just Work. But I didn't get do all the settings correctly (late night? too much coffee?) and had to find out why. Apart from desk checking everything while engaging brain, the method that gave me some clues was to add 'cipher none' at both ends (to turn off encryption), ensure there was no comp-lzo compression at both ends and install and run Ethereal (known these days as WireShark

?

). Watching the actual packets and figuring out who's not listening to who can be very revealing!

Adding Windows servers and clients

Deploying on the remote site, part 1

Safety net

(Needs details of how I shot myself in the foot when I tried to deploy on the remote system and found that some kind of safety net is a Good Idea) No need to do this if the server is local. This is to try to recover if networking gets hosed. Root terminal, crontab -e

0 3 * * * /root/rollback

This runs at 3am every morning. Obviously if you're impatient you can set this to run more often (at one stage I had it running every 30 minutes) but don't have it running so often that it reboots again before you have a chance to adjust it! Tip: make sure the clocks on the various machines you're running are set to within at least a minute or so, so you don't get nasty surprises, scripts running when you don't expect. Of course, if you use an ntp time server they'll be much more accurate than this. In /root a script file:

#!/bin/bash
# script to be run to return system to a good state, e.g. with crontab

echo `date` rollback >>/root/rollback.log
/root/genreport
echo `date` "copy backed up files" >>/root/rollback.log
# cp -v -r -p /etc.bak /etc >>/root/rollback.log
# above doesn't work, it creates /etc/etc.bak/...
# so do the copies individually for now
cp -v -p /etc.bak/network/interfaces /etc/network/interfaces >>/root/rollback.log
echo "---------- (rebooting)" >>/root/rollback.log
/sbin/shutdown -r now

This script in turn runs a useful script, genreport, which saves the state of the networking, which hopefully will be useful afterwards for diagnosing the problem. genreport:

#!/bin/bash
# script to report current status

echo `date` genreport >>/root/rollback.log
echo "route -een >>/root/rollback.log" >>/root/rollback.log
route -een >>/root/rollback.log
echo "-----" >>/root/rollback.log
echo "netstat -an >>/root/rollback.log" >>/root/rollback.log
netstat -an >>/root/rollback.log
echo "-----" >>/root/rollback.log
echo "ifconfig >>/root/rollback.log" >>/root/rollback.log
ifconfig >>/root/rollback.log
echo "-----" >>/root/rollback.log
echo "cat /etc/network/interfaces >>/root/rollback.log" >>/root/rollback.log
cat /etc/network/interfaces >>/root/rollback.log
echo "-----" >>/root/rollback.log
echo "----------" >>/root/rollback.log

The rollback script also copies the saved version of /etc/network/interfaces which I keep in /etc.bak/network/interfaces. It then reboots the server.

Deploying on the remote site, part 2

I now have a bridged vpn running, using an Xubuntu server on the remote site (where there are also Windows servers on the LAN) and I'm able to access these servers from my own clients (both Xubuntu and W2K) even including Windows network browsing of shared files.

References

(Good here? Or include as appropriate within the text??)

Step by step guide to easy-rsa, the first step in setting up a vpn (assuming you're using certificates)

 

Mentioned in that thread, haven't viewed yet: