Raspberry PI VPN Gateway with ExpressVPN

Although I run a OPNsense box as a firewall, I still use a raspberrypi connected to my LAN as my VPN gateway for my devices. The PI is a low cost hardware and delivers decent VPN performance for my LAN (~30Mbps).  Alternatively I could have the OPNsense box run a VPN client but I decided against it keeping my requirements in mind. Part of it was also because ExpressVPN provides a very easy PI package to connect to VPN servers. If you are out to configure the PI to act as a VPN client for you LAN devices read on.

Assuming you already have the PI setup with an IP address and connected to the network (I have PI connected to the local network through a wire – eth0). You would do the following configuration.

Part 1 – Setup PI to Forward traffic to VPN.

Enable IP Forwarding for the PI to forward packets

nano /etc/sysctl.conf
net.ipv4.ip_forward = 1

Enable NAT for packets received on LAN to the tunnel.

sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT

To make the rules persistent use

sudo apt-get install iptables-persistent

Apply the rules at startup

sudo apt-get install iptables-persistent

Part 2 – Setup Express VPN

Download the ExpressVPN installer file to pi. Install and activate using the command

sudo dpkg -i expressvpn_1.2.0_armhf.deb
expressvpn activate

You get the activation code from the Downloads page on ExpressVPN when you download the ExpressVPN installer for PI.

List servers to connect to

expressvpn list

Connect to a particular server and to check the status

expressvpn connect ussc
expressvpn status

Disconnect from server

expressvpn disconnect

Connect to the last connected server

expressvpn connect

At this point, you should have the PI connected to the VPN and ready to accept connections from your LAN devices. All that is left to do is to use the PI’s IP as the default gateway for devices that need a VPN connection (in my case, I point the Apple TV to use the VPN)

Lan is -
Firewall -
PI -
Apple TV -; Default GW

You could also set the PI to provide your the ExpressVPN DNS to your LAN devices by

sudo apt-get install dnsmasq

This ensures your DNS queries do not go leaking to your ISP. Don’t forget to set the DNS on your devices that need a VPN connection to the PI IP.

End – for now 🙂

The Leaking DNS in Ubuntu 18.04 and OpenVPN

So  finally i got to installing Ubuntu LTS 18.04 on my work PC. Have been toying with Linux for a number of years but never took the plunge.  The place where i work forces us to use Vmware Horizon as a VDI solution to access to our work machines, so the operating system doesn’t really matter.  Gives me a perfect stage !

Anyways the short story is – the install went smooth and I managed to get Vmware Horizon working on my machine without any major issues. I routinely use a lot of SSL VPN to my home to access my files and also to tunnel my traffic back home when i am on a public WiFi so i went about setting that up.

Install OpenVPN

sudo apt install openvpn

I already had the .ovpn file from the VPN server. It reads

cipher AES-256-CBC
auth SDHA512
reneg-sec 0
remote abc.com 1194 udp
lport 0
verify-x509-name "SSLVPN CA"name
remote-cert-tls server
comp-Izo adaptive

To connect to the VPN simply run the following.

sudo openvpn –config <path to the ovpn file> –dev tun0

sudo openvpn --config profile.ovpn --dev tun0

If you get an error , double check your ovpn profile and the error message. Sometimes the profile is not in the format expected by ovpn (check aginst my profile above)

You can also use the GUI to import the profile and connect to the VPN. Install the GUI by issuing the following command.

sudo apt-get install openvpn network-manager-openvpn network-manager-openvpn-gnome

To connect to the VPN – click on the network icon on top right of the menu bar and then goto VPN. Import the ovpn profile and reboot the pc.

Happy that everything works as intended, i went on to verify that all my traffic was routed via the tunnel and that i was able to access the home network. To verify that my DNS queries were also sent via the tunnel i went to http://dnsleak.com and behold – my DNS was leaking.

What does that mean ?That means that my DNS requests were being sent to the the sites through the local DNS server and not through the VPN.

 To check what was happening, I went to read the contents of /etc/resolv.conf. There i was directed to see systemd-resolve status to find out what DNS servers were in use. systemd-resolved is a system service that provides network name resolution to local applications.

systemd-resolve --status

I could see that my home DNS server was listed as the DNS resolver under the tunnel interface and the local DNS server was listed as a resolver under the physical interface (WiFi). Reading around a bit i found that by default, systemd-resolved queries all interfaces for DNS resolutions. If you want to avoid dns leak, it seems you need to force it to only use the link created by Openvpn.

To do that, we make use of a helper script called openvpn-systemd-resolved.

sudo apt install openvpn-systemd-resolved

Now add the following lines to the OpenVPN configuration file (.opvn from before)

script-security 2
up /etc/openvpn/update-systemd-resolved
down /etc/openvpn/update-systemd-resolved
dhcp-option DNSSEC allow-downgrade
dhcp-option DOMAIN-ROUTE .

<the ‘.’ above is very important. If you miss it, the DNS queries will continue to leak>

  1. script-security 2 – this directive offers policy-level control over OpenVPN’s usage of external programs and scripts. Script security level 2 allows calling of built-in executables and user-defined scripts.
  2. up and down directives specify the commands to run after successful TUN/TAP device open and close, in this case, which are /etc/openvpn/update-resolv-conf and /etc/openvpn/update-resolv-conf correspondingly. These scripts align the resolv.conf with the DNS address supplied by OpenVPN server, returning it to its original state when the connection is closed.
  3. dhcp-option DOMAIN-ROUTE means for querying a particular domain use this DNS server. Using a . dot/period instead of a specific domain name matches all domain names and sends all queries out to the VPN.

Restart openvpn and Validate by going to http://dnsleak.com. Now my systemd-resolve –status reads.

Link 16 (tun0)
Current Scopes: DNS
LLMNR setting: yes
MulticastDNS setting: no
DNSSEC setting: allow-downgrade
DNSSEC supported: yes
DNS Servers:
DNS Domain: ~.

Link 2 (wlp2s0)
Current Scopes: DNS
LLMNR setting: yes
MulticastDNS setting: no
DNSSEC setting: no
DNSSEC supported: no
DNS Servers:

This seems to only work if i launch the VPN from the command line. If I use the network manager it doesn’t work.

The End — For Now 🙂