stocksy.co.uk
"the site for those who crave disappointment"

Sponsored Links

OpenVPN - It just works!

5th Nov 2005, 10:37:53

By James Stocks

I've been looking for an easy way to connect my remote computers together for a long time. OpenVPN fits the bill nicely! Best of all, it works with OS X, Linux and even Windows.

My first decision; where am I going to install the OpenVPN server? I chose to install it on my Firewall running Debian Sarge. OpenVPN will install as a server on OS X, too.

$ sudo -s
# apt-get update
# apt-get install openvpn

Trusty old apt will install OpenVPN for you. Lets go to /etc/openvpn and configure it.

# exit
$ cd
$ cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz .
$ unzip server.conf.gz

Example server.conf

# The server will take 10.8.0.1 for itself,
# the rest will be made available to clients.
# Each client will be able to reach the server
# on 10.8.0.1. Comment this line out if you are
# ethernet bridging. See the man page for more info.
server 10.8.0.0 255.255.255.0
# Choose an unused private subnet.  The default 10.8.0.0/24 was ok for me, it may not be for you.

# Maintain a record of client - virtual IP address
# associations in this file.  If OpenVPN goes down or
# is restarted, reconnecting clients can be assigned
# the same virtual IP address from the pool that was
# previously assigned.
ifconfig-pool-persist ipp.txt

# Push routes to the client to allow it
# to reach other private subnets behind
# the server.  Remember that these
# private subnets will also need
# to know to route the OpenVPN client
# address pool (10.8.0.0/255.255.255.0)
# back to the OpenVPN server.
push "route 172.16.0.0 255.255.255.0"
#I wanted the machines behind my firewall to be reachable by clients.

# The keepalive directive causes ping-like
# messages to be sent back and forth over
# the link so that each side knows when
# the other side has gone down.
# Ping every 10 seconds, assume that remote
# peer is down if no ping received during
# a 120 second time period.
keepalive 10 120

# Enable compression on the VPN link.
# If you enable it here, you must also
# enable it in the client config file.
comp-lzo
# ^ This is worth doing - speeds things up a LOT!

# The maximum number of concurrently connected
# clients we want to allow.
max-clients 20
# ^ sensible safeguard

# It's a good idea to reduce the OpenVPN
# daemon's privileges after initialization.
#
# You can uncomment this out on
# non-Windows systems.
user nobody
group nobody
# will create nobody group later

# The persist options will try to avoid
# accessing certain resources on restart
# that may no longer be accessible because
# of the privilege downgrade.
persist-key
persist-tun

# Output a short status file showing
# current connections, truncated
# and rewritten every minute.
status openvpn-status.log

# Set the appropriate level of log
# file verbosity.
#
# 0 is silent, except for fatal errors
# 4 is reasonable for general usage
# 5 and 6 can help to debug connection problems
# 9 is extremely verbose
verb 3
#EOF

OK, we need to generate the keys now. Fortunatly, there are some great little scripts that come with OpenVPN that make this a simple task.

# cd /etc/openvpn
# cp -r /usr/share/doc/openvpn/examples/easy-rsa .
# cd easy-rsa

We need to set some options to build the certs and keys:

# vi vars

Find this section and fill out the values to suit:

# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY=UK
export KEY_PROVINCE=Staffordshire
export KEY_CITY=Stafford
export KEY_ORG="Stocksy"
export KEY_EMAIL="stocksy@stocksy.co.uk"
#EOF

Build the Certificate Authority (CA). Mostly, we can accept the defaults:

# . ./vars
# ./clean-all
# ./build-ca

Let's generate a key for the server:

# ./build-key-server

Again, we can just accept the defaults most of the time, but some responses need to be 'y', such as 'Sign the certificate? [y/N]:'

Lets make some client keys!

# ./build-key-client dave
# ./build-key-client mum+dad

...etc. Finally, generate the DH parameters:

# ./build-dh

Before OpenVPN will start, we need to create the group nobody:

# groupadd nobody
# /etc/init.d/openvpn start

You'll need to let OpenVPN through your firewall. I use shorewall, so I did it like this:

# vi /etc/shorewall/zones

#ZONE   DISPLAY         COMMENTS
net     Net             Internet
loc     Local           Local Networks
vpn     VPN             Remote 10.8.0.0/24 subnet


# vi /etc/shorewall/interfaces
#ZONE   INTERFACE       BROADCAST       OPTIONS
net     eth0            detect          dhcp,routefilter,norfc1918,tcpflags
loc     eth1            detect          tcpflags
vpn     tun0

# vi /etc/shorewall/policy

loc             vpn             ACCEPT
vpn             loc              ACCEPT

# vi /etc/shorewall/rfc1918
#SUBNETS                TARGET
10.8.0.0/24             RETURN

# vi /etc/shorewall/rules

# OpenVPN
ACCEPT          net             fw              udp     1194


# shorewall restart

OK, time to configure the clients - let's start with one of my Ubuntu boxes. The first thing to do is copy the right keys and certs to the remote host:

# cd /etc/openvpn/easy-rsa/keys
# scp ca.crt user@remote:~/
# scp dave.crt user@remote:~/
# scp dave.key user@remote:~/

Get an a prompt with ssh and install OpenVPN on the remote computer. The nice thing about OpenVPN is that the same program is used for both client and server:

# ssh user@remote
$ sudo apt-get update
$ sudo apt-get install openvpn

This time we want a client config:

$ sudo -s
# cd /etc/openvpn
# cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf .
# vi client.conf
# Specify that we are a client
client

# Use the same setting as you are using on
# the server.
;dev tap
dev tun

# Are we connecting to a TCP or
# UDP server?  Use the same setting as
# on the server.
;proto tcp
proto udp

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote your-server's-hostname-here 1194

# Keep trying indefinitely to resolve the
# host name of the OpenVPN server.  Very useful
# on machines which are not permanently connected
# to the internet such as laptops.
resolv-retry infinite

# Most clients don't need to bind to
# a specific local port number.
nobind

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nobody

# Try to preserve some state across restarts.
persist-key
persist-tun

# SSL/TLS parms.
# See the server config file for more
# description.
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/hawthorn.crt
key /etc/openvpn/keys/hawthorn.key

# Verify server certificate by checking
# that the certicate has the nsCertType
# field set to "server".  This is an
# important precaution to protect against
# a potential attack discussed here:
#  http://openvpn.sourceforge.net/howto.html#mitm
#
# To use this feature, you will need to generate
# your server certificates with the nsCertType
# field set to "server".  The build-key-server
# script in the easy-rsa folder will do this.
ns-cert-type server

# Enable compression on the VPN link.
comp-lzo

# Set log file verbosity.
verb 4
#EOF

Let's put the keys in the right place

# cd
# mkdir /etc/openvpn/keys
# mv ca.crt /etc/openvpn/keys
# mv dave.crt /etc/openvpn/keys
# mv dave.key /etc/openvpn/keys

Add group nobody and start OpenVPN

# groupadd nobody
# /etc/init.d/openvpn start

Shorewall is also installed on this Ubuntu box, but the configuation is different this time:

# cd /etc/shorewall
# vi tunnels

#TYPE         ZONE           GATEWAY        GATEWAY ZONE
openvpn       net            server's ip addr

# vi zones
#ZONE   DISPLAY         COMMENTS
net     Net             Internet
vpn     VPN             OpenVPN

# vi rfc1918
#SUBNET                 TARGET
10.8.0.0/24          RETURN

# vi  policy

fw              vpn             ACCEPT
vpn             fw              ACCEPT


# shorewall restart

Switch back to the firewall and look at /etc/openvpn/ipp.txt. You'll see a line like dave,10.8.0.6

Try pinging it from another host

iMac:~ stocksy$ ping -c4 10.8.0.6
PING 10.8.0.6 (10.8.0.6): 56 data bytes
64 bytes from 10.8.0.6: icmp_seq=0 ttl=63 time=59.302 ms
64 bytes from 10.8.0.6: icmp_seq=1 ttl=63 time=57.618 ms
64 bytes from 10.8.0.6: icmp_seq=2 ttl=63 time=58.914 ms
64 bytes from 10.8.0.6: icmp_seq=3 ttl=63 time=56.754 ms

--- 10.8.0.6 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 56.754/58.147/59.302/1.018 ms

Hooray!

OK, for completeness, here's how to set up OpenVPN as a client on Mac OS X:

If you intend to use LZO compression, which I STRONGLY recommend for performance reasons, grab the LZO libraries first:

$ curl -O http://www.oberhumer.com/opensource/lzo/download/lzo-2.02.tar.gz
$ tar zxf lzo-2.02.tar.gz && rm lzo-2.02.tar.gz
$ cd lzo-2.02
$ ./configure --prefix=/usr/local/lzo && make
$ sudo make install

Obtain the latest source tarball from http://www.openvpn.net and untar it:

$ curl -O http://openvpn.net/release/openvpn-2.0.5.tar.gz
$ tar zxf openvpn-2.0.5.tar.gz && rm openvpn-2.0.5.tar.gz
$ cd openvpn-2.0.5

Build it against your new LZO library:

$ ./configure --prefix=/usr/local/openvpn --with-lzo-headers=/usr/local/lzo/include --with-lzo-lib=/usr/local/lzo/lib && make
$ sudo make install

Build your keys as before on the firewall and copy them to the Mac. Place them in the openvpn directory:

# mkdir -p /usr/local/openvpn/etc/keys
# mv powerbook.* /usr/local/openvpn/etc/keys/
# mv ca.crt /usr/local/openvpn/etc/keys/

Create the configuration file:

# vi /usr/local/openvpn/etc/client.conf


# Specify that we are a client and that we
# will be pulling certain config file directives
# from the server.
client

# Use the same setting as you are using on
# the server.
# On most systems, the VPN will not function
# unless you partially or fully disable
# the firewall for the TUN/TAP interface.
;dev tap
dev tun

# Are we connecting to a TCP or
# UDP server?  Use the same setting as
# on the server.
;proto tcp
proto udp

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote 194.106.52.245 1194
;remote my-server-2 1194

# Keep trying indefinitely to resolve the
# host name of the OpenVPN server.  Very useful
# on machines which are not permanently connected
# to the internet such as laptops.
resolv-retry infinite

# Most clients don't need to bind to
# a specific local port number.
nobind

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nobody

# Try to preserve some state across restarts.
persist-key
persist-tun

# SSL/TLS parms.
# See the server config file for more
# description.
ca /usr/local/openvpn/etc/keys/ca.crt
cert /usr/local/openvpn/etc/keys/powerbook.crt
key /usr/local/openvpn/etc/keys/powerbook.key

# Verify server certificate by checking
# that the certicate has the nsCertType
# field set to "server".  This is an
# important precaution to protect against
# a potential attack discussed here:
#  http://openvpn.sourceforge.net/howto.html#mitm
#
# To use this feature, you will need to generate
# your server certificates with the nsCertType
# field set to "server".  The build-key-server
# script in the easy-rsa folder will do this.
ns-cert-type server

# Enable compression on the VPN link.
# Don't enable this unless it is also
# enabled in the server config file.
comp-lzo

# Set log file verbosity.
verb 4

Finally, we need a kernel extension to handle tunX interfaces. Mattius Nissler has written just such an extension: http://www-user.rhrk.uni-kl.de/~nissler/tuntap/

Untar the tarball and install just the tun_kext.pkg and startup_item.pkg packages. Reboot.

$ sudo /usr/local/openvpn/sbin/openvpn /usr/local/openvpn/etc/client.conf

OpenVPN should start OK. Check with

$ ifconfig tun0

New Comments

Some Rights Reserved