Synology OpenVPN Setup

Configuring a secure OpenVPN implementation on Synology NAS devices

Prerequisites

Secure your Synology NAS before enabling internet access. Follow this document before proceeding.

You need to setup dynamic DNS in order to access your WAN IP from the public internet. Most people have DHCP from the ISP. As a result the WAN IP address may change from time to time. There are numerous free and paid dynamic DNS services available. Feel free to pick anything you desire. You can setup dynamic DNS on most home routers. You can also setup dynamic DNS on the Synology NAS as well.

You don't need your own domain to use OpenVPN. Nor do you need a Let's Encrypt certificate. It is best to create your own CA (Certificate Authority) and sign your own certificates. The setup of the root CA is described in detail below.

Setup port forwarding on your home router. The default port for OpenVPN is 1194/UDP. But you can choose any port and change the protocol as well. Every router has a different interface. Use https://portforward.com/ for instructions if needed. Do not buy there little tool. Port forwarding is quite simple to setup. It is recommended to setup a DHCP reservation or use a static IP address for your Synology NAS device. Setting up either option varies from device to device and is beyond the scope of this document.

Official Documentation

The user should always read the official documentation first. This document is based on the official documents plus a few other websites. The official documents will help explain in detail all of the various settings.

For the root CA (certificate authority) I mainly used the directions from the Feisty Duck SSL cookbook. I also borrowed from a few different websites. The openssl.cnf file has tons of options. And there are probably better ways to configure it. I previously created my own CA on my DD-WRT router. This setup is a bit better. And I suspect if I do this in the future I will learn a bit more then. The OpenVPN setup has also improved over my DD-WRT setup. I used a few websites to help setup OpenVPN.

  1. Deprecated OpenVPN Commands - Some of my options will be deprecated in the near future. But for now Synology is running version 2.3.x.
  2. Hardening OpenVPN - I took some of these suggestions.
  3. Another hardening guide
  4. A third hardening guide

High Level Overview

This is a very long document. But the steps are not hard. I found a new WordPress plugin that will allow for tabs. That will make long documents like this a lot more usable.

I created a script to help setup the root-ca and make it easier. And to make it more consistent. The script follows the high level procedures below. More information about the script can be found at the bottom of this document.

Transfer SYNO-OVPN.tar.gz to your NAS. This file has my script and a few configuration files. And it includes a nice little README file.

  1. Install the Synology OpenVPN package
  2. Configure the Synology OpenVPN package
  3. Test the Synology OpenVPN package before making any manual changes.

Now use the script or follow the manual directions to build your own root CA and to secure OpenVPN. Extract the files in /tmp or in /root. It will make a sub-directory name 'SYNO-OVPN'.

Now edit the files and update the variables for your environment. Use the included README for instructions on what to edit. Then run './syno-ovpn.ash build) to setup the basic directory structure and copy over a few configuration files.

  1. Setup the directory structure for the Root CA (./syno-ovpn.ash BUILD)
    1. Setup /etc/ssl/root-ca and sub-directories
    2. Copy the key files
  2. Switch to /etc/ssl/root-ca. Double check the configuration files and finish editing them if required. The script renamed some of the files when it copied them to the new directory.
    1. /etc/ssl/root-ca/openssl.conf
    2. /usr/syno/etc/packages/VPNCenter/openvpn/openvpn.conf
    3. /etc/ssl/root-ca/ovpn/openvpn.client.ovpn
    4. /etc/ssl/root-ca/syno-ovpn.ash (Script mentioned above)
  3. Setup the Root CA (./syno-ovpn.ash root-ca)
  4. Setup the Diffie Hellman file (./syno-ovpn.ash DH)
  5. Add Users (./syno-ovpn.ash -f john -l doe add)
    1. This will create the CSR and private key for the user
    2. Sign the CSR and create the public key for the user
    3. Setup an OVPN file for the user
  6. The script will also make it easier to revoke client certificates
    (./syno-ovpn.ash -f john -l doe revoke)
  7. Overwrite the Synology openvpn.conf server configuration file with our more secure configuration.
  8. Manually add the new SSL/TLS certificates to the Synology GUI for the OpenVPN package
    1. server.key (server private key)
    2. server.crt (server public key)
    3. ca.crt (Root CA public key)

Install the OpenVPN Package

Synology has a VPN Server package. It has 3 VPN protocols.

  • PPTP = Point to Point Tunneling Protocol (Do not use. There are known security vulnerabilities.)
  • L2TP/IPSec - Layer 2 Tunneling Protocol with IPSec (Internet Protocol Security) - L2TP doesn't encrypt. Encryption is done by IPSec. There may be security issues with IPSec.
  • OpenVPN - Recommended - Very configurable and it is open source.

Go to the package center and install 'VPN Server'. Once it is installed go to the main menu and select VPN Server. There are very few native configuration options within this package. Click on the 'OpenVPN' tab and fill in the information as desired.

  • Check 'Enable OpenVPN Server'
  • Dynamic IP address = Pick any /24 private subnet you desire. In this example I am using 10.1.1.0/24.
  • Maximum connection number = choose a number from the drop down box (5, 10, or 15)
  • Maximum number of connections with the same account - I changed this to '1' from the default value of '3'. By default the Synology OpenVPN uses ID and password. I plan to change this to certificate authentication for better security.
  • Port = 1194 (Default) - It is a good idea to change this to another port to reduce port scanning. Additional layers of security are always a good thing.
  • Protocol = UDP (Default) You can change this to TCP if you like. Some people use 443/TCP to help them connect through various firewalls. If possible use UDP.
  • Encryption = AES-256-CBC - Choose this or another encryption algorithm. NOTE: This cipher is being deprecated. Perhaps the next release of OpenVPN on Synology will have current ciphers.
  • Authentication = SHA512 - Do not use SHA1 anymore. SHA256 is probably more than enough. But I went for the highest HMAC.
  • Check "Enable compression on the VPN link"
  • [OPTIONAL] - Check "Allow clients to access server's LAN - Enable this if you want to SSH or RDP to other boxes on your home LAN.
  • [OPTIONAL] - Do not check - Enable IPv6 server mode. Most people are not using IPv6 at this time.
  • Click 'Apply'
OpenVPN Configuration Panel
OpenVPN Configuration Panel

Update the Synology Firewall

Based on the document 'Securing Synology NAS' mentioned above update your firewall to allow 1194/UDP. Or choose another port if desired.

Before changing anything else test out the basic configuration. Export your configuration from the OpenVPN GUI. Edit it with your dynamic DNS name. And install it on your phone or something else. Make sure everything works before proceeding.

Create Your Own CA

The default Synology OpenVPN setup uses ID and password for authentication. This is not recommended for several reasons. I am following the hardening guide from OpenVPN. At the time of this writing Synology is running OpenVPN v2.3.11 and OpenSSL v1.0.2n-fips. Two factor authentication is not an option with the Synology OpenVPN server at this time. It may be possible to compile the code yourself and update PAM.

NOTE: Once you manually update the configuration files you cannot hit 'apply' in the VPN Server configuration panel GUI. It will overwrite your settings. Make a backup of all your changes. It is possible that package updates may overwrite things as well.

Follow the steps below to configure your CA (Certificate Authority). The v1.0.2 MAN pages are here. And links to the main commands used are shown below with a brief explanation of each option.

GENRSA Man Page - genrsa - Generates an RSA private key.

CA Man Page - ca - This is a minimal CA application. It can be used to sign certificate requests (CSR) in a variety of forms and generate CRLs. It also maintains a text database of issued certificates and their status.

REQ Man Page - req - PKCS#10 certificate request and certificate generating utility. The req command primarily creates and processes certificate requests in PKCS#10 format. It can additionally create self signed certificates for use as a root CA.

X509 Man Page - x509 - A certificate display and signing utility. The x509 command is a multi purpose certificate utility. It can be used to display certificate information, convert certificates to various forms, sign certificate requests like a 'mini CA' or edit certificate trust settings.

Please note that in all of the commands below we must specify the updated openssl.conf file using the '-config' flag. We are not using the system default file.

1. Setup a New SSL Directory

Synology OpenSSL uses '/etc/ssl' as the default directory. (openssl version -d) I don't want to mess up any of the other items using SSL. So I will create a new openssl.conf file and directory structure for my CA. SSH to the Synology NAS and run the following commands as root or use sudo.

  • # Temporarily change the umask to ensure the newly created files and directories are secure
    • umask 0077
  • # Make a new directory for root-ca - /etc/ssl/root-ca
    • mkdir -m 0700 /etc/ssl/root-ca
  • # Change to that directory to lessen the amount of typeing
    • cd /etc/ssl/root-ca
  • # Make the sub-directories (certs - For PEM formatted certificates 'hash_of_name.pem' // db - For text based control files // private - For the private keys '*.key' // pub - For the public certificates '*.crt' // csr - For the certificate signing request '*.csr')
    • mkdir -m 0700 certs db private pub csr
  • # Optionally make a directory to hold the OpenVPN OVPN client configuration files for each user. Note, my script requires this directory.
    • mkdir -m 700 ovpn
  • # Each private key should be secured by a unique strong password. To help secure these files the directory is only available to 'root'.
    • chmod 0700 private
  • # Seed the '.rand' file. This file is used to help create entropy.
    • dd if=/dev/urandom of=/etc/ssl/root-ca/private/.rand bs=256 count=1
  • # For extra security we limit access to this file.
    • chmod 0600 /etc/ssl/root-ca/private/.rand
  • # Create the text based database file for openssl.
    • touch db/index
  • # Create a random unique string to start the count of each public key. Each public key gets the next number in the sequence.
    • openssl rand -hex 16 > db/serial
  • #The number with which to start a sequence of numbers to identify revoked certificates. Each one will get a unique number.
    • echo 1001 > db/crlnumber
  • # For security make sure everything is owned by root. On other systems it is best not to run this as root.
    • chown -R root:root /etc/ssl/root-ca

2. Create a New Openssl.conf (aka openssl.cnf)

Now we need to create a new openssl.conf file. The file should be owned by 'root:root' with permissions of 0600. Synology OpenSSL uses '/etc/ssl/openssl.cnf' as the configuration file. You can copy that file over, or use the file from the *.tar.gz file I provide. The script from the *.tar.gz file will copy over the initial file.

  • vi /etc/ssl/openvpn/openssl.conf

I am using the Feisty Duck site and PKI tutorials to help me configure the openssl.cnf file. I am not creating OCSP responders. Use the sample file below to create openssl.conf. Edit the lines in blue as desired.

# The [default] section contains global constants that
# can be referred to

# from the entire configuration file. It may also hold
# settings pertaining to # more than one openssl command.

# EDIT AS APPROPRIATE
# base_url = http://FQDN of your NAS
# Optional - update aia_url and crl_url
[ default ]

default_ca          = ca_default            # The default CA section
base_url            = http://your_nas.lab.example.com
aia_url             = $base_url/pub/ca.crt
crl_url             = $base_url/ca.crl
name_opt            = utf8,esc_ctrl,multiline,lname,align
prompt              = yes

# EDIT THIS AS APPROPRIATE
# Update countryName, stateOrProvince, localityName & organizationName
# Optional - update commonName
# CA Distinguished Name (DN) - called from req section

[ ca_dn ]
countryName          = "US"
stateOrProvinceName  = "IL"
localityName         = "Chicago"
organizationName     = "Lava VPN"

commonName           = "Root CA"

# The CA section defines the locations of CA assets, as
# well as the policies

# applying to the CA. Used by the 'openssl ca' command
[ ca_default ]
home                = /etc/ssl/root-ca     # Base directory
database            = $home/db/index       # dB index file
serial              = $home/db/serial      # Serial number file
crlnumber           = $home/db/crlnumber   # CRL number file
certificate         = $home/ca.crt         # CA public cert
private_key         = $home/private/ca.key # CA private key
RANDFILE            = $home/private/.rnd # Private random number file
new_certs_dir       = $home/certs       # Public certs directory
unique_subject      = no                # Require unique subject
copy_extensions     = none              # Copy extensions from the CSR
default_days        = 3650              # Certify for 10 years
default_crl_days    = 365               # How long until next CRL
crl_extensions      = crl_ext           # CRL extensions
default_md          = sha512            # Default signature algorithm
copy_extensions     = none              # Copy extensions from CSR

policy              = match_pol         # Default naming policy
x509_extensions     = client_ext        # Default signing extensions

# The next part of the configuration file is used by the
# openssl req command.
# It defines the CA's key pair, its DN, and the desired
# extensions for the CA 
certificate.
[ req ]
default_bits        = 2048        # RSA key size
encrypt_key         = yes         # Protect private key
default_md          = sha512      # MD to use
utf8                = yes         # Input is UTF-8
string_mask         = utf8only    # Emit UTF-8 strings
prompt              = no          # Don't prompt for DN
distinguished_name  = ca_dn       # DN section
x509req_extensions  = ca_reqext   # Extensions for CA self-signed

# Extensions for CA self-signed Cert ca.crt
[ ca_reqext ]

keyUsage                  = critical,keyCertSign,cRLSign
basicConstraints          = critical,CA:true,pathlen:0
extendedKeyUsage          = clientAuth,serverAuth
subjectKeyIdentifier      = hash
authorityKeyIdentifier    = keyid:always

# Naming policies control which parts of a DN end
# up in the certificate and

# under what circumstances certification should be denied.
[ match_pol ]
countryName           = match     # Must match cn_dn
stateOrProvinceName   = match     # Must match cn_dn
localityName          = match     # Must match cn_dn
organizationName      = match     # Must match cn_dn
commonName            = supplied  # Must be present

# Certificate extensions define what types of
# certificates the CA is able to
 create.
[ root_ca_ext ]
keyUsage                 = critical,keyCertSign,cRLSign
basicConstraints         = critical,CA:true,pathlen:0
subjectKeyIdentifier     = hash
authorityKeyIdentifier   = keyid:always

# CRL extensions exist solely to point to the CA
# certificate that has issued
 the CRL.
[ crl_ext ]
authorityKeyIdentifier    = keyid:always

# Extensions used to create server
[server_ext]
keyUsage                 = critical,digitalSignature,keyEncipherment
basicConstraints         = critical,CA:false
extendedKeyUsage         = clientAuth,serverAuth
authorityKeyIdentifier   = keyid:always
subjectKeyIdentifier     = hash

# Extensions used to create clients
[client_ext]
keyUsage                 = critical,digitalSignature
basicConstraints         = critical,CA:false
extendedKeyUsage         = clientAuth
authorityKeyIdentifier   = keyid:always
subjectKeyIdentifier     = hash
#
#EOF

3. Create the Diffie Hellman Parameters

I think you can use elliptic curve (EC) parameters instead of Diffie Hellman (DH) parameters. But I need to do some more research. I am using the 'dsaparam' flag to drastically reduce the amount of time it takes to create the file. I am using 2048 bits. Do not use 1024. And 4096 is overkill at this time.

  • cd /etc/ssl/openvpn
  • openssl dhparam -dsaparam -rand /dev/urandom -out dh2048.pem 2048

NOTE: This command will still take around 15 to 30 minutes to complete. Newer more powerful Synology NAS devices may require a bit less time.

4. Create the TLS Auth

Creating a TLS auth key helps to harden your VPN. It is a static pre-shared key (PSK) that must be generated in advance and shared among all peers.

  • cd /etc/ssl/openvpn
  • openvpn --genkey --secret private/ta.key

NOTE: This is not an OpenSSL command. It is an OpenVPN command.

On the OpenVPN server configuration file we must add the following line.

  • tls-auth /path/to/ta.key 0

On the clients we will be using inline files (concatenate all crt and key files into the OVPN file). The client configuration file needs the following line.

  • key-direction 1

5. Create the Root CA

The command below will generate a private key file (ca.key) and a public key file (ca.crt) for our new CA. When prompted, supply a secure password for the private key. Keep track of this password.

  • cd /etc/ssl/openvpn
  • openssl req \
    -config ./openssl.conf \
    -days 3650 \
    -x509 \
    -new \

    -keyout private/ca.key \
    -out pub/ca.crt

Check the private and public keys.

  • Private:  openssl rsa -in private/ca.key -check
  • Private:  openssl rsa -in private/ca.key -text -noout
  • Public:  openssl x509 -in pub/ca.crt -text -noout

Verify that the public key (ca.crt) has the correct distinguished name defined by openssl.conf. And verify that the x509v3 extensions list it as a CA.

We will also convert the CA crt to PEM format. This allows us to run 'openssl verify' commands against newly signed certificates.

  • openssl x509 \
    -in pub/ca.crt \
    -outform PEM \
    -out pub/ca.pem

6. Create the CRL (Revocation List)

Our default CRL days is 365. We need to create a new CRL every 365 days. Normally this is 30 days. But this is for a small personal OpenVPN instance. We want this as easy to manage as possible. Now create the CRL file before we create any other keys.

  • cd /etc/ssl/openvpn
  • openssl ca \
    -config ./openssl.conf \

    -gencrl \
    -extensions crl_ext \
    -out ca.crl

NOTE: You must recreate the file every time you revoke a client.

Read the contents with the following command.

  • openssl crl -in ca.crl -text -noout

Revoke a Certficate

The serial number of each CRT is stored in the database. (db/index) Grep for the name in the file and you can see the serial number. The serial number is shown in bold blue in the example below.

grep CN=john.doe db/index

V 280410224051Z 1BA302853C5C152075698774AC393A04 unknown /C=US/ST=IL/L=Chicago/O=Lava VPN/CN=john.doe

You must supply a reason for the revocation. Choose one of the following reasons.

  • unspecified
  • keyCompromise
  • CACompromise
  • affiliationChanged
  • superseded
  • cessationOfOperation
  • certificateHold
  • removeFromCRL

Use the command below to revoke a certificate. Update as appropriate. Make sure you create a new ca.crl file after each certification revocation.

  • openssl ca \
    -config ./openssl.conf \

    -revoke certs/1BA302853C5C152075698774AC393A04.pem \
    -crl_reason keyCompromise

7. Create the Server Key, CSR, & Crt

Now create the server private key (server.key) and CSR (server.csr). Adjust your '-subj' flags as required to match whatever you set in the 'openssl.cnf' file for the CA. When prompted enter a password for the private key (server.key). We need to remove the password for this key as Synology does not support authentication on the server key.

  • cd /etc/ssl/openvpn
  • openssl req \
    -config ./openssl.conf \
    -days 3650 \
    -new \

    -subj '/C=US/ST=IL/L=Chicago/O=Lava VPN/CN=server' \
    -extensions server_ext \
    -keyout private/server.key \
    -out csr/server.csr

Synology will not accept encrypted private keys. We must remove the password from the server private key. When prompted provide the password for the server private key.

  • openssl rsa -in private/server.key -out private/server.key

Now sign the CSR and generate the public key (server.crt). Remember you need to sign the CSR with the password for the CA private key (ca.key). Next we will verify that the public key has the correct information. Check to see the DN is correct and that the x509 extensions are correct. It should not be a CA and should point to the CA issuers public key (ca.crt).

  • cd /etc/ssl/openvpn
  • openssl ca \
    -config ./openssl.conf \
    -extensions server_ext \
    -days 3650 \

    -subj '/C=US/ST=IL/L=Chicago/O=Lava VPN/CN=server' \
    -in csr/server.csr \
    -out pub/server.crt
  • openssl x509 -in pub/server.crt -text -noout

8. Create the Client Key, CSR, & Crt

We will use the first and last name of the person for each client certificate. The first and last names will be separated by a '.' (period /aka dot). You can add a '-' (dash) or another '.' (period /aka dot) to either name to help with repeated names. For example you can use 'john.doe-jr' or 'john.doe.jr' as the name. Update the 'subj' flag with the correct DN. Make sure you use client extensions.

Just like the server setup we need to create a private key and a CSR. Then we need to sign the CSR and create the public key. Make sure you use the client extensions.

First create the CSR and private key. Make sure you create a new secure password for the private key and keep track of it.

  • cd /etc/ssl/openvpn
  • openssl req \
    -config ./openssl.cnf \
    -days 3650 \
    -new \

    -subj '/C=US/ST=IL/L=Chicago/O=Lava VPN/CN=john.doe' \
    -extensions client_ext \
    -keyout private/john.doe.key \
    -out csr/john.doe.csr

Now sign the CSR and create the public key. Remember you need to sign the CSR with the password for the CA private key (ca.key).

  • cd /etc/ssl/openvpn
  • openssl ca \
    -config ./openssl.cnf \
    -extensions client_ext \
    -days 3650 \

    -subj '/C=US/ST=IL/L=Chicago/O=Lava VPN/CN=john.doe' \
    -in csr/john.doe.csr \
    -out pub/john.doe.crt
  • openssl x509 -in pub/john.doe.crt -text -noout

Repeat these steps to add more clients.

Setup OpenVPN Server Configuration

OpenVPN provides a fully annotated sample openvpn server configuration file. They also provide a fully annotated sample client openvpn.ovpn file. To determine the default server configuration file run 'ps -aux | grep openvpn' on your NAS. The default location is shown below.

  • /usr/syno/etc/packages/VPNCenter/openvpn/openvpn.conf

The script mentioned in this document will copy the 'openvpn.conf' file copied below to "/etc/ssl/root-ca/ovpn/openvpn.conf.SERVER.SAMPLE". Edit this script as required. Then copy it over the default config shown above. Feel free to make additional changes. At a minimum you need to edit the push routes and the server VLAN. And you can also change the port if desired.

#
# OpenVPN Server Config
# Edit as appropriate
#

# Push routes to clients for local LAN subnet
# intranet - most home routers use 192.168.1.0/24
push "route 192.168.1.0 255.255.255.0"
# VPN network - choose whatever /24 you desire
push "route 10.2.192.0 255.255.255.0"

# Set Subnet mode
topology subnet

# VPN Server Subnet - OpenVPN uses x.x.x.1
server 10.2.192.0 255.255.255.0

# Do not allow split-tunneling
# Force ALL traffic through VPN
push "redirect-gateway def1"

# Listen on port (UDP or TCP) default 1194
port 1194

# Set Protocol - tcp or udp
proto udp

# Synology only supports TUN (L3)
# Set device tun/tap
dev tun0

# Keepalive n m = ping n ping-restart m
# ping every 10 seconds // restart after no ping in 60 sec
keepalive 10 60

# Renegotiate data channel key after N seconds (default=3600)
# 0 = disable
reneg-sec 0

# SSL/TLS certificates created by OpenSSL - root-ca
# ca = Root CA Self Signed Cert
# key = server running on Root CA private key
# cert = server running on Root CA public key
# dh = Diffie Hellman Parameters
# Syno default dir = /var/packages/VPNCenter/target/etc/openvpn/keys
ca /etc/ssl/root-ca/pub/ca.crt
key /etc/ssl/root-ca/private/server.key
cert /etc/ssl/root-ca/pub/server.crt
dh /etc/ssl/root-ca/dh2048.pem

# "HMAC FW" - helps block DoS attacks and UDP port flooding
# openvpn --genkey --secret ta.key
tls-auth /etc/ssl/root-ca/private/ta.key 0

# CRL Revocation List File Location
crl-verify /etc/ssl/root-ca/ca.crl

# Select a cryptographic cipher. (symmetric)
# Used by 'data channel'
# NOTE: OpenVPN 2.4 has newer ciphers GCM
# openvpn --show-ciphers
cipher AES-256-CBC

# Select Auth - auth alg
# openvpn --show-digests

# Authenticate packets with HMAC
auth SHA512

# For compression compatible with older clients use comp-lzo
# If you enable it here, you must also
# enable it in the client config file.
comp-lzo adaptive

# The maximum number of concurrently connected
# clients we want to allow.
max-clients 5

# 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

# Limit TLS v1.2
tls-version-min 1.2

# Limit TLS ciphers to those listed below
# Used by 'control channel'
# openvpn --show-tls
# EC and ECDSA tls ciphers only availble in 2.4 or higher
# tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA
# Using list below as this is v2.3.x
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256

# Limit scripting level
# 0 - no calling of external programs
# 1 (default) only call built-in executables - ifconfig, ip, netsh
# 2 allow calling of user defined scripts
# 3 allow passwords to be passed to scripts via environmental variables (unsafe)
script-security 2

# Ensure clients have EKU - extended key usage - set to client
# Clients must be set to use server
# remote-cert-eku "TLS Web Server Authentication"
remote-cert-eku "TLS Web Client Authentication"

# Output a short status file showing
# current connections, truncated
# and rewritten every N (30 sec)
status /tmp/ovpn_status_2_result 30

# Status version N - 1, 2 or 3
status-version 2

# 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

Setup OpenVPN Client Configuration

Edit the included sample client configuration to match your server configuration. Then for each new client change the name to easily identify each OVPN file. And concatenate the certificates in the proper order. First put CA certificate (ca.crt). Second add the new client public certificate. Third add the new client private key. And fourth add the TLS authentication file (ta.key).

The client configuration file will be identical with 3 exceptions.

  1. For Windows clients comment out the 'user nobody' and 'group nobody' lines.
  2. Each client will have their own unique client public key. (john.doe.crt)
  3. Each client will have their own unique client private key. (john.doe.key)

Edit the sample file below as appropriate. Make sure you add the certificates.

#
# OpenVPN Client Config
# Needs to match server config
# Edit as appropriate
#

# 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 tun0

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

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
# Should be dyn dns hostname
remote dyn.dns.name.for.nas 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)
# WINDOWS - COMMENT OUT USER AND GROUP NOBODY
; user nobody
; group nobody

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

# Verify server certificate by checking that the
# certicate has the correct key usage set.
# This is an important precaution to protect against
# a potential attack discussed here:
# http://openvpn.net/howto.html#mitm
remote-cert-tls server

# If a tls-auth key is used on the server
# then every client must also have the key.
key-direction 1

# Allow remote peer to change IP (DHCP)
# Accept authenticated packets from any address
# not just address specified by 'remote' option
float

# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
# Note that v2.4 client/server will automatically
# negotiate AES-256-GCM in TLS mode.
# See also the ncp-cipher option in the manpage
cipher AES-256-CBC

# Select HMAC Authentication
# server/client must match
auth SHA512

# Verify EKU - Extended Key Usage is set to server on remote box
remote-cert-eku "TLS Web Server Authentication"

# Set TLS to min of 1.2
tls-version-min 1.2

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

# Set log file verbosity.
verb 0

# To simplify OVPN client setup concatenate
# all certificates here in proper order
# 1 <ca> </ca> 2 <cert> </cert>
# 3 <key> </key> 4 <tls-auth> </tls-auth>
# ADD CERTS BELOW HERE

Concatenate the Client OVPN

The script will create our client OVPN file. If you do this manually you need to concatenate all of the files into the client OVPN file.

  • Add the user to the root CA using the commands above.
  • Copy the sample OVPN file and create a client OVPN file. (john.doe.ovpn)
  • Add the ca.crt file, client crt file, client key file, and ta.key. Each file must be enclosed with the identifiers shown below.

<ca>
cat ca.crt here
</ca>
<cert>
cat john.doe.crt here
</cert>
<key>
cat john.doe.key here
</key>
<tls-auth>
cat ta.key here
</tls-auth>

Overwrite the Synology openvpn.conf File

Copy are new OpenVPN server configuration file  and overwrite the default Synology openvpn.conf file. Our new file is shown below.

  • /etc/ssl/root-ca/ovpn/openvpn.conf.SERVER

The default file is shown below.

  • /usr/syno/etc/packages/VPNCenter/openvpn/openvpn.conf

Add Our Server Keys to the GUI

By default Synology uses the self-signed synology certificate for everything. We need to add a new certificate to the DSM GUI and then configure OpenVPN to use that new certificate. It has to be a chained certificate and include our new server.key (private key), the server.crt (public key), and the new root CA public certificate (ca.crt).

I tar these three files up before I transfer them.

  • /etc/ssl/root-ca/pub/ca.crt (Root CA public certificate)
  • /etc/ssl/root-ca/pub/server.crt (OpenVPN server public certificate)
  • /etc/ssl/root-ca/private/server.key (OpenVPN server private certificate)

Extract the files somewhere on your computer. Then launch the DSM GUI. (https://your_nas:5001)

  • Next launch the 'Control Panel'.
  • Navigate to 'Security' and then open the 'Certificate Tab'.
  • Click 'Add'
    • Choose 'Add a new certificate' and click 'Next'
    • Choose 'Import certificate'. Optionally add a description. Click 'Next'.
    • Now import the server.key, server.crt, and ca.crt. See the picture below.
      Import Certificate Files Screen
      Import Certificate Files Screen

      Click OK to import the certificate. Then highlight your new certificate and click 'Configure'. Select 'server' (or what you used for a description) in the drop down box next to 'VPN Server'. And then click OK.

      Select 'server' Certificate
      Select 'server' Certificate

       

Restart OpenVPN

Restart OpenVPN so that it loads the new configuration. You may do this from the GUI or from the command line.

In the GUI open 'Package Center' and then scroll to 'VPN Server'. Open that and use the drop down box labeled 'Action' and select 'Stop'. Use the same box to start the VPN server again.

From a command line run the following command.

  • synoservice --restart pkgctl-VPNCenter
  • Or: /var/packages/VPNCenter/scripts/start-stop-status {stop start}

To check out your server configuration you may run the following.

  • cd /usr/syno/etc/packages/VPNCenter/openvpn
  • openvpn --config ./openvpn.conf

Using the Script

Setting everything up manually isn't that difficult. And it is very useful to help learn about SSL and OpenVPN. But adding or revoking users can be a pain if you have to remember the correct syntax. I created a script to help build the root CA. And it will add and revoke users as well. I mentioned the script above. It is included in 'SYNO-OVPN.tar.gz'. The README file shows you how to use the script. And it explains how to edit the included sample files.  Enjoy.

DD-WRT OpenVPN 101

DEPRECATED

This document is a bit old. It still works. But I created a new setup on my Synology NAS. And it is a better setup. I now better understand openssl and how to configure it. There are a few things I would probably change in this document. Plus as nice as DD-WRT may be, it is open source and free. Those nice folks do not have the same resources as Synology. My DD-WRT OpenSSL package is a bit out of date and so is my OpenVPN package. Synology isn't the latest and greatest either. But it is more current. And it is more likely to be updated before DD-WRT.

Please use my Synology OpenVPN setup guide.

Read the Docs

The official DD-WRT documentation (and this doc) is very good.  And the official OpenVPN documentation covers a lot more detail.  Also refer to the Wikipedia article on X.509.  This document just covers the steps I needed to perform and does not add a lot of explanation.

Backup DD-WRT

Backup your DD-WRT configuration before you start changing anything.

Routing (tun) vs Bridging (tap)

Routing or tunneling encapsulates the data over OSI L3.  I am using this method.  One reason is that the iPhone does not support bridging.  With routing you need to create a new private subnet for the VPN server.

Bridging encapsulates the data over OSI L2.  You are extending your local LAN subnet across the VPN.  The default DD-WRT subnet is 192.168.1.0/24.  You create a TAP interface on the server and the client.  As stated above this is not supported on Apple IOS devices.  And from what I have read it can be rather difficult to setup on Windows as well.

File Formats

This is provided as a reminder to myself.  With OpenSSL you can convert from almost any format to another.  This information is from Wikipedia, ssl.com, openssl.org,  and a few other sources.

  • *.pem - (Privacy-enhanced Electronic Mail) Base64 encoded DER certificate, enclosed between "----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----".  Certificate container format that may include just the public certificate, or the entire certificate chain including the public key, private key, and root certificates.  
    • Base64 (ASCII) Encoding - Group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation.
    • DER Encoding (Binary) - DER is a restricted variant of BER for producing unequivocal transfer syntax for data structures described by ASN.1.
      • X.690 is an ITU-T standard specifying several ASN.1 encoding formats:
      • Basic Encoding Rules (BER)
      • Canonical Encoding Rules (CER)
      • Distinguished Encoding Rules (DER)
  • *.cer, *.crt - X.509 certificate (Base64 (ASCII) or DER (binary) encoded) - PEM formatted file with a different extension.  Recognized by Windows explorer as a certificate.
    • *.der - (DEPRECATED) - Binary DER encoded certificates.  These may also use the "*.cer" or "*.crt" extensions.
  • *.key - This is the PEM formatted file containing just the private key.
  • *.p7b *p7c, *.spc - PKCS#7 SignedData structure without data, just certificate(s) or CRL(s).  (Certificate Revocation List)
  • *.crl - Certificate Revocation List
  • *.csr - Certificate Signing Request - Submit this to the CA.  Contains some or all of the key details (subject, organization, state, OU, CN, etc) and the public key.
  • *.stl, *.ctl - Certificate Trust List (MS IIS)
  • *.sst - Microsoft Serialized Certificate Store
  • *.p12 - PKCS#12 - May contain certificate(s) public and private keys.  This is password protected.  
  • *.pfx - PFX, predecessor of PKCS#12.  Usually contains data in PKCS#12 formate with PFX files generated in IIS.)

The Environment

I am using a non-standard port.  My Aunt has a Xfinity wireless router.  The firewall on that isn't very good.  I have setup maximum security on it but it doesn't allow for exceptions or specific rules.  But it does allow 500/UDP GRE (Generic Routing Encapsulation) VPNs.  So I will use that port for my OpenVPN configuration.  My main laptop runs Windows.  I will be using the Windows setup steps.  I will be creating client files for my iPhone, Android tablet, Nexus tablet, and my Windows laptop.  At the time of this writing I installed version 2.3.11 (64 bit) for Windows Vista and later.  These directions assume you have already setup Dynamic DNS for your router's public IP address or you have a static IP address.

Easy-RSA Certification Creation

From an Administrator command prompt switch to the easy-rsa directory.

  • C:\Program Files\OpenVPN\easy-rsa

Perform the following steps.  I have VIM and GOW installed on my Windows box.

  • init-config <ENTER>  (This will copy the vars.bat.sample to vars.bat.)
  • vim vars.bat  (Edit the following lines as appropriate.)

set KEY_COUNTRY=US
set KEY_PROVINCE=IL
set KEY_CITY=Chicago
set KEY_ORG=OpenVPN
set KEY_EMAIL=zaphod@example.com
set KEY_CN=OpenVPN-CA
set KEY_NAME=Zaphods Widgits
set KEY_OU=Zaphods
set PKCS11_MODULE_PATH=changeme (Ignore)
set PKCS11_PIN=1234  (Ignore)

  • vars <ENTER>  (This will source the environmental variables.)
  • clean-all <ENTER>  (Deletes anything in .\keys\* and recreates the index.txt and serial files in .\keys.)
  • build-ca <ENTER>  (Builds the Certificate Authority (CA) certificate (.\keys\ca.crt) and key (.\keys\ca.key).  This allows us to sign our certificates.)

WARNING: can't open config file: /etc/ssl/openssl.cnf
Loading 'screen' into random state - done
Generating a 1024 bit RSA private key
..............++++++
...++++++
writing new private key to 'keys\ca.key'
-----
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [IL]:
Locality Name (eg, city) [Chicago]:
Organization Name (eg, company) [OpenVPN]:
Organizational Unit Name (eg, section) [Zaphods]:
Common Name (eg, your name or your server's hostname) [OpenVPN-CA]:
Name [Zaphods Widgits]:
Email Address [zaphod@example.com]:

  • vars <ENTER> (re-source variables)
  • build-key-server server <ENTER>  (You can use any name, but using 'server' is easier.  This creates the server crt and key and csr.  You MUST USE 'server' as the CN in the example below.  Edited to highlight the important bits.)

Country Name (2 letter code) [US]:
State or Province Name (full name) [IL]:
Locality Name (eg, city) [Chicago]:
Organization Name (eg, company) [OpenVPN]:
Organizational Unit Name (eg, section) [Zaphods]:
Common Name (eg, your name or your server's hostname) [OpenVPN-CA]:server
Name [Zaphods Widgits]:
Email Address [zaphod@example.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:******* (Optional - used by revocation)
An optional company name []:
WARNING: can't open config file: /etc/ssl/openssl.cnf
Using configuration from openssl-1.0.0.cnf
Loading 'screen' into random state - done
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'IL'
localityName :PRINTABLE:'Chicago'
organizationName :PRINTABLE:'OpenVPN'
organizationalUnitName:PRINTABLE:'Zaphods'
commonName :PRINTABLE:'server'
name :PRINTABLE:'Zaphods Widgits'
emailAddress :IA5STRING:'zaphod@example.com'
Certificate is to be certified until Jul 8 21:06:12 2026 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

C:\Program Files\OpenVPN\easy-rsa>

Create the Client Keys

You can use the same client key and crt files on every client.  But it is more secure to use unique keys.  This allows for client revocation.  You should use unique identifiable names for each client.  You MUST use the client name for the CN name during the file creation process.  You can come back to this section and create more client keys at any time.  This will create three files in the keys directory.  (*.crt, *.key, *.csr)

  • vars <ENTER>
  • build-key iphone <ENTER>  (Replace iphone with a unique name for each client.  Use the same name in commands below for the CN.)

Country Name (2 letter code) [US]:
State or Province Name (full name) [IL]:
Locality Name (eg, city) [Chicago]:
Organization Name (eg, company) [OpenVPN]:
Organizational Unit Name (eg, section) [Zaphods]:
Common Name (eg, your name or your server's hostname) [OpenVPN-CA]:iphone
Name [Zaphods Widgits]:
Email Address [zaphod@example.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:******* (Optional)
An optional company name []:
WARNING: can't open config file: /etc/ssl/openssl.cnf
Using configuration from openssl-1.0.0.cnf
Loading 'screen' into random state - done
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'IL'
localityName :PRINTABLE:'Chicago'
organizationName :PRINTABLE:'OpenVPN'
organizationalUnitName:PRINTABLE:'Zaphods'
commonName :PRINTABLE:'iphone'
name :PRINTABLE:'Zaphods Widgits'
emailAddress :IA5STRING:'zaphod@pahoehoe.net'
Certificate is to be certified until Jul 8 22:36:47 2026 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

C:\Program Files\OpenVPN\easy-rsa>

Repeat as necessary for each client.

Create the Diffie Hellman Parameters

If this was a Linux server I would use a 2048 bit key.  This step will create the 'dh1024.pem' file.  To change this to 2048 bits edit 'vars.bat' and change the 'KEY_SIZE' variable from 1024 to 2048.  This will also change the output file from 'dh1024.pem' to 'dh2048.pem'.

  • vars <ENTER>
  • build-dh <ENTER>

Create the TLS Authentication File

This isn't part of the easy-rsa setup.  But while we are creating all of our files on our Windows box we may as well create this file as well.  I am copying this to the keys directory just to keep all of the files together.

  • cd ..\bin
  • openvpn.exe --genkey --secret ta.key
    • --genkey:  Generate a random key to be used as a shared secret, for use with the --secret option.
    • --secret file:  Write the key to a file.
  • move ta.key ..\easy-rsa\keys\ta.key
    • server config = tls-auth ta.key 0
    • client config = tls-auth ta.key 1
    • iphone = key-directive 1 (comment out tls-auth)

List of Files

All of these files are in the keys directory.  This is just the relevant files.  The "*.csr" files are not required anymore.

Filename Needed By Purpose Secret
ca.crt server & all clients Root CA Certificate No
ca.key Key Signing Machine Only Root CA Key Yes
dh{n}.pem server only DH Parameters No
server.crt server only Server Certificate No
server.key server only Server Key Yes
iphone.crt client 1 only (iphone) Client 1 Certificate No
iphone.key client 1 only (iphone) Client 1 Key Yes
ta.key server & all clients OpenVPN TLS Auth Yes

Setup the DD-WRT Gateway

Log into the DD-WRT web GUI.  Go to 'Services // VPN' and enable the 'OpenVPN Server/Daemon'.  I am using the WAN UP start type and configuring this as a daemon.  Copy the files we created via easy-rsa to the server.  Simply copy and paste the Base64 encoded sections of each file.  See the example below.  Most of the file has been replaced by '........'.

-----BEGIN CERTIFICATE-----  (Start Copy & Paste Here)
MIID1DCCAz2gAwIBAgIJAKs5r3xYQISKMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYD
........
G0t7SngHbrooGimTgkuAALqvwTIO3mLOk52f10rQC5OoG6s5pClP1eNsWnr+Kxs3
mLvuSsTEx7Kts0R9ed8rBje4EB0PRhpT
-----END CERTIFICATE-----  (End Copy & Paste Here)

Box Name File to Insert
CA Cert ca.crt
Public Server Cert server.crt
Private Server Key server.key
DH PEM dh1024.pem
Additional Config See Server Config Below
TLS Auth Key ta.key
Certificate Revoke List crl.pem (If exists to revoke client X)

At this time the 'clr.pem' file does not exist.  If we revoke a client in the future we can add the 'crl.pem' file.

  • vars <ENTER>
  • revoke-full clientX <ENTER>  (Where clientX is the name of one of the clients.)

Server Config

OpenVPN includes a fully annotated sample configuration file.  I am configuring the server using the 'additional config' box.  This replicates how an OpenVPN server would be setup on a Linux box.  The results are the same using the web GUI or the command line.  See the config by running 'nvram get openvpn_config' from the DD-WRT command line.

Many sites recommend using 'push "dhcp-options DNS x.x.x.x"'.  I am not using that setting.  If I use that option I cannot get DNS working.  I suspect I have some strange setting in my DHCP setup.

I am using the 'push "redirect-gateway def1"' on the server.  This forces all traffic over the VPN.  You can use this option on the client side by removing the 'push' part.  Feel free to test this option using 'tcpdump -nl -i tun0' on your DD-WRT router.  Or by simply heading to 'ipchicken.com' or 'whatismyip.com'.

  • C:\Program Files\OpenVPN\sample-config\server.ovpn

There are two networks that connect over the internet (WAN).

  • Local LAN = 192.168.1.0/24 (DD-WRT Default - Update with your subnet)
  • OpenVPN Private Routing = 10.2.192.0/24 (Use whatever you like)

# Push route to clients for local LAN subnet
push "route 192.168.1.0 255.255.255.0"
# Set subnet mode (net30, p2p, subnet)
topology subnet

# VPN Server Subnet - OpenVPN uses x.x.x.1
# Clients use the remaining IPs
server 10.2.192.0 255.255.255.0

# Listen on non-standard port (default 1194)
port 500
# Set protocol tcp or udp
proto udp
# Set device (tunX|tapX|null) server/client identical
# tun - L3 // tap - L2
dev tun0
# keepalive n m = ping n ping-restart x
# ping every 10 sec // restart after no ping in 120 sec
keepalive 10 120
# path to certs and keys - hard coded dd-wrt paths
dh /tmp/openvpn/dh.pem
ca /tmp/openvpn/ca.crt
cert /tmp/openvpn/cert.pem
key /tmp/openvpn/key.pem
# Additional layer HMAC auth on top of TLS control

# channel to protect against DoS attacks
# server must be  0 // client 1
tls-auth /tmp/openvpn/ta.key 0
# Compression mode (yes|no|adaptive (default) )
comp-lzo adaptive
# Allow multiple clients with same CN to connect concurrently
# duplicate-cn
# Route all traffic over VPN - NOT split tunnel
# 1. create static route for remote address which forwards
#    to pre-existing default gateway
# 2. delete the default gateway route
# 3. Set new def gateway to be the VPN endpoint address
# local - both openvpn servers connected via common subnet (wireless)
#         causes step 1 to be omitted
# def1 - override def gateway (0.0.0.0/1,128.0.0.0/1) does not wipe
#        out original def gateway
push "redirect-gateway def1"

# Encrypt data channel packets
# cipher alg - server/client must match
# defaults to BF-CBC 128 bit
# openvpn --show-ciphers (to list ciphers)
cipher AES-256-CBC
# Authenticate packets with HMAC (message digest algorithm)
# auth alg - server/client must match
# defaults to sha1
# openvpn --show-digests (to list digests)
auth sha1

# Logging verbosity (services/services/syslogd)
# 0 silent except fatal
# 4 reasonable for general usage
# 5, 6 - debug
# 9 - extremely verbose
verb 0

# Only use crl-verify if you have revoke list
# crl-verify /tmp/openvpn/ca.crl

# Management parameter - DD-WRT can 
# access server's management port
management localhost 5001

Copy and paste the above into the 'additional config' box.  Edit as desired.  Now save and apply the settings.

DD-WRT Firewall Settings

Now we must allow the VPN traffic through the DD-WRT firewall.  Go to "Administrative // Commands".  Edit the rules below as required for your environment.  To help identify the correct interface run 'netstat -rn' from the DD-WRT command line or from the web GUI.  An edited example is shown below.  The public interface uses vlan2.  DD-WRT creates br0 for the internal networks.  And OpenVPN created tun0.

# netstat -rn (Removed Flags MSS Window and irtt)
Kernel IP routing table
Destination     Gateway       Genmask       Iface
0.0.0.0         001.002.003.1 0.0.0.0       vlan2  (Public Gateway)
10.2.192.0      0.0.0.0       255.255.255.0 tun0  (OpenVPN)
001.002.003.0   0.0.0.0       255.255.254.0 vlan2
127.0.0.0       0.0.0.0       255.0.0.0     lo
169.254.0.0     0.0.0.0       255.255.0.0   br0
192.168.1.0     0.0.0.0       255.255.255.0 br0 (DD-WRT Internal Bridged Networks)

Edit the lines below before adding them to the web GUI.  Cut and paste them into the 'Commands' box.  Then click 'Save Firewall'.  You will lose connectivity as the firewall rules are processed.  Edit the bold blue items as required.

  • udp - Change to tcp if required
  • 500 - Default port is 1194.  Edit as required
  • 10.2.192.0/24 - This is the VPN server subnet previously created.  Edit as appropriate.
  • br0 - Default DD-WRT internal bridge
  • tun0 - The newly created OpenVPN tunnel interface
  • vlan2 - The public interface for the DD-WRT router (netstat -rn)
  • # Accept incoming connections on port 500/UDP
    iptables -I INPUT 1 -p udp --dport 500 -j ACCEPT
    # Forward packets from VPN subnet 10.2.192.0/24

    iptables -I FORWARD 1 --source 10.2.192.0/24 -j ACCEPT
    # Forward packets inbound bridge outbound via tunnel

    iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
    # Forward packets inbound tunnel outbound via bridge

    iptables -I FORWARD -i tun0 -o br0 -j ACCEPT
    # SNAT 10.2.192.0/24 outbound packets as VLAN2 IP (public ip)

    iptables -t nat -A POSTROUTING -s 10.2.192.0/24 -o vlan2 -j MASQUERADE

To see the rules run 'iptables -nvL' and 'iptables -t nat -nvL'.

Client Config

You can edit the sample configuration file.  It is nicely annotated.

  • C:\Program Files\OpenVPN\sample-config\client.ovpn

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

# Specify virtual network device tunX|tapX|null
# X may be omitted for dynamic device
# Both ends must match settings
# tun - encapsulate IPv4-6 OSI L3
# tap - encapsulate IPv4-6 Ethernet 802.3 OSI L2
dev tun0

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

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote DD-WRT-PUBLIC.dyndns.com 500

# 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

# Offers policy-level control over usage of external
# programs and scripts
# 0 -- strictly no calling of external programs
# 1 -- DEFAULT - Only call built-in exec - ifconfig, ip, route
# 2 -- All calling of built-in exec and user-defined scripts
# 3 -- Allow passwords to be passed to scripts via env variables
# script-security <level>

# SSL/TLS parms.
# See the server config file for more
# description.
# Using inline files - comment out here

# ca ca.crt
# cert client.crt
# key client.key
# tls-auth ta.key 1

# Verify server certificate by checking that the
# certicate has the correct key usage set.
# This is an important precaution to protect against
# a potential attack discussed here:
# http://openvpn.net/howto.html#mitm
#
# To use this feature, you will need to generate
# your server certificates with the keyUsage set to
# digitalSignature, keyEncipherment
# and the extendedKeyUsage to
# serverAuth
# EasyRSA can do this for you.
remote-cert-tls server

# If a tls-auth key is used on the server
# then every client must also have the key.
# tls-auth ta.key 1
# For inline files use key-direction not tls-auth
key-direction 1

# Allow remote peer to change IP (DHCP)
# Accept authenticated packets from any address
# not just address specified by 'remote' option
float

# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
cipher AES-256-CBC

# Select HMAC Authentication
# server/client must match - default sha1
auth sha1

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

# Set log file verbosity.
verb 0

# Redirect all traffic over vpn
# Optional - I am setting on server side via push

# redirect-gateway def1

Read the next section to add all of the TLS files to the OVPN configuration file.  This makes management of the files much easier.

Concatenate Key Files into OVPN

Instead of providing the clients with the "*.ovpn" file and the key files you can combine everything into the OVPN file.  At the bottom of the OVPN file add the following.

Here is a list of the files you will need to add.

File Description File to Insert Enclosed By
Root CA Certificate ca.crt (The same file on all clients) <ca> </ca>
Client Certificate iphone.crt (Replace iphone as required) Unique per client <crt> </crt>
Client Private Key iphone.key (Replace iphone as required) Unique per client <key> </key>
TLS Auth Key ta.key (The same file on all clients) <tls-auth> </tls-auth>

# Root Certificate Authority ca.crt
<ca>
-----BEGIN CERTIFICATE-----
MIID1DCCAz2gAwIBAgIJAKs5r3xYQISK
................
mLvuSsTEx7Kts0R9ed8rBje4EB0PRhpT
-----END CERTIFICATE-----
</ca>
# client cert iphone.crt
<cert>
-----BEGIN CERTIFICATE-----
MIIEFjCCA3+gAwIBAgIBAjANBgkqhkiG9
................
6PSxUlAeZkPnVpj8BZ3HpERWZvy7Ljw79Z36
-----END CERTIFICATE-----
</cert>

# client private key iphone.key
<key>
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEF
...................................
FDAQQyE4WV4GJ113Dtfagw==
-----END PRIVATE KEY-----
</key>
# tls auth ta.key
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
64b7b9b8b1b25825fa006aabe829b379
...............................
d200a5f90563facf2f5a374564904e15
-----END OpenVPN Static key V1-----
</tls-auth>

Verify Your Connection

Before you use this in the wild you need to verify that your VPN tunnel is operating correctly.  Here are a few commands to verify that all traffic is routing over the VPN.

From the DD-WRT command line run a few tcpdump commands.

  • tcpdump -nl -i tun0
  • tcpdump -nl -i tun0 port 53
  • To verify ipchicken.com
    • tcpdump -nl -i tun0 host 104.25.63.114 && host 104.25.64.114
  • To verify whatismyip.com
    • tcpdump -nl -i tun0 host 104.27.201.91 && host 104.27.202.91

Obviously use your browser and go to 'whatismyip.com' and 'ipchicken.com' before and after you establish your VPN tunnel.  Make sure your IP is now your ISP public IP address.

A Note on Windows

You must run the OpenVPN client as an Administrator.  And you must comment out the 'user nobody' and 'group nobody' lines in the client OVPN file.