I've been dying to try out WireGuard for a while now, and I finally got around to it. I was scouring tutorials and also checked the docs and figure it all out. It's a new VPN protocol, that works similarly to ssh. I've put my desktop, iPhone, and MacBook Air on it. Here's a few neat things it's allowed me to try:
- Running iOS builds from xcode without being on the same physical network. Useful on an unknown network and you don't feel like connecting your phone after connecting your laptop.
- Accessing development servers from any device, without remembering the IP address. Ex:
macbookair:3000from any of my devices, across any network.
- Throwing up code-server on my desktop, and coding from my iPad from anywhere.
- Using VS Code's Remote SSH plugin, and running all projects on a desktop, increasing Macbook air battery life. Plus things run way faster and cooler on the laptop now!
- Steam link / game streaming away from home.
- Adding a windows file share (raid setup) to the iOS Files app, using it from anywhere. It's like having your own personal iCloud.
There's so much more you can do, hopefully that gives you some ideas.
Here's the fastest way to get it running on Ubuntu and iOS, while also persisting your configuration.
Get an Ubuntu server running 20.04, I like to use Digital Ocean. After setup, I tend to change the default SSH port in
/etc/ssh/sshd_config and also disable root logins.
First, we need to enable ipv4 forwarding, so that traffic flows through our VPN:
sysctl net.ipv4.ip_forward=1 sudo vim /etc/sysctl.d/99-sysctl.conf # Add 'net.ipv4.ip_forward = 1' to the end of the file
Now let's install WireGuard
sudo apt install wireguard
Let's generate keys for our server
umask 077; wg genkey | tee privatekey | wg pubkey > publickey sudo mv publickey /etc/wireguard/publickey sudo mv privatekey /etc/wireguard/privatekey
the first command ensures that our outputted file can only be used by the current user, as a security precaution. The remaining piped commands come from the key generation docs from WireGuard. After that, I am copying the files into the wireguard directory for safe keeping.
Create our first peer's keys
wg genkey | tee mobile-privatekey | wg pubkey > mobile-publickey sudo mv mobile-publickey /etc/wireguard/mobile-publickey sudo mv mobile-privatekey /etc/wireguard/mobile-privatekey
Let's create our WireGuard interface configuration.
sudo vim /etc/wireguard/wg0.conf
[Interface] ## Internal IP for the interface ## Address = 10.10.10.1/24 ## Whatever DNS provider you want to use, in this case CloudFlare ## DNS = 18.104.22.168 ## My VPN server port ## ListenPort = 41194 ## cat /etc/wireguard/privatekey and paste the contents below ## PrivateKey = privatekeytext # 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; iptables -A INPUT -s 10.200.200.0/24 -p tcp -m tcp --dport 53 -m conntrack --ctstate NEW -j ACCEPT; iptables -A INPUT -s 10.200.200.0/24 -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT 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 ## Add the below section for every client you created above ## ## Increment the allowedIPs by one each time ## [Peer] PublicKey = publickeyfromclient AllowedIPs = 10.10.10.2/32
Internal IP for the interface
Be sure to paste your
PrivateKey contents, first one is
/etc/wireguard/privatekey and the other would be your
mobile-publickey. Open up access to the
ListenPort of your choosing, if you have a firewall like csf or ufw enabled.
Next, we enable the service, so that it runs on boot, and start it:
sudo systemctl enable wg-quick@wg0 sudo systemctl start wg-quick@wg0
sudo wg and make sure you see your interface and peers listed with the correct addresses. You can create multiple interfaces, just make
wg1.conf and enable that, instead of
wg0 above. This can be useful if you have a lot of devices and networks you want to setup.
Our server is good to go! Let's make a config file for iOS now. There's nothing special about this config, and it could be used on any type of device. But at the end we will encode it in a QR code for usage in the mobile WireGuard app.
[Interface] PrivateKey = <contents of mobile-privatekey> ## Must match peer address in our server config above ## Address = 10.10.10.2/32 ## Setup your own DNS server, or use CloudFlare / Google / etc ### DNS = 22.214.171.124 [Peer] PublicKey = <contents of server-publickey> Endpoint = <public-server-ip>:41194 AllowedIPs = 0.0.0.0/0, ::/0
Interface PrivateKey with the contents of
Peer PublicKey with the server's
/etc/wireguard/publickey. Finally, put your server's public IP address in the
Add to device
sudo apt-get install qrencode qrencode -t ansiutf8 < mobile.conf
You'll now see a QR code. Scan it using the WireGuard iOS app, and you should be connected!
Adding more peers
Here's a quick reference for when you want to add a new client device to your VPN network.
# Generate new private / public keys wg genkey | tee DESKTOP-privatekey | wg pubkey > DESKTOP-publickey # Copy existing config, since it has most of what we need cp mobile.conf DESKTOP.conf cat DESKTOP-privatekey # copy contents vim DESKTOP.conf
DESKTOP.conf (or whatever you named it) you need to paste the private key contents at the top, and then increment the Address by one. Ex:
Now we need to update our
cat DESKTOP-publickey # copy the contents vim /etc/wireguard/wg0.conf # Add the following lines to the bottom [Peer] PublicKey = contents-from-above # Matching IP from our DESKTOP.conf file AllowedIPs = 10.10.10.4/32 PersistentKeepalive = 25
If your device is behind a firewall, and it is going to be routinely used as a server, you will want to use PersistentKeepalive, otherwise you can omit it.
My desktop doesn't access anything from my iPhone, so my iPhone doesn't use it. However, I do use PersistentKeepalive on my desktop, because my iPhone regularly connects to its development server, file share, etc and it is behind a router.
Now we run
sudo systemctl restart wg-quick@wg0 and then
sudo wg should show the peer we just added.
DESKTOP.conf file to your device, or use the QR method from above for mobile. Repeat these steps and replace
DESKTOP with your real device name!
If you are serious about using this, it can be nice to setup a DNS server as well. This way you can alias all your device IP's and just use
iphone when connecting between devices. Follow this guide for more on that. I wanted to keep this tutorial to the bare minimum. Because of my interest in WireGuard, I've been following a tuturial on making a DNS server in Rust. So I may write about setting that up if I end up finishing it.
I hope this was helpful, as I had found a mix of the above steps, and some extra unnecessary things on other tutorials.