Graham Stevens
⟵ Home

WireGuard Setup Guide for iOS

WireGuard is the new kid on the block when it comes to VPNs. I could try and explain what it is and why you should switch from OpenVPN or IPsec to it, but they do a great job of that themselves:

WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPSec, while avoiding the massive headache.

Great” I hear you say, “but IPSec and OpenVPN are a pain to setup, let alone setup securely”. Fear not, WireGuard has you covered:

WireGuard aims to be as easy to configure and deploy as SSH. A VPN connection is made simply by exchanging very simple public keys – exactly like exchanging SSH keys – and all the rest is transparently handled by WireGuard.

This guide will walk you through how to setup WireGuard in a way that all your client outgoing traffic will be routed via another machine (server). This is ideal for situations where you don’t trust the local network (public or coffee shop wifi) and wish to encrypt all your traffic to a server you trust, before routing it to the Internet.

Server Setup Guide

I am making some assumptions here, such as using Ubuntu for your server OS, so please tweak to fit your situation.

First up, we need to make sure you’ve got the kernel headers installed, as well as enabling IPv4 forwarding:

sudo apt install linux-headers-$(uname -r)
sysctl net.ipv4.ip_forward=1
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/99-sysctl.conf  # Make the change persistent

Because WireGuard isn’t currently part of the distributed Ubuntu packages, we’ll add the helpful PPA repository to keep things easy and up to date.

sudo add-apt-repository ppa:wireguard/wireguard
sudo apt update
sudo apt install wireguard
sudo modprobe wireguard

With WireGuard now installed, we need to generate a public and a private key – fortunately, this is a simple one-liner:

wg genkey | tee /etc/wireguard/server-privatekey | wg pubkey > /etc/wireguard/server-publickey

Next up, we need to create a WireGuard config file:

sudo nano /etc/wireguard/wg0.conf

[Interface]
Address = 10.200.200.1/24
Address = fd86:ea04:1115::1/64
SaveConfig = true
# Change eth0 to your network interface if it differs
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server-privatekey>

At this point, WireGuard on the server is complete and we could start it up if we wanted, but first, lets configure our client.

iOS Client Setup Guide

Our first client is an Apple iOS device. Currently WireGuard isn’t built into the operating system, unlike IPSec or IKEv2. However, we can easily overcome this hurdle thanks to the WireGuard iOS App which is currently in alpha and can be installed easily via TestFlight. Alternatively you can check out another 3rd party client produced by TunSafe which again can be installed via TestFlight.

With one of the two apps installed, lets generate a config server-side and we can transfer it later with a simple QR code. We could manually enter a config within the app, however moving around those keys can be a nightmare…

First up, client private and public keys:

cd /etc/wireguard
wg genkey | tee mobile-privatekey | wg pubkey > mobile-publickey

We need to configure our mobile client as a peer within wg0.conf, so that we can connect to our server.

[Interface]
[...]

[Peer]
# Our mobile client details
PublicKey = <contents of mobile-publickey>
AllowedIPs = 10.200.200.2/32, fd86:ea04:1115::2/128

That is everything we need to do for our server config - simple right?


To split things up a little, lets start WireGuard. We can bring the interface up with wg-quick up wg0, as well as down with wg-quick down wg0.

However if you would rather run it as a service so that it is always brought up on start-up or after reboots, we can utilise systemctl:

systemctl enable wg-quick@wg0  # Enable to start at boot-up
systemctl start wg-quick@wg0  # Start to.. well, start.

You can get the current status of WireGuard by simply running wg:

root@lon-vpn:/etc/wireguard# wg
interface: wg0
  public key: 3YjKyxxxxxxxxxxxxxxxxxxxxxxxxxxxsx856vfcQc=
  private key: (hidden)
  listening port: 51820

peer: x8roC6GOxxxxxxxxxxxxxxxxxxxxxxxdi7Uhol6xY=
  allowed ips: 10.200.200.2/32, fd86:ea04:1115::2/128

With WireGuard successfully running, lets create a conf file for our iOS device which we will transfer via QR code. We can do all of this whilst we are still on our server.

cd /etc/wireguard
nano mobile.conf

[Interface]
PrivateKey = <contents of mobile-privatekey>
Address = 10.200.200.2/32, fd86:ea04:1115::2/128
DNS = 8.8.8.8

[Peer]
PublicKey = <contents of server-publickey>
Endpoint = <server-ip>:51820
AllowedIPs = 0.0.0.0/0, ::/0

Mobile config done. Lets get it transferred to our device. We will do this using a QR code, which we can create on our server using qrencode. You can install this via apt install qrencode.

To generate the QR code and display it on the screen:

qrencode -t ansiutf8 < /etc/wireguard/mobile.conf

A QR code generated from `mobile.conf`

Simply scan this code using one of the iOS apps mentioned previously, and you will be all setup! Enjoy routing all of your traffic via your server. You can verify this by visiting https://canihazip.com or similar on your device.


$ whoami I am Graham Stevens, a Cyber Security Specialist based in the South West of the UK. If you're lucky, I very occasionally post updates on Twitter.