The FreeBSD Diary

The FreeBSD Diary (TM)

Providing practical examples since 1998

If you buy from Amazon USA, please support us by using this link.
[ HOME | TOPICS | INDEX | WEB RESOURCES | BOOKS | CONTRIBUTE | SEARCH | FEEDBACK | FAQ | FORUMS ]
OpenVPN - getting it running 27 November 2008
Need more help on this topic? Click here
This article has 1 comment
Show me similar articles

This article is about OpenVPN, a full-featured open source SSL VPN solution. I first started using OpenVPN in December 2006. That is nearly two years ago. I took some notes but I never published anything until today. My original use for OpenVPN was easy access to my home network while away from home. For this is was wonderful. Being able to ssh "directly" to my machines, cvsup, etc, was very convenient.

NOTE: The solution here is rather simplistic. It allows for a single client to connect to a single server. You cannot do multiple clients with this setup. If you need multiple clients, try reading my aritcle on creating a routed VPN.

Today, my goals have changed somewhat. I still want to use OpenVPN to get into my office network. In this article, I will refer to the VPN server as the office network (after all, it is my home office). Now new goals have arise as new problems arise or old problems become more burdensome. Recently, I've become much more annoyed with my Dynamic IP address at home. I've outlined the problems in my other diary and I urge you to read that before proceeding. It will provide valuable background as to why I have chosen this particular solution.

This article assumes you know how to setup firewall rules, adjust them, diagnose routing issues, etc. I'm just here to show you OpenVPN.

For another view on installing OpenVPN on FreeBSD, see FreeBSD OpenVPN Server HowTo.

Certificates

This particular configuration of OpenVPN will make use of OpenSSL certificates. Creation of certificates is complex enough to justify its own article. As such, I will assume you have used that reference for creating your certificates and will not refer that process at all here.

Installing

Installing OpenVPN on FreeBSD is pretty simple:

cd /usr/ports/security/openvpn
make install clean/usr/ports/security/openvpn

You will find sample configuration files at /usr/local/share/doc/openvpn/sample-config-files but I will share my configuration files with you.

TAP interfaces

I have chosen a particular OpenVPN solution that makes use of a virtual ethernet device. This device must be loaded before running OpenVPN. You can do this on the command line with this:

kldload if_tap

To ensure this module is loaded at boot time, add the following line to /boot/loader.conf:

if_tap_load="YES"

If you see an error like this one, then you have forgotten to load this particular kernel module:

openvpn[1264]: Cannot allocate TUN/TAP dev dynamically
kldload if_tap
Server configuration

This section shows you the setup of my OpenVPN server. The main configuration file is /usr/local/etc/openvpn/openvpn.conf. This is mine:

#
# Sample OpenVPN configuration file for
# office using SSL/TLS mode and RSA certificates/keys.
#
# '#' or ';' may be used to delimit comments.

# Use a dynamic tun device.
# For Linux 2.2 or non-Linux OSes,
# you may want to use an explicit
# unit number such as "tun1".
# OpenVPN also supports virtual
# ethernet "tap" devices.
dev tap

# 192.168.100.2 is our local VPN endpoint (home).
# 192.168.100.3 is our remote VPN endpoint (office).
ifconfig 192.168.100.3 255.255.255.0

# In SSL/TLS key exchange, Office will
# assume server role and Home
# will assume client role.
tls-server

# Diffie-Hellman Parameters (tls-server only)
dh /usr/local/etc/openvpn/keys/dh1024.pem

# Certificate Authority file
ca /usr/local/etc/openvpn/keys/ca.crt

# Our certificate/public key
cert /usr/local/etc/openvpn/keys/myserver.example.com.crt

# Our private key
key /usr/local/etc/openvpn/keys/myserver.example.com.key

# OpenVPN 2.0 uses UDP port 1194 by default
# (official port assignment by iana.org 11/04).
# OpenVPN 1.x uses UDP port 5000 by default.
# Each OpenVPN tunnel must use
# a different port number.
# lport or rport can be used
# to denote different ports
# for local and remote.
port 1194

# Downgrade UID and GID to
# "nobody" after initialization
# for extra security.
; user nobody
; group nobody

# Verbosity level.
# 0 -- quiet except for fatal errors.
# 1 -- mostly quiet, but display non-fatal network errors.
# 3 -- medium output, good for normal operation.
# 9 -- verbose, good for troubleshooting
verb 3

status openvpn-status.log

From the above configuration, you will need to get the certificate public key, the certificate private key, the CA public key, and the Diffie-Hellman Parameters file (see the items in bold above). Each of these files were created when you followed the instructions in the CA reference article.

You must copy the .key files over a secure channel. Do not email it.

To start OpenVPN at boot time, you need to add the following items to /etc/rc.conf:

openvpn_enable="YES"
openvpn_if="tap"

The second line defines the interface to use, in this case, tap(4).

Starting the server

To start the server, issue this command:

# /usr/local/etc/rc.d/openvpn start
Starting openvpn.

If you look at /var/log/messages, you should see something like this:

openvpn[52594]: OpenVPN 2.0.6 i386-portbld-freebsd6.3 [SSL] [LZO] built on Jun  1 2008
openvpn[52594]: Diffie-Hellman initialized with 1024 bit key
openvpn[52594]: Control Channel MTU parms [ L:1573 D:138 EF:38 EB:0 ET:0 EL:0 ]
openvpn[52594]: TUN/TAP device /dev/tap0 opened
openvpn[52594]: /sbin/ifconfig tap0 192.168.100.3 netmask 255.255.255.0 mtu 1500 up
openvpn[52594]: Data Channel MTU parms [ L:1573 D:1450 EF:41 EB:4 ET:32 EL:0 ]
openvpn[52594]: Local Options hash (VER=V4): '6ab3b73a'
openvpn[52594]: Expected Remote Options hash (VER=V4): 'ea8adc0d'
openvpn[52597]: UDPv4 link local (bound): [undef]:1194
openvpn[52597]: UDPv4 link remote: [undef]

You should also see a tap device such as this:

tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        inet6 fe80::2bd:a4ff:fe65:0%tap0 prefixlen 64 scopeid 0x8
        inet 192.168.100.3 netmask 0xffffff00 broadcast 192.168.100.255
        ether 00:bd:a4:65:00:00
        Opened by PID 52594

That looks good. Now let us start the client.

Client configuration

On the client, as on the server, I have this in /etc/rc.conf:

openvpn_enable="YES"
openvpn_if="tap"

The configuration file, /usr/local/etc/openvpn/openvpn.conf, contains this:

#
# Sample OpenVPN configuration file for
# home using SSL/TLS mode and RSA certificates/keys.
#
# '#' or ';' may be used to delimit comments.

# Use a dynamic tun device.
# For Linux 2.2 or non-Linux OSes,
# you may want to use an explicit
# unit number such as "tun1".
# OpenVPN also supports virtual
# ethernet "tap" devices.
dev tap

# Our OpenVPN peer is the office gateway.
float
remote myserver.example.com

# 192.168.100.2 is our local VPN endpoint (home).
# 192.168.100.3 is our remote VPN endpoint (office).
ifconfig 192.168.100.2 255.255.255.0
route 10.55.0.0 255.255.255.0 192.168.100.3

# In SSL/TLS key exchange, Office will
# assume server role and Home
# will assume client role.
tls-client

ns-cert-type server

# Certificate Authority file
ca /usr/local/etc/openvpn/keys/ca.crt

# Our certificate/public key
cert /usr/local/etc/openvpn/keys/client.example.com.crt

# Our private key
key /usr/local/etc/openvpn/keys/client.example.com.key

# OpenVPN 2.0 uses UDP port 1194 by default
# (official port assignment by iana.org 11/04).
# OpenVPN 1.x uses UDP port 5000 by default.
# Each OpenVPN tunnel must use
# a different port number.
# lport or rport can be used
# to denote different ports
# for local and remote.
port 1194

# Downgrade UID and GID to
# "nobody" after initialization
# for extra security.
user nobody
group nobody

persist-key
persist-tun

# Send a UDP ping to remote once
# every 15 seconds to keep
# stateful firewall connection
# alive.  Uncomment this
# out if you are using a stateful
# firewall.
ping 15
#keepalive 10 60

# Verbosity level.
# 0 -- quiet except for fatal errors.
# 1 -- mostly quiet, but display non-fatal network errors.
# 3 -- medium output, good for normal operation.
# 9 -- verbose, good for troubleshooting
verb 3

To start the client, issue this command:

# /usr/local/etc/rc.d/openvpn start
Starting openvpn.
add net 10.55.0.0: gateway 192.168.100.3

This is similar to what you should now see in /var/log/messages:

openvpn[62722]: OpenVPN 2.0.6 i386-portbld-freebsd6.3 [SSL] [LZO] built on Nov 26 2008
openvpn[62722]: WARNING: --ping should normally be used with --ping-restart or --ping-exit
openvpn[62722]: Control Channel MTU parms [ L:1573 D:138 EF:38 EB:0 ET:0 EL:0 ]
openvpn[62722]: gw 64.147.113.41
openvpn[62722]: TUN/TAP device /dev/tap0 opened
openvpn[62722]: /sbin/ifconfig tap0 192.168.100.2 netmask 255.255.255.0 mtu 1500 up
openvpn[62722]: /sbin/route add -net 10.55.0.0 192.168.100.3 255.255.255.0
openvpn[62722]: Data Channel MTU parms [ L:1573 D:1450 EF:41 EB:4 ET:32 EL:0 ]
openvpn[62722]: Local Options hash (VER=V4): 'ea8adc0d'
openvpn[62722]: Expected Remote Options hash (VER=V4): '6ab3b73a'
openvpn[62727]: GID set to nobody
openvpn[62727]: UID set to nobody
openvpn[62727]: UDPv4 link local (bound): [undef]:1194
openvpn[62727]: UDPv4 link remote: 172.28.123.191:1194
openvpn[62727]: TLS: Initial packet from 172.28.123.191:1194, sid=9a791e73 6db7b2f9
openvpn[62727]: VERIFY OK: depth=1, /C=US/ST=PA/L=Warrington/O=The_FreeBSD_Diary
                                    /emailAddress=dan@example.com
openvpn[62727]: VERIFY OK: nsCertType=SERVER
openvpn[62727]: VERIFY OK: depth=0, /C=US/ST=PA/O=The_FreeBSD_Diary/CN=myserver.example.com
                                    /emailAddress=dan@example.com
openvpn[62727]: Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key
openvpn[62727]: Data Channel Encrypt: Using 160 bit message hash 'SHA1' for
                                      HMAC authentication
openvpn[62727]: Data Channel Decrypt: Cipher 'BF-CBC' initialized with 128 bit key
openvpn[62727]: Data Channel Decrypt: Using 160 bit message hash 'SHA1' for
                                      HMAC authentication
openvpn[62727]: Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 1024 bit RSA
openvpn[62727]: [myserver.example.com] Peer Connection Initiated with 172.28.123.191:1194
openvpn[62727]: Initialization Sequence Completed

On the server, you should see something like this:

bast openvpn[52597]: TLS: new session incoming connection from 172.10.10.101:1194
bast openvpn[52597]: VERIFY OK: depth=1, /C=US/ST=PA/L=Warrington/O=The_FreeBSD_Diary
                                         /emailAddress=dan@example.com
bast openvpn[52597]: VERIFY OK: depth=0, /C=US/ST=PA/O=The_FreeBSD_Diary
                                         /CN=client.example.com
                                         /emailAddress=dan@example.com
bast openvpn[52597]: Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key
bast openvpn[52597]: Data Channel Encrypt: Using 160 bit message hash 'SHA1' for
                                           HMAC authentication
bast openvpn[52597]: Data Channel Decrypt: Cipher 'BF-CBC' initialized with 128 bit key
bast openvpn[52597]: Data Channel Decrypt: Using 160 bit message hash 'SHA1' for
                                           HMAC authentication
bast openvpn[52597]: TLS: move_session: dest=TM_ACTIVE src=TM_UNTRUSTED reinit_src=1
bast openvpn[52597]: TLS: tls_multi_process: untrusted session promoted to trusted
bast openvpn[52597]: Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 
                                      1024 bit RSA

You should see see a tap device like this on the client:

# ifconfig tap0
tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        inet 192.168.100.2 netmask 0xffffff00 broadcast 192.168.100.255
        ether 00:bd:10:e7:72:00
        Opened by PID 62722
Testing the comms

These tests are done on the client.

Test that you can ping the local end of the VPN:

# ping -c 5 192.168.100.2
PING 192.168.100.2 (192.168.100.2): 56 data bytes
64 bytes from 192.168.100.2: icmp_seq=0 ttl=64 time=0.043 ms
64 bytes from 192.168.100.2: icmp_seq=1 ttl=64 time=0.042 ms
64 bytes from 192.168.100.2: icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from 192.168.100.2: icmp_seq=3 ttl=64 time=0.035 ms
64 bytes from 192.168.100.2: icmp_seq=4 ttl=64 time=0.028 ms

--- 192.168.100.2 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.028/0.037/0.043/0.005 ms

Can we ping the far end of the VPN?

# ping -c 5 192.168.100.3
PING 192.168.100.3 (192.168.100.3): 56 data bytes
64 bytes from 192.168.100.3: icmp_seq=0 ttl=64 time=30.379 ms
64 bytes from 192.168.100.3: icmp_seq=1 ttl=64 time=39.191 ms
64 bytes from 192.168.100.3: icmp_seq=2 ttl=64 time=15.725 ms
64 bytes from 192.168.100.3: icmp_seq=3 ttl=64 time=17.148 ms
64 bytes from 192.168.100.3: icmp_seq=4 ttl=64 time=21.225 ms

--- 192.168.100.3 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 15.725/24.734/39.191/8.853 ms

If you cannot ping the far end of the VPN, check your routing tables, firewall rules etc. Any problems you encounter here are outside the scope of this tutorial.

If these pings work, then traffic from the client to the server should just work.

Unroutable control packet

If you see errors on the server such as this, don't Google them. Look farther up in /var/log/messages for the real error.

openvpn[29610]: TLS Error: Unroutable control packet received from 172.10.10.101:1194
                (si=3 op=P_CONTROL_V1)
last message repeated 10 times
openvpn[29610]: TLS Error: Unroutable control packet received from 172.10.10.101:1194
                (si=3 op=P_ACK_V1)

Look above that for other errors. In my case:

openvpn[29610]: VERIFY ERROR: depth=0, error=unable to get local issuer certificate:
                /CN=client.example.com
openvpn[29610]: TLS_ERROR: BIO read tls_read_plaintext error: error:14090086:SSL
                routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
openvpn[29610]: TLS Error: TLS object -> incoming plaintext read error
openvpn[29610]: TLS Error: TLS handshake failed

In this case, there was clearly something wrong with my setup. I had the wrong certificates or wrong ca.crt file, something like that. Be cautious and careful.

It should just work

The hard part is getting the certificates and configuration correct. The primary goal of this article is to simplify that process. It Should Just Work(tm).

Best wishes. Enjoy.


Need more help on this topic? Click here
This article has 1 comment
Show me similar articles