OpenVPN Setup Guide for Beginners

This is a beginner's guide to setting up OpenVPN on a server and a client (and a PKI) where, in this instance, both are running OpenWrt (although the OpenVPN client could easily be running on another OS, such as Windows, or *nix). Because of that, this HOWTO is quite long & wordy.

For non-beginners, vpn.server.openvpn.tun may be a better place to start.

The primary goal of this HOWTO is purely to create a working OpenVPN tunnel. However, once the tunnel is working, then it can be further 'tuned' for specific use-cases. The strategy here is to keep it simple, and get the OpenVPN tunnel working before adding the complexity required for 'real-world' use-cases. Because of that, this is a very basic OpenVPN tunnel configuration that may not suit most people's needs.

However, once the basic tunnel is working, then additional 'recipes' for other use-cases can be found at vpn.server.openvpn.tun (sorry, that wiki page is a WIP). Such use-cases might include: TAP, multiple-VPN routers, VPN-over-SOCKS, etc.

For real-world tunnels, vpn.server.openvpn.tun may be a better place to start.

Note that all of the 'work' here is accomplished via non-interactive commands (that you should cut-and-paste to minimize transcription errors), and there are no files to edit. It requires console access to your OpenWrt router (usually via SSH) rather than via LuCI.

What follows has been tested on trunk (currently BB, b39757), but will likely work on the latest stable branch (currently AA, b39408). It is based upon OpenVPN v2.3, but will likely work with v2.2.

For an overview of all VPN-related articles (including other VPN technologies) in the OpenWrt wiki, see vpn.overview.

Use Case (the beginner's configuration)

The user wants a client to access their OpenWrt router without the possibility of being 'snooped'. That is, the user can already access the router, but (say) over a 'public' network, such as the Internet (different subnets), or a Wifi Hotspot (same subnet).

The end result will be a private connection directly between the OpenVPN client and server. Mostly, it is as if the two end-points are in the same subnet (but not the same subnet as your router's LAN).

DIAGRAM: [client]– {Private Tunnel} –[OpenWrt router]

Terminology: The OpenVPN server is listening for a request to negotiate a VPN tunnel. The OpenVPN client initiates the negotiation for that VPN tunnel.

To facilitate configuration/testing, this guide permits two distinct flavors of this use-case:

  • Scenario 0: the OpenVPN client can 'ping' the OpenWrt router via the router's LAN interface. Specifically, they are in the same subnet (e.g. the client is a DHCP client of the OpenWrt router).
  • Scenario 1: the OpenVPN client can 'ping' the OpenWrt router via the router's WAN interface (and preferably using a public DNS FQDN). Specifically, they are not in the same subnet (e.g. they are separated by the Internet).
Scenario 0 takes out much of the complexity of 'real-world' configurations, such as the vagaries of the Internet, or your OpenWrt firewall configuration.

DIAGRAM s0: {Internet} –WAN iface-||firewall||-[OpenWrt router]-LAN iface– {LAN} –[client]

DIAGRAM s1: [client]– {Internet} –WAN iface-||firewall||-[OpenWrt router]-LAN iface– {LAN}

Scenario 0 allows you to most easily implement an OpenVPN tunnel (i.e. at home), which can then (relatively easily) be switched to Scenario 1, which itself is the basis of most 'real-world' OpenVPN tunnel configurations. You can either start with Scenario 0, and switch to Scenario 1 when you've got it working, or start directly with Scenario 1 (and switch back to Scenario 0 for troubleshooting).

Overview of the process

Installing and (more importantly) configuring an OpenVPN tunnel consists of the following process:

  1. Creating and distributing the PKI certificates and their keys to the server and the clients
  2. Configuring the network (i.e. devices, interfaces, and firewall)
  3. Configuring, starting and testing the VPN tunnel

Prerequisites

This HOWTO:

  1. requires that the client can ping the server (via either it's WAN or LAN interface)
  2. requires the OpenVPN server (listener) is an OpenWRT router (look elsewhere for help with OpenVPN servers running on Linux, Windows, etc.)
  3. prefers the OpenVPN client is an OpenWRT router (but could easily be based upon Linux, Windows, etc.)
  4. requires TUN (routing, recommended) rather than for TAP (bridging)

Part 1/1 - Installing the OpenVPN packages

:!: Before executing Step 1, you should check which specific version of OpenWRT you have. See the notes below for more information.

  1. On both the client and the server, install the OpenVPN package:
      opkg update; opkg install openvpn-openssl  ## or: opkg install openvpn

Which package you should install will be indicated by which version of OpenWRT you have (check via: cat /etc/banner):

  • on Barrier Breaker: there are three versions of OpenVPN that you can choose from, including: openvpn-openssl (used here), openvpn-polarssl (warning: polarssl might not work with the following scripts), or openvpn-nossl (it should be obvious why you should not use that one).
  • on Attitude Adjustment: there is only one version of OpenVPN that you can install, openvpn (which uses OpenSSL)

Creating the Client and Server PKI Certificates

Easy-RSA is a simple PKI that was spun off from OpenVPN as a separate project. With OpenVPN, there does exist a means of creating client/server certificates that does not require a PKI (known as static keys), but Easy-RSA is used here as it is a simple enough method, and using a proper PKI is much better practice.

Part 1/2 - Create the CA and the Certificates

We will create a certificate for the OpenVPN server (named as my-server), and for the first OpenVPN client (named as my-client).

  1. On the OpenVPN Server, install the Easy-RSA package:
      opkg update; opkg install openvpn-easy-rsa
  2. If running Attitude Adjustment (specifically, version 2.2.2-2 of the Easy-RSA package), then you must 'tweak' the PKI configuration to prevent problems later on (this step 'comments-out' the relevant code):
      sed -i '/KEY_CN/ s:^export:# &:' /etc/easy-rsa/vars  ## do not set the KEY_CN environment variable
  3. Establish the shell variables, and start with a clean slate (you may get warnings about ./clean-all, which you can ignore):
      source /etc/easy-rsa/vars
      clean-all
  4. Create the Certification Authority, Server, and Client certificates:
      pkitool --initca            ## equivalent to the 'build-ca' script
      pkitool --server my-server  ## equivalent to the 'build-key-server' script
      pkitool          my-client  ## equivalent to the 'build-key' script
  5. Finally, create the Diffie Hellman parameters (left until last because it can take a long time):
      build-dh                    ## this script will 'take a long time'

If you get an error message TXT_DB error number 2, then check that the CommonName variable is not set: that is, set | grep KEY_CN must return no results. The failure is because subsequent certificates have the same identifier as first (the server's). If required, execute unset KEY_CN, and start again from Step 2.

Potential traps and pitfalls

:!: If you want more than one OpenVPN (concurrent) client, then you will need to create multiple client certificates, and each should have a different name ( (e.g. 'my-client01', 'my-client02', etc.).

Testing & troubleshooting your configuration

You can confirm everything is OK so far via: ls $KEY_DIR; there should be index.txt and serial, the Diffie-Hellman files, and three pairs of .crt/.key files (plus some other files).

If required, you can start from scratch (i.e. destroy the old PKI, and create a completely new one) by re-starting this process from Step 2. :!: If you've copied any of the earlier certificates elsewhere, be sure to delete them. Be warned that it would be relatively easy to confuse these (new) certificate/key sets with older sets, since they just happen to have the same filenames!

Part 2/2 - Distribute the Certificates

:!: Before executing Step 3, you'll have to find a way achieving Step 2 (discussed only briefly here). See the notes below for more information.

  1. On the server, copy the server certificate to where OpenVPN needs it to be ($KEY_DIR is a variable set by source /etc/easy-rsa/vars):
      cd $KEY_DIR
      mkdir -p /etc/openvpn
      cp ca.crt my-server.* dh*.pem  /etc/openvpn/     ## the server files (note: dh*.pem is required)
  2. Next, you'll need to copy the client certificate from the server to the client (e.g. via a USB stick, or using the scp utility).
  3. On the client, copy the server certificate to where OpenVPN needs it to be, example:
      cp ca.crt my-client.*          /etc/openvpn/     ## the client files (note: dh*.pem is not used)

Discussion

For security reasons, you need to think long and hard about where you backup your PKI files, and especially the .key files:

  • ca.key should be moved to a place that is not accessible from the Internet; it needed only when 'doing' CA stuff, such as creating certificates (but not using those certificates)
  • the other .key files should be kept 'private', that is, stored only on the 'owning' system
  • all .key files should never be distributed in an insecure manner - it is well known that copying .key files across the Internet is a leading cause of male-pattern baldness!

Configuring the Network Infrastructure

Before you start this, you must confirm that the client can ping the OpenWrt router.

Also, you need to know if the OpenVPN client and server are: * (Scenario 0) on the same subnet (i.e. ping via the router's LAN port) * (Scenario 1) either side of the Internet (i.e. ping via the router's WAN port)

Part 1/2 Configure the Network on the Server

This is the configuration of the OpenVPN server only.

  1. Create the VPN interface (note that the tun0 device does not yet exist):
      uci set network.vpn0=interface
      uci set network.vpn0.ifname=tun0
      uci set network.vpn0.proto=none
     
      uci commit network; /etc/init.d/network reload
  2. Allow OpenVPN tunnel negotiation (i.e. accept inbound traffic and thereby allow a tunnel to be created):
      uci add firewall  rule
      uci set firewall.@rule[-1].name=Allow-OpenVPN-Inbound
      uci set firewall.@rule[-1].target=ACCEPT
      uci set firewall.@rule[-1].src=*
      uci set firewall.@rule[-1].proto=udp
      uci set firewall.@rule[-1].dest_port=1194
  3. Allow OpenVPN tunnel utilization (i.e. allow a tunnel to be used):
      uci add firewall  zone
      uci set firewall.@zone[-1].name=vpn
      uci set firewall.@zone[-1].input=ACCEPT
      uci set firewall.@zone[-1].forward=ACCEPT
      uci set firewall.@zone[-1].output=ACCEPT
      uci set firewall.@zone[-1].network=vpn0
  4. Finally, commit the changes:
      uci commit firewall; /etc/init.d/firewall reload

Testing & troubleshooting your configuration

There's not much you can do now, but later, when it comes time to test communication between the client and the server (either before or after the OpenVPN tunnel is established), you could disable the server's firewall altogether to see if it's the reason why you're having problems (see below).

Execute: uci show network | grep ifname to see the interface of each network (e.g. 3gwan network via usb0 interface). Execute: uci show firewall | grep zone | grep -E "(net|name)" to see the networks of each zone (e.g. wan/3gwan networks in wan zone).

Part 2/2 Configure the Network on the Client

This is how to configure the network on an OpenVPN client running on OpenWrt. This process consists of essentially the same sequence of steps as for the OpenVPN server, above.

:!: Note that Step 3 is not required on a client.

This is how to configure the network on an OpenVPN client:

  1. Create the VPN interface (this is the same as for the server).
  2. Don't do this step on a client - most OSs allow outbound (client-instigated) tunnels.
  3. Allow OpenVPN tunnel utilization (this is the same as for the server).
  4. Finally, commit the changes (this is the same as for the server).

Testing & troubleshooting your configuration

More later…

Configuring the OpenVPN Infrastructure

This process consists of four steps that are essentially the same on both an OpenWrt-based OpenVPN clients and servers. However, non-OpenWRT-based clients usually require OpenVPN configuration files (i.e. they don't have OpenWrt's UCI).

These configurations have been intentionally kept simple; they are the minimal required to get an effective OpenVPN tunnel (i.e. the tunnel you get will work, but may not yet be useful). Do not add any options (i.e. any additional complexity) until you have confirmed the tunnel is functioning correctly. For your own benefit, do not bother with persist_XXX, or comp_lzo at this stage.

:!: I recommend you copy-and-paste these scripts rather than re-type them.

Part 1/2 - Configure and Start the Server

This is how to configure and start the OpenVPN Server running on OpenWrt.

  1. Clear the existing OpenVPN configuration, and create a new configuration called (in this case) 'myvpn' (NB: this step is the same for the OpenWrt OpenVPN client as well). Ensure that, in particular, the last three lines (the ca, cert, and key options) do not produce an error (such as "No such file or directory"):
      echo > /etc/config/openvpn                                ## Clear the existing configuration
     
      uci set openvpn.myvpn=openvpn                             ## This tunnel is called 'myvpn'
      uci set openvpn.myvpn.enabled=1
     
      uci set openvpn.myvpn.dev=tun                             ## This is the basic tunnel configuration
      uci set openvpn.myvpn.proto=udp
     
      uci set openvpn.myvpn.log=/tmp/openvpn.log                ## These options produce a useful log file
      uci set openvpn.myvpn.verb=3
     
      uci set openvpn.myvpn.ca=/etc/openvpn/ca.crt              ## These options are required for tunnel negotiation
      uci set openvpn.myvpn.cert=`ls /etc/openvpn/my-*.crt`     ## NB: these are back-quotes
      uci set openvpn.myvpn.key=`ls /etc/openvpn/my-*.key`      ## NB: these are back-quotes
  2. To that, add the server-specific options. Ensure that, in particular, the last line (the dh option) does not produce an error:
      uci set openvpn.myvpn.server='10.8.0.0 255.255.255.0'     ## NB: these are single quotes
      uci set openvpn.myvpn.port=1194
     
      uci set openvpn.myvpn.keepalive='10 120'                  ## NB: these are single quotes
     
      uci set openvpn.myvpn.dh=`ls /etc/openvpn/dh*.pem`        ## NB: these are back-quotes
  3. And finally, the tricky server-specific option (this will be changed later):
      uci set openvpn.myvpn.push=''                             ## NB: these are single quotes
  4. Commit the configuration, and enable OpenVPN:
      uci commit openvpn; /etc/init.d/openvpn enable

Potential traps and pitfalls

:!: The UCI system is very good, but has it's little quirks. Be aware that (generally) OpenVPN options either require a underscore, or a dash according to whether they are to the left or the right of the '=' sign. See the comp-lzo option, below (do not execute these commands):

  uci set openvpn.test.comp_lzo=adaptive                    ## NB: do not execute these commands
  uci set openvpn.test.push='comp-lzo=adaptive'             ## NB: do not execute these commands

Testing & troubleshooting the configuration

Now you can start the OpenVPN server and check the listener.

  1. Start OpenVPN, and confirm that there is an OpenVPN daemon and a TUN:
      /etc/init.d/openvpn start; sleep 3
      ps -w | grep openvpn
      ifconfig | grep tun0
  2. If the OpenVPN server is working OK, then you would expect there to be a result from (this is only for a server):
      netstat -an | grep 1194

If things go wrong (now or later), then for troubleshooting:

  1. A good place to start is the log file:
      cat /tmp/openvpn.log

Part 2/2 - Configure the (OpenWrt) Client

This is how to configure and start an OpenVPN client running on OpenWrt. This process consists of essentially the same sequence of steps as for the OpenVPN server, above.

:!: Before you execute Step 3, you need to know the IP address, or FQDN (VPN_SERVER_ID, below) that the client will use to access the server.

First, create a variable with the IP address (XXX.XXX.XXX.XXX, below) or FQDN and test that you can get a ping response.:

  set VPN_SERVER_ID="XXX.XXX.XXX.XXX"
  ping -c 4 ${VPN_SERVER_ID}

If that works, then you can configure the client, as below.

  1. Clear the default OpenVPN configuration, and create a new configuration called 'myvpn' (as for the server, above).
  2. To that, add the client-specific parameters (this is different from above):
      uci set openvpn.myvpn.client=1
      uci set openvpn.myvpn.remote_cert_tls=server
  3. The client also has a tricky bit (read :!: above before you execute this command):
      uci set openvpn.myvpn.remote='${VPN_SERVER_ID} 1194'    ## NB: these are single quotes
  4. Commit the configuration, and enable OpenVPN (as for a server, above):
    uci commit openvpn

Testing & troubleshooting your configuration

That's it for the client! Now you can start the OpenVPN client and check the tunnel.

  1. Before starting the tunnel, you should (again) be able to ping the server from the client:
      ping -c 4 $(uci -P/var/state get openvpn.myvpn.remote | awk '{print $1;}')
  2. Start OpenVPN, and confirm that there is an OpenVPN daemon and a TUN:
      /etc/init.d/openvpn start; sleep 3
      ps | grep openvpn
      ifconfig | grep tun0

Testing the tunnel:

  1. The tunnel should have made a change to the client's route table (so you can access the tunnel end-point, should be 10.8.0.1):
      cat /tmp/openvpn.log | grep 'route add'
         ...
      route
  2. You should be able to ping the tunnel end-point (i.e. the OpenVPN server):
      traceroute 10.8.0.1
  3. You should still be able to ping hosts on the Internet via your default gateway:
      traceroute 8.8.8.8
  4. You should be able to ping hosts on the Internet via the tunnel:
      route add -net 8.8.4.4 netmask 255.255.255.255 gateway 10.8.0.5
      route
         ...
      traceroute 8.8.4.4

In particular, look at hops 1 and 2 of the traceroute; hop 1 should be one of the gateways from your route table. If hop 2 of traceroute 8.8.4.4 is the IP address of VPN_SERVER_ID, then the tunnel is working.

:-D Congratulations! Now look to 'tune' the OpenVPN tunnel for a specific use-case.

However, if things go wrong (now or later), then for troubleshooting:

  1. A good place to start is the log file:
      cat /tmp/openvpn.log
  2. In addition, you could try (temporarily) turning off the firewall on the OpenVPN server (i.e. execute the following command on the server, and not the client):
      /etc/init.d/firewall stop
       ...
      /etc/init.d/firewall start

:!: Don't forget to restart your firewall after you have finished troubleshooting (or just reboot).

Routing All Client Traffic Through the Tunnel

If the OpenVPN server can access the Internet, then the client has the option of routing all its IP traffic via the tunnel rather than through it's local gateway. If the tunnel is merely provide access to other subnets (e.g. to access a server at home from work), but Internet access is to remain as-is, then this is not your answer. Instead, see XXX.

Before you do this, you should know whether your network is Scenario 1 (client and server in different subnets), or Scenario 2 (client and server in the same subnet).

In Scenario 1, the client and server are in different subnets:

  1. On the OpenVPN server, execute the following
      uci set openvpn.myvpn.push='redirect-gateway def1'        ## NB: these are single quotes
      uci commit openvpn; /etc/init.d/openvpn restart
  2. On the OpenVPN client, execute the following:
      /etc/init.d/openvpn restart
      traceroute 8.8.8.8

Alternatively, in Scenario 2, the client and server are in the same subnet (useful for creating/testing an OpenVPN tunnel at home):

  1. On the OpenVPN server, execute the following:
      uci set openvpn.myvpn.push='redirect-gateway def1 local'  ## NB: these are single quotes
      uci commit openvpn; /etc/init.d/openvpn restart
  2. On the OpenVPN client, execute the following:
      /etc/init.d/openvpn restart
      traceroute 8.8.8.8

:!: If your OpenVPN client is not to route all it's traffic via the server (and therefore continue to use it's existing default gateway), then you should not push the redirect-gateway option at all.

You might need to make OpenWRT route traffic from vpn to wan. Add to /etc/config/firewall:

config forwarding
	option src 'vpn'
	option dest 'wan'
This worked for BB RC2 (uci commands would be better).

Once this is working, head to vpn.server.openvpn.tun for more OpenVPN 'recipes'.

Testing & troubleshooting your configuration

Test as above.

Configuring OpenVPN for Other OSs

Below is a copy of an OpenVPN configuration file that is identical to that created above for OpenWrt OpenVPN clients.

Create an OpenVPN client configuration file

In your favorite text editor on the client machine that will be connecting, paste the following. Save the file as client.ovpn:

dev tun
proto udp
 
log openvpn.log
verb 3
 
ca ca.crt
cert MY-CLIENT.crt
key MY-CLIENT.key
 
client
remote_cert_tls server
 
remote VPN_SERVER_ID 1194

:!: Make sure to try and mirror ALL the server options client-side, whatever client you're using, as some of them (especially LZO compression) can have adverse effects if they're not present in BOTH configurations.

Completed OpenVPN Configuration

Below is a copy a the final OpenVPN configuration as produced by this beginner's guide (HOWTO). Note that some of these settings are very implementation-specific.

On OpenWrt, standard-format OpenVPN configuration files are not normally used (although you can do so if you wish). Instead, these configuration files are dynamically created from /etc/config/openvpn by /etc/init.d/openvpn during it's startup process. If OpenVPN is running, then the specific name/location of the OpenVPN-compatible configuration file can be seen with ps -w | grep openvpn. If required, you can copy this file and use it elsewhere!

Server Configuration

If you execute cat /etc/config/openvpn on an OpenWrt-based OpenVPN client, you 'should' get:

config openvpn 'myvpn'
        option enabled '1'
        option dev   'tun'
        option proto 'udp'

        option server    '10.8.0.0 255.255.255.0'
        option port      '1194'
        option keepalive '10 120'

        option ca   '/etc/openvpn/ca.crt'
        option key  '/etc/openvpn/my-server.key'
        option cert '/etc/openvpn/my-server.crt'
        option dh   '/etc/openvpn/dh2048.pem'

        option log  '/tmp/openvpn.log'
        option verb '3'

Alternatively, you could execute uci show openvpn to see the same configuration, but in UCI format. It may be easier to make changes via UCI, or by directly editing the OpenWrt configuration file directly.

Client Configuration (OpenWrt-based clients)

If you execute cat /etc/config/openvpn on an OpenWrt-based OpenVPN client, you 'should' get:

config openvpn 'myvpn'
        option enabled '1'
        option dev   'tun'
        option proto 'udp'

        option client '1'
        option remote '172.27.0.1 1194'

        option ca   '/etc/openvpn/ca.crt'
        option cert '/etc/openvpn/my-client.crt'
        option key  '/etc/openvpn/my-client.key'
        option remote_cert_tls 'server'

        option log  '/tmp/openvpn.log'
        option verb '3'

Note that your OpenVPN server will probably have a different IP address (or even a FQDN) to that used here.

Client Configuration File (standard clients)

If you execute (the equivalent of) cat /var/etc/openvpn-myvpn.conf on any OpenVPN client, you should get:

dev tun
proto udp

client
remote 172.27.0.1 1194

ca   /etc/openvpn/ca.crt
cert /etc/openvpn/my-client.crt
key  /etc/openvpn/my-client.key
remote-cert-tls server

log  /tmp/openvpn.log
verb 3

Other Stuff

General guidelines for troubleshooting

This command is useful:

ps -w | grep openvpn

You should see a *.conf file after —-config. You can then execute this more useful command:

cat  /var/etc/*.conf

* Make sure you are trying to connect to the VPN server from the outside - i.e. use 3G connection, go to a different building etc. Using another vpn (that routes all your traffic) does not seem to help. If you do not do this, a good configuration might not work at all.

* Attention: The logfile (if not in system log) doesn't limit its disk space - check periodically that you have enough free disk space for other applications (my log on level 6 needed less than a week to fill the whole disk space of a TP-Link 1043). [the way to fix this is: a) use verb=3, and b) use logrotate]

FIXME: Please read vpn.overview and see this old articles on this matter: http://wiki.openwrt.org/?do=search&id=vpn and help migrate them. There is also an article in the inbox: vpn.howto

When truly stuck: asking for help

In short, hit the OpenWrt forum: https://forum.openwrt.org/viewforum.php?id=10.

:!: If you do so, then please use code tags https://forum.openwrt.org/help.php?section=bbcode (otherwise your post will be TL;DR)!

At a minimum, you'd be expected to a) create an intelligent request for help, and b) paste a copy of the following files:

cat /tmp/openvpn.log
cat /etc/config/network
cat /etc/config/firewall
cat /etc/config/openvpn

References

Back to top

doc/howto/vpn.openvpn.txt · Last modified: 2014/08/20 23:40 by zxdavb