Setup 4096-bit OpenVPN on OpenWRT

If you want to setup OpenVPN with 4096-bit key on OpenWRT, with a few tips and tricks in addition, read on.

Reasons for setting up VPN

  1. To access your home network via a secure tunnel from outside.
  2. To avoid port forwardings which opens up a direct pipe to your home devices, a potential security hole.
  3. To deny others from eavesdropping on your Internet traffic when using public Wi-Fi.
  4. To browse the Internet as if you are in your home country when you are abroad. This is useful in circumventing geo-blocking.

OpenVPN is probably the best open source implementation of VPN at this time. It is offered by all public VPN providers that I know of but encryption strength varies.

Setup

Default settings

Prior to using OpenVPN on OpenWRT, I was using OpenVPN on Network-attached Storage. I stopped using after realising that they use 1024-bit key. Then I setup OpenVPN on OpenWRT which as at time of writing this blog post defaults to 2048-bit key. While this is sufficient for today’s needs, an attacker could potentially capture the encrypted data today to be decrypted using much better hardware in future.

Installing OpenVPN on OpenWRT

Install openvpn-easy-rsa and openvpn-openssl. If you use OpenWRT GUI, install luci-app-openvpn as well. Ensure that your router has sufficient free space for these packages! I am unsure how much is required but very sure that routers with 4MB flash memory is insufficient.

Increasing key size from 2048 to 4096 bit

Edit /etc/easy-rsa/vars using your preferred editor. If you are not sure how to edit, I recommend installing nano then edit the file by typing nao /etc/easy-rsa/vars.
Set export KEY_SIZE=4096.

Other settings

You should set the following fields so that you do not have to enter them for each key creation.

export KEY_COUNTRY="[2-letter country code]"
export KEY_PROVINCE="[whatever]"
export KEY_CITY="[whatever]"
export KEY_ORG="[whatever]"
export KEY_EMAIL="[whatever]"
export KEY_OU="[whatever]"

export KEY_NAME="[keyname]"

Password keys

For all steps below, when prompted to enter password for keys, leave them blank.

Clean all

To delete everything in /etc/easy-rsa/keys folder, run clean-all. Be warned that this removes all existing keys! Use it only for starting afresh.

Generate Certificate Authority key

Create Certificate Authority (CA) key by running build-ca. This step produces ca.crt and ca.key. The former (certificate) is to be distributed to every client while the latter (key) must not be given out to anyone. If the key is compromised, you must recreate all keys beginning with clean-all step in previous paragraph.

Generate Diffie Hellman key

Create Diffie Hellman (DH) key by running build-dh. Note that this takes hours if not days on a typical router! If you want this step to complete significantly faster, install OpenSSL onto your workstation and execute:

openssl dhparam 4096 -out dh4096.pem

Be patient. A modern hardware may still require more than an hour to complete this step. The output is a file dh4096.pem. Copy this into /etc/easy-rsa/keys.

Generate server key

build-key-server server

This creates a server key called ‘server’.

Generate client keys

For each client, create a key with unique name. Besides this, do not create client keys with the same name as server key.

build-key-pkcs12 clientname

This generates the following files:

  • clientname.crt
  • clientname.key
  • clientname.p12

Hardening security

While not required, enabling Transport Layer Security (TLS) authentication is strongly recommended. Generate TLS key by running:

openvpn --genkey --secret /etc/easy-rsa/keys/ta.key

This key is a shared secret. Therefore, must be copied to every client. If the server is set to ta.key 0, the client must be set to ta.key 1 or vice versa.

Copy all keys to openvpn folder

cd /etc/easy-rsa/keys
cp ca.crt ca.key dh4096.pem server.crt server.key ta.key /etc/openvpn

For subsequent configuration steps, point to /etc/openvpn for keys.

Server configuration

Edit /etc/config/openvpn. Add and edit where relevant the following:

# OpenVPN instance name must be unique
config openvpn 'myvpn'
    option enabled '1'
    option mode 'server'
    option tls_server '1'

    # Virtual network adapter name, must be unique
    option dev 'tun-local'

    # The default port number is 1194
    option port '1194'
    option proto 'udp'

    option status '/var/log/openvpn_status.log'
    option log '/tmp/openvpn.log'
    option mute '5'
    option persist_key '1'
    option persist_tun '1'
    option ca '/etc/openvpn/ca.crt'
    option cert '/etc/openvpn/server.crt'
    option key '/etc/openvpn/server.key'
    option dh '/etc/openvpn/dh4096.pem'

    # Instead of using the default Blowfish algorithm
    option cipher 'AES-256-CBC'

    # Set ta.key 0 for server and ta.key 1 on client or vice versa
    option tls_auth '/etc/openvpn/ta.key 0'

    option route_gateway 'dhcp'

    # Allows a VPN client to talk to another
    option client_to_client '1'

    # IMHO, compression should be decided at application layer
    option comp_lzo 'no'

    # Use a subnet where no other instance of OpenVPN is using
    option server '10.8.1.0 255.255.255.0'
    option verb '0'
    option float '1'
    option keepalive '10 120'

    # Do not comment this line
    list push 'comp-lzo no'

    # Redirects all client traffic to go through VPN
    list push 'redirect-gateway def1'

    # Tell client to use router's DNS forwarder, change this accordingly
    # You must configure firewall to allow this to flow through
    # Otherwise use Google DNS 8.8.8.8
    list push 'dhcp-option DNS 192.168.0.1'

Restart Openvpn:

/etc/init.d/openvpn restart

Edit /etc/config/network and add the following. Note that tun-local must be replaced with whatever you have specified under option dev in previous step:

config interface 'vpn'
    option proto 'none'
    option auto '1'
    option ifname 'tun-local'

Restart network:

/etc/init.d/network restart

Next, setup firewall by editing /etc/config/firewall. Create a firewall zone for the VPN:

config zone
    option name 'vpn'
    option input 'ACCEPT'
    option forward 'ACCEPT'
    option output 'ACCEPT'
    option masq '1'
    option network 'vpn'

Forward traffic from VPN to WAN:

config forwarding
    option dest 'wan'
    option src 'vpn'

Forward traffic from VPN to LAN:

config forwarding
    option dest 'lan'
    option src 'vpn'

Allow incoming connections via UDP port 1194:

config rule
    option name 'Allow-OpenVPN-Inbound'
    option target 'ACCEPT'
    option proto 'udp'
    option dest_port '1194'
    option src 'wan'
    option family 'ipv4'

Restart firewall: /etc/init.d/firewall restart

Client configuration

Create clientname.ovpn file:

dev tun

# Protocol to use
proto udp

# Certificates
ca   ca.crt
cert clientname.crt
key  clientname.key

script-security 3
float
cipher AES-256-CBC
tls-auth ta.key 1
client
remote-cert-tls server

# Try the first, if fail try the second automatically
# Replace server-hostname with your hostname
remote server-hostname 1194
remote server-hostname 53

Copy the OVPN file along with the following files to the client:

  • clientname.crt
  • clientname.key
  • ca.crt
  • ta.key

Import the OVPN file using your preferred OpenVPN client. The client should automatically recognise the other four files. If not, explicitly point to them.

Troubleshooting

Read on if you are facing issues. One of the solutions might be helpful to you.

Able to establish connection over mobile network but not from public Wi-Fi

The firewall at the public Wi-Fi network is probably blocking outgoing connections on UDP port 1194. Try using a different port instead of the default 1194. Alternatively, you could support multiple ports by adding an iptable rule per extra port. Below is an example of redirecting incoming UDP port 53 to 1194. UDP 53 is for DNS, very unlikely to be blocked:

# Redirect UDP 53 to UDP 1194 OpenVPN
iptables -t nat -A PREROUTING -p udp -i pppoe-wan --dport 53 -j REDIRECT --to-port 1194

If this does not work for you, try using TCP port 443 by changing the following lines in /etc/config/openvpn:

option port '443'
option proto 'tcp'

Unable to connect to remote LAN machines via VPN

Firstly, avoid using very common subnets such as 192.168.0.x and 192.168.1.x. If the source (where you are connecting to VPN from) and destination (where the VPN server is running) are on the same subnet, the destination cannot be reached. The server could push a route of that subnet explicitly overriding the client’s route. In doing so however, it prevents connecting to the source LAN when client is connected to VPN. In short, stay away from very common subnets.

### Unable to ping any machine via VPN

I was having no problems connecting to VPN from my Android device but I was not able to connect from a Lubuntu notebook. After trying various settings, the setting that fixed the problem was turning on comp-lzo on the Lubuntu notebook. This is despite the server having set the comp-lzo to ‘no’ explicitly and pushing that option to client too.