Basic OpenVPN Server Setup Guide

This is a guide to setting up OpenVPN on a server and a client where, in this instance, both are running OpenWRT. What follows has been tested on trunk (currently BB, b39757), but will likely work on the latest stable branch (currently AA, b39408).

Note that all of the 'work' here is accomplished via non-interactive commands (that you should cut-and-paste), andthere are no files to edit.

This how-to has had a BIG rewrite. If required, you can find the old version here:

Overview of the Process

On the OpenVPN server (and on similarly, on clients), installing and (more importantly) configuring an OpenVPN tunnel consists of the following:

  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 and Starting the VPN listener

Use Case

The user (i.e. client) wants to access the LAN on the other side of the server without being 'snooped' (e.g. via a public WiFi network), and/or the user wants to access the Internet via the server (e.g. to punch through a company firewall and thereby bypass it's restrictions).

This article will be based upon TUN (routing); for TAP (bridging), you will find information elsewhere in this Wiki.


So to make it easier for you, this How-To assumes:

  1. the client and the server are (vanilla-build) OpenWRT routers (look elsewhere for help Linux/Windows/etc.; it wont be too hard for clients)
  2. the client can ping the server though its WAN interface, and that they are not in the same subnet

The OpenVPN client (i.e. the system who initiates the negotiation for the VPN tunnel) must be able to ping (using IPv4) the OpenVPN server (who responds to such requests) via it's WAN interface (and preferably using a public DNS FQDN). In this case, it is assumed that the client, as well as the server (a.k.a. router) are both running OpenWRT (although *nix & Windows clients are also covered).

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 (recommended) or openvpn-polarssl, which might not work with the following scripts (it should be obvious why you should not use openvpn-nossl).
  • on Attitude Adjustment: there is only one version of OpenVPN that you can install, openvpn (which uses OpenSSL)

Creating the Client and Server 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 Certification Authority and the Client/Server Certificates

:!: Before executing Step 3, you may (or may not) need to execute Step 2. See notes below for more information.

  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
  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.


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 3. :!: If you've copied any of the earlier certificates elsewhere, be sure to delete them. Be warned that it would be easy these (new) certificate/key sets with older sets, since they just happen to have the same filenames!

Part 2/2 - Distribute the Certificates to the Clients and Servers

:!: 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).
  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)


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 is only needed when 'doing' CA stuff)
  • the other .key files should be kept 'private', that is, stored only on the 'owning' system
  • all .key files should not 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

Part 1/2 Server Configuration (on OpenWRT)

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.vpn=interface
      uci set network.vpn.ifname=tun0
      uci set network.vpn.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-Inbound-OpenVPN
      uci set firewall.@rule[-1].target=ACCEPT
      uci set firewall.@rule[-1].src=wan
      uci set firewall.@rule[-1].family=ipv4
      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=REJECT
      uci set firewall.@zone[-1].output=ACCEPT
      uci set firewall.@zone[-1].network=vpn
  4. Allow the client to access the OpenVPN server's LAN via the VPN (optional):
      uci add firewall forwarding
      uci set firewall.@forwarding[-1].src=vpn
      uci set firewall.@forwarding[-1].dest=lan
  5. Allow the client to access the OpenVPN server's WAN via the VPN (optional):
      uci add firewall forwarding
      uci set firewall.@forwarding[-1].src=vpn
      uci set firewall.@forwarding[-1].dest=wan
  6. Finally, commit the changes:
      uci commit firewall; /etc/init.d/firewall reload


When reading the following, make sure you're clear on the difference between an interface, a network, and a zone.

Note that Step 4 and 5 overrule the REJECT in Step 3. You may want only Step 4, or only Step 5, or maybe both. That is,

  • Step 3 will allow the VPN client(s) to access the OpenVPN server itself
  • Step 4 will allow the VPN client(s) to access networks via the OpenVPN server's LAN interfaces
  • Step 5 will allow the VPN client(s) to access networks via the OpenVPN server's WAN interfaces

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 Client Configuration

There shouldn't be much to do. Most clients allow outbound (client-instigated) tunnels.

However, you need to think about which Route tables, and which DNS server to use. More later.

Configuring the OpenVPN Infrastructure

This is essentially the same as for a OpenWRT server.

Part 1/2 - Configure and Start the Server

:!: Before you execute Step 3, you should understand the requirements of your specific use-case (i.e. your network configuration). See the notes below for more information.

  1. Clear the default OpenVPN configuration, and create a new OpenVPN configuration called 'myvpn' (it could be called anything). Ensure that, in particular, the last three lines (the ca, cert, and key parameters) do not produce an error:
      echo > /etc/config/openvpn
      uci set openvpn.myvpn=openvpn
      uci set openvpn.myvpn.enabled=1
      uci set
      uci set openvpn.myvpn.persist_tun=1
      uci set openvpn.myvpn.persist_key=1
      uci set openvpn.myvpn.proto=udp
      uci set openvpn.myvpn.comp_lzo=yes
      uci set openvpn.myvpn.verb=3
      uci set openvpn.myvpn.log=/tmp/openvpn.log
      uci set openvpn.myvpn.status=/tmp/openvpn-status.log
      uci set
      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 parameters. Ensure that, in particular, the last line (the dh parameter) does not produce an error:
      uci set openvpn.myvpn.server=''     ## NB: these are single quotes
      uci set openvpn.myvpn.port=1194
      uci set openvpn.myvpn.ifconfig_pool_persist=/tmp/openvpn-ipp.txt
      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 bit (read :!: below before you execute this command):
      uci add_list openvpn.myvpn.push='redirect-gateway def1'   ## NB: these are single quotes
  4. Commit the configuration, enable and start the OpenVPN daemon:
      uci commit openvpn; /etc/init.d/openvpn enable

:!: If the OpenVPN Client and Server and on the same subnet, then you must add the local flag. Use instead: uci add_list openvpn.myvpn.push='redirect-gateway def1 local'

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

Testing & troubleshooting your configuration

  1. Ensure OpenVPN is not running, and confirm that there is no OpenVPN daemon and no TUN:
      /etc/init.d/openvpn stop
      sleep 3
      ps | grep openvpn
      ifconfig | grep tun0
  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
  3. If you need to troubleshoot, a good place to start is the log file:
      cat /tmp/openvpn.log

Part 2/2 - Configure and Start the OpenWRT-based client

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

  1. Clear the default OpenVPN configuration, and create a new openvpn configuration 'myvpn' (as for the server).
  2. To that, add the client-specific parameters (this is different):
      uci set openvpn.myvpn.client=1
      uci set openvpn.myvpn.resolv_retry=infinite
      uci set openvpn.myvpn.nobind=1
      uci set openvpn.myvpn.remote_cert_tls=server
  3. The client also has a tricky bit (read :!: below before you execute this command):
      uci set openvpn.myvpn.remote='$VPN_SERVER_PUBLIC_ADDRESS 1194'
  4. Commit the configuration, enable and start the OpenVPN daemon (as for a server).

You can troubleshoot as for a server.

Create a client configuration for Other OSs

In your favorite text editor on the client machine that will be connecting, paste (needs testing):

dev tun
proto udp
remote XXXXXXXX 1194
resolv-retry infinite
ca ca.crt
cert my-client.crt
key my-client.key

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

Save the file as client.ovpn


* 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.

* If unsure how various parameters are parsed to openvpn, you can find out PID with ps and then look up the parameters with tr '\0' ' ' < /proc/PID/cmdline (Replace PID with a number)

* 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)

FIXME: Please read vpn.overview and see this old articles on this matter: and help migrate them. There is also an article in the inbox: vpn.howto

Back to top

doc/howto/vpn.openvpn.txt · Last modified: 2014/03/09 09:29 by ptitgnu