Install OpenVPN Client in a Router with only 4MB Flash

I use VPN service from Private Internet Access (PIA). For various reasons, I have decided to configure the OpenVPN client at router level for connecting to PIA server. I had an old and cheap ($25) Buffalo router collecting dust that I once used primarily as Wireless AP and I thought to finally put it into good use. I already installed popular dd-wrt firmware into it earlier; but, as the model has only 4MB flash – dd-wrt does NOT provide OpenVPN bundled into the firmware for this model. Furthermore, this router does not have any USB port. Though not impossible, it’s certainly difficult to add custom packages into a dd-wrt image. Searching around and testing gave me the impression that it would be easier to do with OpenWrt due to ‘opkg’ availability and relative flexibility compared to dd-wrt. So, I reverted back to Buffalo factory image from dd-wrt and then installed OpenWrt (Barrier Breaker 14.07) into the router.

As it turns out, it is not that difficult to get OpenVPN client installed and working even on a router which has only 4MB flash (and no USB for extRoot) when you have OpenWrt onboard! This post covers my steps to get OpenVPN client installed in the router with small flash (4MB) and also configuring connection to PIA from the router.

I have done this on Buffalo WHR-G301N, but the method should work in other routers with limited flash size (ex: 4 MB). Also, the configurations and settings for VPN in my case is for PIA – make sure to change those with the information for your provider.

The Idea:

My router has limited Flash and can NOT hold OpenVPN binaries in flash area. But, the RAM in the router can. So, I would install it in RAM and run from there. Of course, if the router is rebooted or powered off, with other contents in the RAM my OpenVPN binaries would be gone too. So, I would deploy some scripts for repeating the installation in each reboot. My settings would also enforce a ‘No VPN Connection = No Internet Connection’ policy at router level.

I am assuming:

  • You have already installed OpenWrt into your router.
  • You can ssh into OpenWrt router from PC (I used Putty).
  • You have uhttpd enabled in the OpenWrt router and can access LuCI (web interface for OpenWrt) from PC Browser.
  • The router is acting as the DHCP server for the PC and you can already browse sites (i.e. your LAN and WAN interfaces are properly configured in router).

Steps:

1. SSH to the Router.

2. Create Folder where scripts and setting files will be stored.

mkdir /etc/openvpn

3. Copy the certificate (ca.crt) and (crl.prm) files to the directory created above. These are downloaded from PIA client support area – OpenVPN config files.

4. Create a OpenVPN setting file with following content in above folder. In my case, it was ‘/etc/openvpn/pia.ovpn’.

client
dev tun
proto tcp
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
tls-client
remote-cert-tls server
auth-user-pass auth
comp-lzo
verb 1
reneg-sec 0
crl-verify crl.pem
mute-replay-warnings
keepalive 10 120

5. Create the file that will hold username and password (this is the username, password you get as a subscriber to PIA VPN service). In my case, the file is ‘/etc/openvpn/auth’. [Note: OpenVPN expects this file to have strict read permission, so best to set the permission to be only ‘owner readable, writable’  (chmod 0600 /etc/openvpn/auth).] Content of ‘/etc/openvpn/auth’:

USERNAME
PASSWORD

6. Install some prerequisite packages. These are small, so 4 MB flash can still hold these.

opkg update
opkg install kmod-tun zlib liblzo

7. Create ‘/etc/openvpn/install_openvpn_in_ram’ file with following contents. This is the file which will download OpenVPN binaries and install those into RAM during boot.

#!/bin/sh /etc/rc.common
 
# This script installs packages into RAM
 
RAM_ROOT=/tmp/root
export PATH=$PATH:$RAM_ROOT/usr/bin:$RAM_ROOT/usr/sbin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RAM_ROOT/usr/lib
 
PACKAGES='libopenssl openvpn-openssl'
 
start() {
	echo Updating package list...
	opkg update
 
	[ ! -d $RAM_ROOT ] && mkdir $RAM_ROOT
	cd $RAM_ROOT
 
	for PACKAGE in $PACKAGES
	do
		echo Installing $PACKAGE...
		tar xzf $(opkg download $PACKAGE | grep Downloaded | cut -d\  -f4 | sed '$s/.$//')
		tar xzf data.tar.gz
		find . -maxdepth 1 -type f -exec rm {} \;
	done
}

8. Create the ‘/etc/openvpn/openvpn’ script with following contents. This script will run the OpenVPN binaries installed in RAM (by the script we created in Step 7) as per provided configurations listed in the file we created in step 4.

Additional Notes: You can see that I have a number of servers listed here with only one being uncommented. If you would like to use a different server, just comment out the current line and uncomment the one you prefer. This can be useful for easily switching the servers too. So, for example, if you want to switch to a UK server from a US server, you can simply ‘comment,uncomment’ the appropriate entries and restart the script by just executing ‘/etc/openvpn/openvpn’.

#!/bin/sh /etc/rc.common

RAM_ROOT=/tmp/root
PIA_SERVER=us-east.privateinternetaccess.com
# PIA_SERVER=nl.privateinternetaccess.com
# PIA_SERVER=us-east.privateinternetaccess.com
# PIA_SERVER=sweden.privateinternetaccess.com
# PIA_SERVER=uk-london.privateinternetaccess.com
# PIA_SERVER=sweden.privateinternetaccess.com
# PIA_SERVER=germany.privateinternetaccess.com
 
export PATH=$PATH:$RAM_ROOT/usr/bin:$RAM_ROOT/usr/sbin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RAM_ROOT/usr/lib
 
start() {
	openvpn --writepid /tmp/ovpn_ciberterminal.pid --daemon --cd /etc/openvpn --config pia.ovpn --remote $PIA_SERVER 443
}

stop() {
	PIDOF=$(ps | egrep openvpn | egrep  -v grep | awk '{print $1}')
	kill ${PIDOF}
}

9. Make the scripts executable:

chmod +x /etc/openvpn/install_openvpn_in_ram
chmod +x /etc/openvpn/openvpn

10. I used ‘/etc/rc.local’ to run the scripts at boot. So, I changed my /etc/rc.local’ file to took like below:

# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
 
##  Download and Install OpenVPN in RAM  ##
# Sleep 2 minutes to allow network interfaces to come up
sleep 120
# Execute install script
/etc/openvpn/install_openvpn_in_ram start 
 
## Start OpenVPN  ##
# Sleep for 2 minutes for installation to complete
sleep 120
 
# OpenVPN start script
/etc/openvpn/openvpn start 
 
exit 0

11. Change ‘/etc/rc.local’ to be executable (otherwise, the scripts will not run). By default, it’s NOT executable.

chmod +x /etc/rc.local

12. Assign DNS addresses to be used (LuCI -> Network -> ‘DHCP and DNS’ -> ‘DNS Forwarding’ section). I (initially) used following DNS addresses, you can choose the ones suitable for you. If you would rather set up DNSCrypt to be more secure, help yourself.

209.222.18.222 # PIA DNS
209.222.18.218 # PIA DNS
8.8.4.4        # Google Public DNS

13. Run the scripts in following sequence (let the first one finish before executing the second):

/etc/openvpn/install_openvpn_in_ram start
/etc/openvpn/openvpn start

14. Confirm that a ‘tun0’ interface has been created by issuing following command. After confirming, via LuCI(‘Network’ -> ‘Interfaces’) change the interface name to ‘VPN’ and set the Protocol of this interface to ‘Unmanaged’. Also, make sure that ‘Bring up on boot’ and ‘Create a bridge over specified interface(s)’ checkboxes are NOT checked for this interface.

ifconfig
# Output should contain a tun0 interface

15. We want a ‘No VPN = No Internet’ policy. So, we need to setup firewall rules via LuCI(‘Netowork’ -> ‘Firewall’) as following. Pay special attention to the Input, Output, Forward selections and also the ‘Zone -> Forwardings’. You can change the ‘reject’ policies to ‘drop’, if you prefer.

Firewall setting for 'No VPN = No Internet Connection' policy16. At this stage, the installation and setting of OpenVPN client at our router is complete. We need to ‘Reboot’ the router and wait for 5 minutes (important). Then we should also restart the PC from where we are performing these steps. When the PC is back to life, test the VPN:

–  From LuCI, check the system log (‘Status’ -> ‘System Log’). This should contain message about the OpenVPN being installed and also the connection attempt & status.

–  From your PC, visit sites like ‘checkmyip’ and ‘dnsleaktest’.

17. In future, if we upgrade the OpenWrt firmware to newer version, the custom folder ‘/etc/openvpn’ that we created will get deleted (along with the scripts and setting files inside). To prevent that from happening, we can add this folder into ‘/etc/sysupgrade.conf’ file. Example of my ‘/etc/sysupgrade.conf’ below:

## This file contains files and directories that should
## be preserved during an upgrade.

/etc/openvpn/

Additional Settings (Optional):

You only need these steps if you are concerned that your VPN connection might drop and want to check for that possibility and re-establish the connection quickly in case of a failure.

The reason I am using this is because I have another router between this router and router from my ISP (this enables me to have two separate networks – one without VPN and another with VPN). Both routers are connected via Static route, router in middle working as the WAN side for this router. When my other router reboots (currently set to reboot once a week), this router’s OpenVPN connection naturally disconnects. But, then it falls into a loop where it can’t resolve the DNS address of the VPN server until the OpenVPN process is restarted. So, following scripts are used to remedy this situation:

1. Create ‘/etc/openvpn/vpn_status_checker.sh’ with following contents:

#!/bin/sh /etc/rc.common
 
VPNFAILCNT=$(logread -l 10| egrep -c 'Cannot resolve host address:(.+)privateinternetaccess')
PIDOF=$(ps | egrep openvpn | egrep  -v grep | awk '{print $1}')
 
export VPNPID=$PIDOF
 
if [ "$VPNFAILCNT" -gt "5" ]
then
    kill $VPNPID
    sleep 120
    /etc/openvpn/openvpn start
    sleep 60
    echo 'VPN was dead. Restarted OpenVPN.'
else
    echo 'VPN Status Checker Log: VPN Seems to be working fine.'
fi
 
exit 0

2. Change this script to be executable:

chmod +x /etc/openvpn/vpn_status_checker.sh

3. Create ‘cron’ entry to execute this script every 30 minutes:

touch /etc/crontabs/root
vi /etc/crontabs/root
# Enter Following:
*/30 * * * * /etc/openvpn/vpn_status_checker.sh >/dev/null 2>&1

4. Start and Enable ‘cron’ daemon:

/etc/init.d/cron start
/etc/init.d/cron enable

5. Optional: Change the ‘cron’ log level to add only ERROR messages into system log. This can be done by changing ‘cronloglevel’ to 9 in ‘/etc/config/system’ file.

6. Reboot router.

Result:

I have implemented this couple of months ago and so far it’s working perfectly. I have also seen great improvement in speed and stability since I implemented OpenVPN client in Router compared to doing so from PC. Though not shown in this post, adding WLAN alongside LAN to use the VPN connection is also very easy and has proven to be extremely useful in cases like watching drama serials from iPad and downloading (legal) stuff from PC at the same time. I also use the WLAN of this router as ‘Guest’ wifi access point when needed, as the guests can’t access my home devices and also I don’t have to worry too much about their internet activities 🙂

Disclaimer: I am just showing what’s worked for me, which might or might NOT work for you. If you decide to follow anything mentioned in this post, that’s your decision and I am not responsible for your actions.

16 thoughts on “Install OpenVPN Client in a Router with only 4MB Flash”

  1. As you know this router is one of the most used routers and it would be great if you make a tutorial for people without experience in linux console because I can’t follow all your steps to make OpenVPN with my PIA account run on it.

    Like

  2. how do i access that openvpn folder, and what’s the scrip extensions, is there any detailed tutorial (i mean a video or walkthrough with pictures)

    Like

  3. I have done everything like you said, however after changing the firewall settings I just straight up lose internet connection, it works if I revert back to defaults, but what is the point of that if I have no VPN.
    Do you have any suggestions on what I can do ?

    Like

  4. Hello,
    thank you very much for this amazing guide !!!
    however I have a tiny issue, everything works, but my filesystem switched in to readonly and now I can not change the VPN server.
    currently I am stuck with the one in the Netherlands and it is reeeeaaally slow for me
    Is there anyway to make the filesystem read-write again ?

    thanks in advance

    Like

    1. Hi,

      I assume you are trying to change the content of the ‘/etc/openvpn/openvpn’ file. Have you checked the obvious ones:

      1. ssh to router via terminal (example: Putty) and checked the read permission:
      cd /etc/openvpn
      ls -l

      2. If you don’t see write permission, just give it to the file and then try changing it:
      chmod a+w openvpn

      Another way would be to copy the file to local drive -> edit it using editor like notpad++ (be careful that the file format remains linux) -> remove the file in openwrt disk -> upload the changed one via scp using programs like winscp.

      If the whole filesystem has become unwritable, least I can say that it’s very unusual. In that case, probably the best course would be to reflash openwrt and start from beginning.

      Best of Luck.

      AAA

      Like

  5. With OpenWRT Image Builder you can add to the kernel those packages that you need without recompiling. You can also add the necessary configuration files. I have a 4MB router with with openvpn, easy-rsa and curl and still remain free 1.2 MB. The squashfs is only 2.8 MB.

    Like

    1. Could you elaborate on this? I’m trying to achieve exactly that but still I’ve got around 80kB too much and don’t know how to shrink the image any further. I’ve already removed PPP and PPPoE support as well as IPv6.

      Like

    2. Could you elaborate on this? I’m trying to achieve the exact same thing and I’ve got still ~80kB too much. I already removed support for PPP and PPPoE, as well as IPv6.

      Like

  6. good post, thanks. FYI you can buy these pre-configured at easyvpnrouter.com if you aren’t technical enough to figure it out, other websites don’t seem to sell this model

    Like

  7. That guide sounds perfect, I haven’t tried it yet because I don’t my router with me atm.

    Am currently using the TPLink MR3020 as a ‘dial’ home router for some field devices I require remote control of. At the moment I’m using PPTP LAN-to-LAN connection so I can access devices on the router wired LAN side from my remote connection, this works ok except 2 things, PPTP is no longer supported by Apple products and some cellular ISP’s block the ports or PPTP:(

    In your guide you allow some time ‘x’ in the ‘/etc/rc.local’ bootup script for the interfaces to load, would it be possible to poll or monitor the interface, so as soon as it becomes available the VPN connect is established?

    Like

  8. Nice tutorial. I have a batch of 841v11s. Tried your method but then I hit “out of memory” error along while executing install_openvpn_in_ram.

    I built my own Image for the 841v11 and it works flawlessly. I just want to share it with you here.

    I assume that you have a working OpenVPN server. You tested your cert files with your PC.

    Openwrt “Image builder” is not hard to follow. It took me 2 hours from start to finish.

    1. For the Image builder “make” to work with v11, follow this instruction: https://electrohobby.ca/forum/showthread.php?tid=250

    2. When you are ready, run the following code:
    make image PROFILE=TLWR841 PACKAGES=”luci openvpn-polarssl luci-app-openvpn -pppoe -ipv6 -ddns” FILES=files/

    This guide is also very informative (in German) https://youadmin.wordpress.com/2015/12/27/openwrt-firmware-fuer-tp-link-tl-wr841n-v10-zum-download/

    The guide has several prebuilt images for 841v10 and v11 with Openvpn & Luci in place. You could download the prebuilt images from there without having to build one yourself.

    3. Get the 841v11 bin files (factory image and sysupgrade) from ./bin folder. You can upload either with the (1) router web interface or (2) tftpd32 method.

    Instruction on how to flash via tftpd32 here:
    https://wiki.openwrt.org/toh/tp-link/tl-wr842nd

    4. Now your router should be ready. Just open Services > OpenVPN and upload your key/cert/ca files and click start.

    After that, the interface should say (Started Yes). Click on “Enabled”.

    You now should be able to ping OpenVPN server ip via your router ssh. But not from LAN pcs.

    5. To enable LAN connection to remote VPN site: Add VPN interface and allow input, output, forward, along with masquerading to LAN.

    To test, try ping your VPN server IP from your LAN pc.

    And that’s it. You are good to go.

    P/S: I hope the instruction is clear enough. If not, someone let me know and I will make a tutorial/video from start to finish.

    Like

Leave a comment