OpenVPN - It just works!
5th Nov 2005, 10:37:53
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