Recently I am traveling a lot doing my business so I often need to access my home network from remote locations around the world. The obvious solution to arrange this is to build the Road Warrior VPN setup on a home router or a home computer acting as server.
There are a ton of guides on the web but all of them describe making a connection to a desktop client in the tunnel mode. On the other hand, for my needs I would like to create the VPN link which will make my remote devices behave just like it is on my home WiFi net.
Once I have finally solved this challenge, I am eager to share the solution to other people facing the same problem.
As a server side I use a MikroTik RB951 router:
This $70-priced SOHO-class router is ideal for home networks operating in "set it and forget it" mode, where the power of MiktoTik's own software platform, RouterOS, makes nearly any configuration of a home network possible. The only drawback of the device is a single core CPU running at 750MHz max and no hardware AES encryption making OpenVPN encryption purely CPU-necked.
My goal was to make a VPN link which will truly bridge the remote device into the network, including DHCP address assigning, full IPv6 support and smooth UDP transfers. As a client side, I use the stock Android 7.1.2 phone.
I decided to use OpenVPN bridge for my setup. OpenVPN is de-facto an industry standard for organizing virtual private networks. Its open-source implementation and availability for every platform (including Android, iOS, Blackberry and Windows Phone) makes it a perfect choice for remote networking worldwide.
Unfortunately, MikroTik's OpenVPN server implementation lacks some standard features of OpenVPN protocol, such as:
- UDP packet encapsulation - only TCP mode is available
- No LZO compression
- No official support for DHCP assignment of a peer IP address
- No EAP-based authrentication
VPN Client Pro (Google Play) by Paolo Colucci is a paid VPN client which supports OpenVPN and SSTP VPN protocols. For OpenVPN it also features a unique component named TAP emulator, whose purpose is to overcome the traditional limitation of Android VPN API: the inability to use interface bridging on Android without root access and kernel module support for TAP interface driver. With TAP emulator, every Android client can use internal network's DHCP server to obtain the IP address from, just like the device is associated with a corporate or a home WiFi.
The typical VPN setup begins from certificate generation. However, once I already have a domain in posession running a LetsEncrypt client for certificate manipulation (I prefer acme.sh LetsEncrypt client: get it on GitHub), I decided to use the LetsEncrypt certificate for OpenVPN as well.
I saved my certificate and its private key as "ovpn-server" and "ovpn-server-key" files respectively. The trusted root CA and intermediate CA certificates forming the server certificate chain can be found on the LetsEncrypt website:
ISRG Root X1 Root CA certificate used by LetsEncrypt Signing Authority
LetsEncrypt X3 CA certificate cross-signed by ISRG Root X1 Root CA
These certificates were saved as "ovpn-ca" and "ovpn-intermediate" as well.
After all ovpn-* files were uploaded to the router using the previously configured SSH access, the configuration of MikroTik was pretty straightforward. For the reference, I used the guide from Taisto with some changes.
I wrote a simple RouterOS script to estabilish everything at once:
================ CUT HERE ===============
# declare a variable to store the ID of a IPv4 firewall rule
# dropping everything from WAN side for security
:local dropruleid
# import OpenVPN certificates and keys
/certificate
import file-name="ovpn-ca" passphrase=""
import file-name="ovpn-intermediate" passphrase=""
import file-name="ovpn-server" passphrase=""
import file-name="ovpn-server-key" passphrase=""
# create OpenVPN user and password
/ppp secret
add name="myunguessableuser" password="mysupersecretpassword" service=ovpn
# create an OpenVPN interface to be bridged into a local
# bridge with router's LAN and WLAN ports
/interface ovpn-server
add name=ovpn-user user=myunguessableuser
# create OpenVPN service profile describing the
# local address of bridge
/ppp profile
add bridge=bridge-local local-address=the-router-local-IPv4-address name=openvpn use-encryption=yes
# configure the OpenVPN server instance using profile and
# certiifcates listening on TCP port 443 (HTTPS)
/interface ovpn-server server
set auth=sha1 certificate=ovpn-server_0 cipher=aes128,aes256 default-profile=openvpn enabled=no mode=ethernet port=443
# Add firewall rules allowing external connections from a WAN side
# and denying connections to VPN server from internal network
/ip firewall filter
:set $dropruleid [/ip firewall filter find where comment="defconf: drop all from WAN"]
add action=accept chain=input comment="accept OpenVPN connections on WAN" in-interface=ether1-gateway dst-port=443 protocol=tcp place-before=$dropruleid
add action=reject chain=input comment="reject OpenVPN connections on other interfaces" dst-port=443 protocol=tcp place-before=$dropruleid
# start the OpenVPN server
/interface ovpn-server server
set enabled=yes
# protect VPN interface from neighbor discovery
/ip neighbor discovery
set ovpn-user discover=no
# remove unnecessary files
/file
remove ovpn-ca
remove ovpn-intermediate
remove ovpn-server
remove ovpn-server-key
================ END OF CUT ===============
To use the script, replace the bold values of username, password and router's local IP address in the script and copy-paste it in terminal of WinBox or SSH console. As a result, OpenVPN server becomes configured and running.
Once the VPN server part was over, the Android client configuration was simple:
1. Open VPN Client Pro:
2. Tap "+ New" button in the right-corner of screen. The VPN settings menu appears:
3. Select "New OpenVPN Profile" and write the connection name of your choice and server info:
4. Save the ISRG X1 Root CA and LetsEncrypt X3 Signing Autohrity certificates to Android phone internal storage (aka /sdcard) as "ISRG.pem" and "LetsEncrypt.pem" and import them in the "Certificates" tab of OpenVPN connection settings. Import the ISRG X1 Root CA certificate to VPN client as a Certificate Authorities entity, and the LetsEncrypt intermediate CA certificate as an "Extra certficates" entry:
Select "CA(TLS) + password" authentication type and enter the VPN username and password chosen in the OpenVPN configuration script.
WARNING: Choose user name and password wisely. The user name should not be guessable easily or be a common English word - these kinds of user names and password are easily brute-forced by hackers!
5. Set encryption options to use SHA-1 authentication and AES-128-CBC encryption:
Also AES-256-CBC can be used for a paranoid setup, but I think it is enough for now to use 128-bit encryption.
6. To enable DHCP address assignment, find out the phone WLAN MAC address (either by finding it in Settings - About Phone dialog or typing "ifconfig" or "netcfg" from Android terminal or ADB) and specify it in "Set MAC Address" field under "Use tap device" group under "Options" pane. Also yo set IPv6 address policy if IPv6 is configured on the router side:
7. Save the changes, disconnect the Android device from the WiFi hotspot and start the OpenVPN connection:
Congratulations! The OpenVPN bridged connection between Android phone and MikroTik router should be estabilished and the IP address of the phone should match the one assigned to the phone in a WiFi network.
Within this setup, I can easily watch online videos from Youtube via VPN link and do the remote debugging of applications on my phone from my home computer or gain the remote access to PCs in my home network from my phone easily.
In case of a simpler VPN setup, if the bridged connection is an overhead, the regular OpenVPN connection using a tunnel mode can be configured using the ofiicial MikroTik's wiki on OpenVPN.
As a final note, I am not affiliated neither to MikroTik nor to Paolo Colucci and his awesome VPN client app. However, this setup is cheap and working, so try it out!
Good luck and stay tuned!