If you want to setup OpenVPN with 4096-bit key on OpenWRT, with a few tips and tricks in addition, read on.
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.
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.
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.
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
.
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]"
For all steps below, when prompted to enter password for keys, leave them blank.
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.
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.
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
.
build-key-server server
This creates a server key called ‘server’.
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:
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.
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.
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
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:
Import the OVPN file using your preferred OpenVPN client. The client should automatically recognise the other four files. If not, explicitly point to them.
Read on if you are facing issues. One of the solutions might be helpful to you.
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'
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.