OpenVPN on Tomato with Android and Linux Clients

I’ve been wanting to do this for a very long time. When away from home I sometimes need access to the systems (or data residing on those systems) back at home. I wanted to set up a secure means to access the machines behind my router’s firewall and one of the most versatile and secure ways to do that is with a Virtual Private Network (VPN). The problem was that this stuff is pretty complicated and even though the open source firmware we run on our router has had a VPN-enabled version available, I’ve been loathe to try implementing it.

Well, the garage control system project I was recently working on had a hardware failure such that I could not implement it in the original way intended (until I replace the CAI WebControl board central to it). The board failed in such a way that it would not accept PLC programming but would still respond through the default web interface – which unfortunately is not sufficiently secure to expose to the internet directly. However, we were going away for an extended period and I needed to be able to access it while away. A perfect application for VPN technology, I could keep the “vulnerable” system firewalled behind the router and poke a secure hole through it using the VPN to control it from afar when needed. Just the shove I needed to get going on the VPN!

Curiously enough, in googling, I was able to find various basic tutorials about setting up a Tomato VPN-enabled router (which is Linux based) as a VPN server with Windows clients and creating the certificates and keys on Windows but pretty much nothing simple about doing so with other platforms like mine – Android (again Linux based), Linux and Mac. The ones about setting up a VPN with Linux all seemed to want you doing everything down in the weeds of config files and installing VPN packages on your own server (not a router). Not what I wanted.

The good news for you and me is that I figured out how to get this done with minimal effort and it pretty much worked perfectly on the first try, so I’m writing it up here for future reference and to share with any others following this path. Looking back, it wasn’t that hard but the lack of clear guidance made it all confusing. All that said, here’s some clarity on how to get it done:

Creating Certificates and Keys

On Linux Mint LMDE (Debian Linux) workstation, using Synaptic or another package manager install:
openvpn
easy-rsa

This will install the easy-rsa scripts into
/usr/share/easy-rsa

Taking note of the instructions at http://openvpn.net/index.php/open-source/documentation/howto.html#pki, I did the following:

Copy the easy-rsa files to another location that will persist after package upgrades (note, this location already existed as a result of the openvpn installation and contained the single file update-resolv-conf, so maybe that claim is misleading?) and cd into that directory:
sudo cp -R /usr/share/easy-rsa/* /etc/openvpn/
cd /etc/openvpn

Edited the vars file using vi to set the KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, and KEY_EMAIL parameters. These were at the bottom of the file for me. From what I can tell, the two email entries are identical but for the quote symbols. I presume the quoted one is meant to be the “real life name”, but nothing I could easily find via google confirmed or contradicted this – so I just set them both to the same address.

export KEY_COUNTRY="US"
export KEY_PROVINCE="MA"
export KEY_CITY="MyCity"
export KEY_ORG="My ORG Name"
export KEY_EMAIL="vpn_contact@myDomain.com"
export KEY_EMAIL=vpn_contact@myDomain.com

I then completed the rest of the steps at the above link using root/sudo priviledges, creating the certificate authority, server certificate and key and then the client certificates and keys. What I found online was not very informative on this point, but the Commmon Name (CN) must be entered each time you build these items and should be varied so as to be descriptive. So, for each command:

./build-ca
For this I specified my own name as the Common Name (I’m my own certificate authority) and it generated two files, ca.crt and ca.key (note, these are not named after the Common Name given, unlike the following).

./build-key-server ServerName
I gave my intended VPN server name as the ServerName which it then used as the Common Name and generated ServerName.crt, ServerName.csr, ServerName.key plus a 01.pem file and changed the index.txt and serial files in the keys directory.
NOTE: I also here encountered something different than that laid out at the above URL, for each key it asked me for:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
which I simply clicked Enter through (I presume to set as blank, as no password was later asked for).

./build-key ClientNameHere
I gave unique descriptive names for each client and it created similar files to the server ones above, named per the client names I gave, created sequentially numbered pem files and updated the index.txt and serial files.

./build-dh
Returned Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
(But it didn’t – it was less than 5 seconds on my main Linux 64 bit workstation)

In the Arch Linux wiki entry for EasyRSA it stated that there was a need to convert the server certificate to an encrypted .p12 format for use on Android. I found this to not be needed, using the OpenVPN for Android client from the Google Play Store.

In order to provide additional TLS security and to protect against potential denial of service attacks against my router/VPN server I also set up an HMAC signature:
openvpn --genkey --secret ta.key

Setting the server and clients up…

As I created all the certificates, keys, etc. on my main Debian workstation, I needed to transfer those files to the associated machines. First I used my browser and the Tomato-powered router (VPN server) web interface to set up the VPN server following the info here *except* for using TUN instead of TAP. Installing Tomato is covered in my other blog post. Here’s screenshots of my settings (click on them to enlarge):
Tomato-Version
Tomato-VPN-Basic
Tomato-VPN-Advanced
Tomato-VPN-Keys
Tomato-VPN-Status

Connecting with a Linux machine. I then set up the test client on my Mint LMDE/Debian laptop following the leads at https://support.hidemyass.com/hc/en-us/articles/202721596-OpenVPN-Setup-with-Network-manager-on-Linux-Mint-Mate , which dragged along a bunch of other required packages including openvpn, easy-rsa, etc. I imported the certificates and keys when setting up the VPN connection using NetworkManager. Trying to connect via this initially failed. I thought this might be because I was on my home network at the time, so I proceeded to set up my phone as a client to see if I could use the cellular network to test outside access.

Connecting via Android. I installed OpenVPN for Android from the Google Play store onto my cell phone. Copied over the certs and keys to my phone using USB cable and set up the connection in the app. Took a bit of twiddling to figure out where everything went and which boxes to check, but it connected quickly once set up. Could access private resources behind the router firewall now! I went on to set up my Android tablet with the same app.

Connecting from an Outside Network. Brought my phone, Linux laptop and Android tablet for a drive to find an available Xfinity Wi-Fi connection. Tried each client to access the VPN once connected to some poor folks’ wireless access point (why folks stand for Comcast doing this, I don’t know), and they all connected quickly and could access my Garage Control System web interface on my home network… success!

Note that in none of these set-ups did I need to edit or create any configuration files manually on the clients or server, despite lots of other tutorials making great points of this! It appears each of the OpenVPN server and client implementations I used took care of this for me.

The only bit of weirdness is that I cannot figure how to directly disconnect from the VPN using NetworkManager under MATE desktop on my Linux laptop. I can disconnect the VPN by dropping the wireless connection overall. There should be a “Disconnect VPN” option within NetworkManager but I don’t see it on my laptop when I’m connected (it is there when I’m not!). But that’s a (minor) problem for another day.

I’ve found the disconnect option in the VPN menu under NetworkManager and that can be used to drop the VPN connection. The Android clients have a connection status entry in the notifications list which provides a disconnect option once clicked on. All good to go now!

This entry was posted in Computer, Debian, DIY, Linux, Mint, Windows and tagged , , , , . Bookmark the permalink.

10 Responses to OpenVPN on Tomato with Android and Linux Clients

  1. Gaurav says:

    Nice post, may I ask you one question, is it necessary to be on static ip, or router was able to do with dynamic ip

    • Don says:

      Sorry for the delayed reply, this comment was waiting in my post SPAM queue.

      A static IP is not required for the router, I use a dynamic host forwarding service.

  2. Wayno says:

    First off, thank you for this post.

    If possible, could you go through the OpenVPN for android settings? If that’s too much work perhaps post some screenshots? For the life of me I can’t get my Android phone to work. Connects (Router assigns it an IP address) but spits out errors. Presently I get write to TUN/TAP: Invalid argument (code=22). There are a ton of options in the settings that I’m confused about. Thank you again.

    • Don says:

      You’re welcome – glad it has been of use to folks!

      Before I spend any real time on this, are you using the exact same options selections within OpenVPN on the Tomato Router as I specify in this post? And the same Android VPN app (https://play.google.com/store/apps/details?id=de.blinkt.openvpn)? If not, then my client settings in the Android app will be different than yours and I’m not expert enough to tell you what to change to match. It’s been a while since I set this up…

      If you are using the same app and OpenVPN on Tomato settings and our only difference is then the router address and certificates/keys set, I can post what my selections on the Android app are for my connection Profile (there is a “Generated Config” text listing in the last tab of the profile which summarizes them, which I can redact the sensitive parts out of and post).

      • Waynosan says:

        Thanks Don!
        Two differences: 1. I’m using TAP, and 2. one of the options “Push LAN to Clients” in my Tomato doesn’t show up (even though I have confirmed I’m using the same firmware version as you; probably due to different HW, in my case a Linksys E3000 router).

        • Don says:

          Ah, but (from here):

          TAP drawbacks:

          • causes much more broadcast overhead on the VPN tunnel
          • adds the overhead of Ethernet headers on all packets transported over the VPN tunnel
          • scales poorly
          • can not be used with Android or iOS devices

          The “Push LAN to Clients” option only appears if you’re using TUN, so that’s why you’re not seeing it. 🙂

          Here’s my redacted settings summary from the Android OpenVPN app:

          # Enables connection to GUI
          management /data/data/de.blinkt.openvpn/cache/mgmtsocket unix
          management-client
          management-query-passwords
          management-hold

          setenv IV_GUI_VER "de.blinkt.openvpn 0.6.50"
          setenv IV_PLAT_VER "***MY ANDROID TABLET BUILD ID, ETC.***"
          machine-readable-output
          ifconfig-nowarn
          client
          verb 4
          connect-retry-max 5
          connect-retry 5
          resolv-retry 60
          dev tun
          remote LOWERCASE.MY.VPN.DYNDNS.DOMAIN.ADDRESS 1194 udp

          -----BEGIN CERTIFICATE-----
          ***REDACTED CERTIFICATE CONTENT***
          -----END CERTIFICATE-----



          -----BEGIN PRIVATE KEY-----
          ***REDACTED KEY CONTENT***
          -----END PRIVATE KEY-----



          Certificate:
          Data:
          Version: 3 (0x2)
          Serial Number: 5 (0x5)
          Signature Algorithm: sha1WithRSAEncryption
          ***REDACTED CERTIFICATE CONTENT***
          Validity
          Not Before: Jan 10 20:31:09 2015 GMT
          Not After : Jan 7 20:31:09 2025 GMT
          Subject: ***REDACTED CERTIFICATE CONTENT***

          Subject Public Key Info:
          Public Key Algorithm: rsaEncryption
          Public-Key: (1024 bit)
          Modulus:
          ***REDACTED CERTIFICATE CONTENT***
          X509v3 extensions:
          X509v3 Basic Constraints:
          CA:FALSE
          Netscape Comment:
          Easy-RSA Generated Certificate
          X509v3 Subject Key Identifier:
          ***REDACTED CERTIFICATE CONTENT***
          X509v3 Authority Key Identifier:
          ***REDACTED CERTIFICATE CONTENT***

          X509v3 Extended Key Usage:
          TLS Web Client Authentication
          X509v3 Key Usage:
          Digital Signature
          Signature Algorithm: sha1WithRSAEncryption
          ***REDACTED CERTIFICATE CONTENT***
          -----BEGIN CERTIFICATE-----
          ***REDACTED CERTIFICATE CONTENT***

          -----END CERTIFICATE-----


          comp-lzo

          #
          # 2048 bit OpenVPN static key
          #
          -----BEGIN OpenVPN Static key V1-----
          ***REDACTED KEY CONTENT***

          -----END OpenVPN Static key V1-----


          key-direction 1
          route-ipv6 ::/0
          route 0.0.0.0 0.0.0.0 vpn_gateway
          remote-cert-tls server
          persist-tun
          # persist-tun also enables pre resolving to avoid DNS resolve problem
          preresolve
          # Use system proxy setting
          management-query-proxy

  3. Waynosan says:

    Thank you Don. On the server side everything is identical now. On the client side the only line I do not see in my config is:

    # Use system proxy setting
    management-query-proxy

    The only item I’m concerned about in the client log is:
    OpenVPN ROUTE6: OpenVPN needs a gateway parameter for a –route-ipv6 option and no default was specified by either –route-ipv6-gateway or –ifconfig-ipv6 options

    Either way, VPN appears to have connected as I see the key icon in the notification bar…. now for the silly question: Shouldn’t the phone now think it’s connected to my home network? I do not see any of the resources (such as SAMBA shares) on my home network when I search for them with ES File explorer on the phone. :Confused:

    Thank you again for all of your help!

  4. Waynosan says:

    Update: I can ping my samba servers, Raspberry Pi, and control my stereo (yay!) when I’m connected over the VPN (~80ms ping) but for some reason it won’t connected to the shared drives through ES File explorer. :/

    Thank you so much! If you have any idea what the issue with the shared drive access may be let me know but thank you for the inspiration and all the help.

  5. Pingback: QR Codes as a Password/Key Storage Mechanism | A New Don

Leave a Reply to Don Cancel reply

Your email address will not be published. Required fields are marked *