VPN Wi-Fi Hotspot with Raspberry Pi

TL;DR: I explain here how to setup a home Wi-Fi network, which routes all traffic through a VPN, using a Raspberry Pi.

No one wants to get tracked or sniffed while browsing. Even those, who "have nothing to hide". 

One of the ways to hide your traffic is to use a VPN. But connecting and disconnecting to it can be annoying. So, I want to setup a home Wi-Fi network, and, when connected to it, to browse automatically through the VPN.

There are already many VPN providers out there, the goal of this post is not to compare them. We just need one, which supports OpenVPN.


Setup

This setup is tested on Raspberry Pi 3 Model B+ with a 2GB SD card.

Any Raspberry Pi OS will do. I recommend using the Lite version.

Some of the values are based on a home network 192.168.0.0/24


OpenVPN

Add to /etc/network/interfaces:

auto lo
iface lo inet loopback
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp
up route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.0.1 metric 300


Add this to /etc/resolvconf.conf to disable DNS Leaks:

name_servers=1.1.1.1
name_servers_append=1.0.0.1
name_server_blacklist=192.168.0.1


Restart:

$ sudo reboot now

Make sure it works:

$ ping google.com


Install OpenVPN:

$ sudo apt-get install openvpn -y

Copy the .ovpn you get from your VPN provider to the Raspberry Pi and then copy it to the OpenVPN configuration:

$ sudo cp /path_to_ovpn/my_config.ovpn /etc/openvpn/ex.conf

Add your credentials in /etc/openvpn/login (each on a separate line):

<USERNAME>
<PASSWORD>

and secure them:

$ chmod 600 /etc/openvpn/login

You are now ready to test the VPN:

$ sudo openvpn --config /etc/openvpn/ex.conf

(Ctrl-C to stop)


Enable the OpenVPN service to connect to the VPN on startup and restart:

$ sudo systemctl enable openvpn@ex
$ sudo reboot now


Check your IP address (to make sure you are connected):

$ curl icanhazip.com


Kill Switch

In case the VPN connection is dropped, you might want to block any access to the Internet with your real IP address. This can be achieved with a "kill switch" - it won't allow any Internet traffic outside of the VPN.

Allow loopback device (localhost):

$ sudo iptables -A INPUT -i lo -j ACCEPT
$ sudo iptables -A OUTPUT -o lo -j ACCEPT


Allow all local traffic:

$ sudo iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT
$ sudo iptables -A OUTPUT -d 192.168.0.0/24 -j ACCEPT


Allow VPN establishment. Only 2 ports will be open - 1 for DNS and 1 for VPN:

$ sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
$ sudo iptables -A INPUT -p udp --sport 53 -j ACCEPT
$ sudo iptables -A OUTPUT -p udp --dport 1194 -j ACCEPT
$ sudo iptables -A INPUT -p udp --sport 1194 -j ACCEPT


Accept all TUN connections (tun = VPN tunnel)

$ sudo iptables -A OUTPUT -o tun+ -j ACCEPT
$ sudo iptables -A INPUT -i tun+ -j ACCEPT


Set default policies to drop all communication unless specifically allowed:

$ sudo iptables -P INPUT DROP
$ sudo iptables -P OUTPUT DROP
$ sudo iptables -P FORWARD DROP


Persist the iptables configuration after rebooting:

$ sudo apt-get install iptables-persistent -y && sudo netfilter-persistent save && sudo systemctl enable netfilter-persistent && sudo reboot now

(You will be asked to confirm this. Choose Yes for both IP4 and IP6.)


Test the kill switch - the ping should not work while the OpenVPN service is stopped:

$ sudo service openvpn stop
$ ping google.com
$ sudo service openvpn start
$ ping google.com


Hot Spot

This basically turns your Raspberry Pi into a WiFi router. Install hostapd:

$ sudo apt install hostapd
$ sudo systemctl unmask hostapd
$ sudo systemctl enable hostapd


Install dnsmasq (for a dhcp server)

$ sudo apt install dnsmasq


Configure the wlan interface in /etc/network/interfaces. The Wi-Fi network will be 192.168.4.0/24.

auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.4.1
netmask 255.255.255.0


Enable IPv4 routing in /etc/sysctl.d/routed-ap.conf:

# https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md
# Enable IPv4 routing
net.ipv4.ip_forward=1


Allow forwarding in iptables:

$ sudo iptables -P FORWARD ACCEPT
$ sudo iptables -A OUTPUT -p udp --dport 67 -j ACCEPT
$ sudo iptables -A INPUT -p udp --sport 67 -j ACCEPT
$ sudo iptables -A OUTPUT -p udp --dport 68 -j ACCEPT
$ sudo iptables -A INPUT -p udp --sport 68 -j ACCEPT
$ sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
$ sudo netfilter-persistent save


Configure the DHCP server in /etc/dnsmasq.conf:

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       # Alias for this router


Unblock the WLAN if it is blocked:

$ sudo rfkill unblock wlan


Configure the new WiFi network in /etc/hostapd/hostapd.conf:

country_code=DE
interface=wlan0
ssid=<NameOfNetwork>
hw_mode=g
channel=7
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=<Password>
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP


And set the config in /etc/default/hostapd:

DAEMON_CONF="/etc/hostapd/hostapd.conf"


Final reboot:

$ sudo systemctl reboot


At this point you should have a new WiFi network. Connect with you device(s) and check you IP address.