March 26, 2019

Playing with WireGuard VPN

Since a couple of years I use OpenVPN to access my home network from remote and also to protect my traffic when I am traveling and have to use WiFi networks I do not completely trust. Unfortunately, the iOS VPN client does not work for me anymore so I needed an alternative.

My Fritz Box (German home WiFi router brand) actually supports an IPSec VPN. However, iOS's VPN client is horrible. You need to activate the VPN using settings buried somewhere deep in the settings menu. When you switch of the phone's screen the tunnel is closed aaaaand must enable it again… And again. And again. Furthermore, there's no option how to set the DNS server the phone uses (which I also wanted to do). So that's not an option for me.

Luckily there's a new kid on the VPN block: WireGuard which I decided to test yesterday. I found the documentation to be a bit confusing because WireGuard is quite new and some documentation seems to address the very early versions, others newer versions.

However, after a bit of research I found a nice and well maintained tool on GitHub which does two things: 1) setting up the server, 2) creating client configurations. After a bit of fiddling around I created myself the following server configuration:

# 10.9.0.0/24 holger.spdns.org:10815 ServerPubKey 1.1.1.1,1.0.0.1
[Interface]
Address = 10.9.0.1/24
ListenPort = PORT
PrivateKey = ServerPrivateKey
SaveConfig = false
# iphone
[Peer]
PublicKey = iPhonePK
AllowedIPs = 10.9.0.4/32
...

Additionally, you must enable forwarding/routing/natting in the firewall:

IPTABLES="/sbin/iptables"
SYSCTL="/sbin/sysctl"
SERVICE="/usr/sbin/service"
SERVER_PORT="PORT"
PRIVATE_SUBNET="10.9.0.1/24"

...

$IPTABLES -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -A FORWARD -m conntrack --ctstate NEW -s $PRIVATE_SUBNET -m policy --pol none --dir in -j ACCEPT
$IPTABLES -t nat -A POSTROUTING -s $PRIVATE_SUBNET -m policy --pol none --dir out -j MASQUERADE

Lastly, a client configuration can look like this:

[Interface]
PrivateKey = iPhonePrivateKey
Address = 10.9.0.4/24
DNS = 1.1.1.1,1.0.0.1
[Peer]
PublicKey = ServerPubKey
AllowedIPs = 0.0.0.0/0
Endpoint = my.dns.name:PORT
PersistentKeepalive = 25

The really cool thing is that you can easily change the behavior of the tunnel. For instance, you can easily change the DNS server the phone uses when connected to the VPN. I use this to make the iPhone use my Pi-hole (in essence a DNS-based ad-blocker/tracker blocker), which lives on my home server that uses the IP 192.168.178.200.

[Interface]
PrivateKey = iPhonePrivateKey
Address = 10.9.0.4/24
DNS = 192.168.178.200,1.1.1.1,1.0.0.1
[Peer]
PublicKey = ServerPubKey
AllowedIPs = 0.0.0.0/0
Endpoint = my.dns.name:PORT
PersistentKeepalive = 25

Also a split tunnel can be easily done. “Split” means that the phone is connected to the VPN but only traffic that must go to the home network (192.168.178.0/8) is routed over the tunnel. Other traffic is directly sent out to the Internet. This can be done like this:

[Interface]
PrivateKey = iPhonePrivateKey
Address = 10.9.0.4/24
DNS = 192.168.178.200,1.1.1.1,1.0.0.1
[Peer]
PublicKey = ServerPubKey
AllowedIPs = 192.168.178.0/8
Endpoint = my.dns.name:PORT
PersistentKeepalive = 25

With that settings, the DNS requests are answered (and cleaned!) by my Pi-hole and all other traffic is directly sent to the Internet. So you have good performance (as not all traffic flows via the home network) but also the Pi-hole functionality. Nice.

Lastly, I discovered a great setting in the WireGuard iOS client: you can tell the client to automatically connect to the VPN when, for instance, the phone uses the mobile network and/or when it is not connected to a trusted WiFi network, i.e., the home WiFi network. This can look as follows:

pihole

So to conclude: WireGuard is really on spot. It is easy to set up, works well, and has some cool features. Goodbye OpenVPN.

© holger 2015 - 2020 |