Introduction
I recently updated my router’s firmware to Advanced Tomato, which is just a modern HTML5 reskin of Tomato by Shibby, which is an update of the original Tomato for the famous WRT54GL. Tomato is a router firmware that supports a wide variety of improved functions, including QoS, realtime bandwidth monitoring and logging, easy LAN DHCP management, etc. – including an OpenVPN server and client, as well as a few other VPN solutions. Tomato supports a number of routers, including my ASUS RT-N16.
I thought I’d try to combine Tomato’s OpenVPN server with OpenVPN for Android, allowing my Galaxy Note II1 to have a fixed endpoint regardless of data connection method (WiFi, 3G, 4G LTE) and increased privacy when connected to public WiFi.
Setup
Tomato
Before starting, I recommend backing up the current configuration settings in Tomato’s Administration > Configuration
section, as this procedure can use a significant amount of NVRAM. If a problem occurs, it can be fixed by restoring the saved configuration file.
To start, customize the settings in Tomato’s VPN > OpenVPN Server
section to your preferences:
Key Generation
Unfortunately, OpenVPN for Android doesn’t seem to play well with ‘static’ key authentication (a single identical private key on both machines), so we’ll have to set up TLS. That requires implementing a custom public key infrastructure (‘PKI’: CA certificate, server key and certificate, and client keys and certificates). While I’m not directly following the Debian instructions for OpenVPN setup, I’ll be using their easy-rsa
package of scripts to generate and manage the required certificates on one of my Debian 8 virtual machines.
After installing easy-rsa
, make a copy for this particular usage and open the vars
file:
cp -R /usr/share/easy-rsa ~/tomatoVPN
cd tomatoVPN && pico vars
Customize the definitions at the bottom of the vars
file, then continue to generate the certificates:
source ./vars
./clean-all
./pkitool --initca
./pkitool --server tomato
./build-dh
./pkitool <clientname>
With output:
source ./vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /home/<you>/tomatoVPN/keys
./clean-all
./pkitool --initca
Using CA Common Name: <your CN> CA
Generating a 2048 bit RSA private key
................................+++
............................................+++
writing new private key to 'ca.key'
-----
./pkitool --server tomato
Generating a 2048 bit RSA private key
.........................+++
.......................................................................+++
writing new private key to 'tomato.key'
-----
Using configuration from /home/nickersonm/tomatoVPN/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'<your info>'
stateOrProvinceName :PRINTABLE:'<your info>'
localityName :PRINTABLE:'<your info>'
organizationName :PRINTABLE:'<your info>'
organizationalUnitName:PRINTABLE:'<your info>'
commonName :PRINTABLE:'tomato'
name :PRINTABLE:'<your info>'
emailAddress :IA5STRING:'<your info>'
Certificate is to be certified until Jul 21 00:21:18 2027 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated
./build-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...............................................................................
<many more lines>
......................................................+....................++*++*
./pkitool <clientname>
Generating a 2048 bit RSA private key
....+++
............+++
writing new private key to '<clientname>.key'
-----
Using configuration from /home/nickersonm/tomatoVPN/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'<your info>'
stateOrProvinceName :PRINTABLE:'<your info>'
localityName :PRINTABLE:'<your info>'
organizationName :PRINTABLE:'<your info>'
organizationalUnitName:PRINTABLE:'<your info>'
commonName :PRINTABLE:'<clientname>'
name :PRINTABLE:'<your info>'
emailAddress :IA5STRING:'<your info>'
Certificate is to be certified until Jul 21 00:28:57 2027 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated
Several of these will need to be transferred to the Android device eventually:
mkdir keys/<clientname>
cp keys/ca.crt keys/<clientname>.key keys/<clientname>.crt keys/<clientname>
And the rest are needed for the Tomato interface:
mkdir keys/tomato
cp keys/ca.crt keys/tomato.key keys/tomato.crt keys/dh2048.pem keys/tomato
Back to Tomato
In the Tomato VPN configuration screen’s ‘Keys’ tab, paste the contents of the appropriate files into the fields in order:
keys/tomato/ca.crt
into ‘Certificate Authority’keys/tomato/tomato.crt
into ‘Server Certificate’keys/tomato/tomato.key
into ‘Server Key’keys/tomato/dh2048.pem
into ‘Diffie Hellman parameters’
And then save the Tomato settings and verify that the router has nonzero free NVRAM – if the certificates used up all available NVRAM, you will have to free up space or may be unable to utilize this feature.
To investigate NVRAM usage, you can use the Administration > Debugging > Download NVRAM Dump
option. This will show where NVRAM is being used – I had to delete the unused Advanced Settings > Adblock
lists, default Administration > Scripts
comments, and unused QoS rules. Alternatively, it’s possible to use local files for the certificates and load them with the VPN > OpenVPN Server > Advanced > Custom Configuration
. As I could not free sufficient NVRAM, I decided to place the certificates on my router’s filesystem. SSH can be configured in Administration > Admin Access
– after doing so, I ended up using pscp
2 to transfer the certificates to the home directory of root:
pscp -scp -r -load local-tomato openvpn-keys/ 192.168.1.1:/tmp/home/root
from my machine, and
chmod -R 0600 /tmp/home/root/openvpn-keys/
on the router3. They can then be loaded in OpenVPN with this custom configuration:
ca /tmp/home/root/openvpn-keys/ca.crt
cert /tmp/home/root/openvpn-keys/tomato.crt
key /tmp/home/root/openvpn-keys/tomato.key
dh /tmp/home/root/openvpn-keys/dh2048.pem

Tomato’s OpenVPN server can now be started with the ‘play’ button in the upper-right of the page.
Android Device
Transfer the three files noted earlier — ca.crt
, <clientname>.key
, and <clientname>.crt
— to your Android device. I use Syncthing and its Android app to keep selected folders synchronized between my desktop4, Note II, and other devices – I utilized this to transfer the keys.
Select these files in the first tab of a new connection in the OpenVPN Android app. Also make sure to change the Authentication > Remote certificate subject
to tomato
(set during key generation via ./pkitool --server tomato
). If your phone is ever on the same LAN as your router, you also want to enable Advanced > Allow floating server
so that the LAN IP address of your router will be accepted by the OpenVPN client in addition to the WAN address.
OpenVPN on Android should now be able to connect to the Tomato OpenVPN server!
Footnotes
- Yes, quite old – I haven’t found an acceptable replacement yet; perhaps the ASUS Zenfone AR or the Galaxy Note 8, assuming it’s rootable
- Windows’ version of
scp
from the PuTTY suite - Probably unnecessary if your router is only accessible locally
- SyncTrayzor is a good Windows GUI for it
Leave a Reply