Much has been said on the subject of VPN services. If you have ever watched a YouTube video, you have probably heard some version of the words, “This video is made possible by our sponsor <fill in the blank> VPN!” followed by a torrent of claims - some perfectly reasonable and demonstrably true, and others perhaps not so much - about the VPN service’s ability and effectiveness in protecting your privacy and anonymity online. On the subject of examining those claims, much has also already been said. This short article is not intended to add any new analysis or opinion from this author on the matter. On offer instead is a casual recollection of a personal project that may be useful to those who live with their hearts and minds in more than one country.


Consumer VPN offerings are a dime a dozen these days. Many are affordable, reliable, offer dozens of endpoints globally, surprisingly fast bandwidth, low latency and a polished, cross-platform experience. But even then they don’t suit every possible need. Sometimes, a more custom approach is required.

The following diagram captures the important element that makes this custom setup differ from most: The devices that are connected to the VPN do not know they are using it. They are not required to have the ability to run a VPN client or adhere to system-wide proxy settings (which they often do not). Instead, they are connecting to the local Raspberry Pi which houses the OpenVPN client, and which also serves as a wireless access point. 

High-level VPN Diagram

The sections below cover the major steps, including they key commands, to build a similar setup.

Remote Configuration

Setting up the remote server and network can involve changes to routes and security configuration in addition to the server itself. I list those steps here, but do not cover the specific implementation.

  • Configure the remote router to provide the remote Pi host with a static internal IP address
  • Configure port forwarding to allow the remote Pi host to be reached on two ports of your choosing: one for incoming VPN connections, and one for SSH

Update the System

1
2
sudo apt update
sudo apt full-upgrade

Apply your SSH Keys

(Don’t have SSH keys? Great guide here: https://www.ssh.com/ssh/keygen/)

This command is run on the workstation where you should have your SSH keys installed, (probably) not the remote or local Pi servers themselves.

1
ssh-copy-id <user>@<address>

Disable Password Authentication

Open the ssh configuration file in your favourite editor:

1
sudo nano /etc/ssh/sshd_config

Ensure the following changes are reflected in the file:

1
2
PasswordAuthentication no
PermitRootLogin no

Save and exit, then restart the ssh daemon to reload the file:

1
systemctl restart sshd

Configure the host for Dynamic DNS

The instructions below are for the free offering from noip.com (no affiliation) but there are many other options for DDNS, both free and paid. 

The steps below involve downloading the no-ip client source code, unpacking it, compiling and installing it. Finally you configure the newly installed daemon service via its configuration file before registering it with the system and starting it up.

1
2
3
4
5
6
7
8
9
cd /usr/local/src
sudo wget https://www.noip.com/client/linux/noip-duc-linux.tar.gz
sudo tar zxvf noip-duc-linux.tar.gz
cd noip-<version>/
sudo make
sudo make install
sudo nano /etc/systemd/system/noip2.service
sudo systemctl enable noip2
sudo systemctl start noip2

Easy-Install OpenVPN

1
2
3
4
wget https://git.io/vpn -O openvpn-install.sh
sudo bash openvpn-install.sh
sudo nano /etc/openvpn/server/server.conf
sudo systemctl restart openvpn-server@server.service

Retrieve and save the contents of ~/client1.ovpn that the above installer generates. These are your VPN connection details.


Local Configuration

The local side of the setup consists of three main parts:

  • Setting up the selected device, the Raspberry Pi in this case, as a Wi-Fi Access Point
  • Installing and configuring an OpenVPN client
  • Configuring IPTABLES such that all traffic originating from the wireless interface (wlan0) is routed through the OpenVPN virtual interface (tun0)

Prep the System

As always, it’s a good idea to ensure your system is updated and secure. Follow the same steps as above to update and lock down your system.

Enable Wireless

Enable wireless on the Pi, if not already.

1
sudo rfkill unblock wlan

Configure the Wireless Interface as an Access Point

The following steps are modified from the following Raspberry Pi guide:
https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md

1
2
3
4
5
sudo apt install hostapd
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo apt install dnsmasq
sudo DEBIAN_FRONTEND=noninteractive apt install -y netfilter-persistent iptables-persistent

Modify the DHCP configuration file:

1
sudo nano /etc/dhcpcd.conf

Append the following:

1
2
3
interface wlan0
static ip_address=192.168.4.1/24
nohook wpa_supplicant

Create an AP configuration:

1
sudo nano /etc/sysctl.d/routed-ap.conf

Include the following contents:

1
net.ipv4.ip_forward=1

Backup your old DNS masq config and edit the existing one: 

1
2
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo nano /etc/dnsmasq.conf

Include the following in the config:

1
2
3
4
5
interface=wlan0 # Listening interface
dhcp-range=192.168.4.2,192.168.4.20,255.255.255.0,24h
# Pool of IP addresses served via DHCP
domain=wlan # Local wireless DNS domain
address=/gw.wlan/192.168.4.1

Configure the Access Point:

1
2
3
4
5
6
7
8
9
10
11
12
13
country_code=CA
interface=wlan0
ssid=<SSID>
hw_mode=g
channel=7
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=<passphrase>
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Install and Configure OpenVPN Client

The client side of this VPN install is considerably less involved than the server which is why simply installing the binaries from repo is likely sufficient.

Place your saved .ovpn file in /etc/openvpn/client and give it the name client.conf then run:

1
2
sudo apt install openvpn
sudo systemctl start openvpn-client@client

Configure Network Restrictions

1
2
3
sudo iptables -t nat -I POSTROUTING 1 -o tun0 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tun0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -I FORWARD 1 -i wlan0 -o tun0 -j ACCEPT

Persist the changes with: sudo netfilter-persistent save

Reboot and try it out!

1
sudo systemctl reboot

Use another device to connect to your newly-minted Wireless Access Point and verify you have connectivity and that your IP address is that of the remote host, and not your local IP address.


All information contained herein is for educational purposes and is provided as is, and without any representation or warranty of any kind, either express or implied, including without limitation any representations or endorsements regarding the use of, the results of, or performance of the information, its appropriateness, accuracy, reliability, or correctness. The entire risk as to the use of this information is assumed by reader.

Enjoy!