Discopter Pi Guide

Chapter 10: Creating a WireGuard VPN Server

First, a quick overview. There are two prominent VPN protocols: OpenVPN and WireGuard. OpenVPN has been around forever and is often the “default” protocol in commercial VPNs, although that's starting to change. WireGuard is faster, easier to configure, and has a much smaller codebase. Most commercial VPNs that offer a proprietary protocol, like Nord VPN's NordLynx, are based on WireGuard. Both WireGuard and OpenVPN have different approaches to handling IP addresses, and each has its own implications for privacy and security.

In the case of WireGuard, it stores the IP addresses of connected clients in memory while the VPN tunnel is active. This is because WireGuard operates on a peer-to-peer model where each client is assigned a unique IP address within the VPN subnet. These IP addresses are necessary for routing traffic between peers within the VPN tunnel. However, WireGuard does not log or store this information persistently on disk.

On the other hand, OpenVPN typically uses a centralized server-client model where the OpenVPN server assigns IP addresses to connected clients dynamically from a configured pool. OpenVPN servers may log client IP addresses for accounting or troubleshooting purposes, depending on the server configuration. Additionally, OpenVPN may store more session-related information in logs or temporary files compared to WireGuard.

Bottom line is unless you have a specific reason for using OpenVPN, you should definitely use WireGuard whenever possible. The only real common use case I can think of for OpenVPN is that certain routers that allow you to load a VPN configuration directly onto the router may only accept an OpenVPN configuration. GLi.Net routers, for example, will let you easily load a Mullvad WireGuard configuration but for some reason restrict you to OpenVPN for most other VPN providers, which will now include yourself.

Another consideration is what address you will use for your VPN server configuration. You have two options: your public IP address or a registered domain name. Chapter 6 discussed setting up a domain name. As a quick review, we would register a domain name and point it to our public IP address. The major benefit of doing this is being able to use Dynamic DNS to auto-update where our domain name points to. If our public IP address changes, your domain name will still be valid.

The other option is to directly use your public IP address. If you're doing this at home, using your public IP is a viable option. Depending on your ISP, this may change never to very frequently. If your ISP changes your public IP frequently, you'll have to update your Pi's VPN server configuration every time that happens, losing connectivity to your clients until you do. Give careful thought to this issue. Adding a domain name adds an extra step but will also allow you to leverage it should you add additional web services, like a password manager.

To create a WireGuard server and clients, we're going to be using PiVPN, an application developed specifically for Raspberry Pis that makes creating a VPN server almost effortless.

Step 1: Installing and Configuring PiVPN.

  1. Run the following command to download and execute the installer:
    curl -L https://install.pivpn.io | bash
  2. Click through the next several screens, selecting yes to force IPv6 routing.
  3. You will be asked if you are using a DHCP reservation. We ensured this back in Chapter QQQ when we installed Pi Hole, so select yes.
  4. Confirm the network settings and choose your username for the account to hold the credentials. You likely only have one option, your main account, to choose from.
  5. Select the VPN protocol. You can choose WireGuard or OpenVPN. As already discussed, unless you have a specific use case for OpenVPN, default to WireGuard, which is also PiVPN's default.
  6. The next screen will allow you to change the port the WireGuard uses on your Raspberry Pi. Much like with our SSH port, we are changing this to have some “security through obscurity.” Make sure you remember what port you choose. Click through the next screen to confirm your port choice.
  7. “We have detected a Pi-hole installation, do you want to use it as the DNS server for the VPN, so you get ad blocking on the go?” There's a reason we did Pi Hole first. Choose Yes. Now, whenever you connect to your VPN, your internet traffic will get filtered through Pi Hole.
  8. On the next screen, you'll be asked about how you want to access your VPN. Either enter your public IP address or a domain name. If you followed the guide in Chapter 6, you would enter something like vpn.MyAwesomePi.com.
  9. Click through the next several screens. Enable unattended upgrades when prompted. This will install security patches and other updates even without a `sudo apt update` or `upgrade` command.
  10. Once the installer finishes, you now have a VPN server. You still need to create profiles for it before you can connect another device. Before we do that though, let's reboot our Pi.
    sudo reboot now

It is highly recommended that you create separate profiles for each device. Don't just create one profile and copy the configuration across all of your devices. The reason for creating separate profiles is it will make it far easier to manage your device access. If you want to disable VPN access to a device, you can do so at the server without affecting any other device by simply deleting the client profile. Every other profile is unaffected. The other reason is to benefit from Pi Hole. If full logging has been enabled, you can compare the domains being blocked across different devices and adjust their settings or behavior as you deem fit.

Step 2: Creating Client Profiles

  1. To add a profile, type the following command:
    sudo pivpn add
  2. Give the profile a descriptive name that will match your device and make it easy to find. “wg-mobile”, “pivpn-laptop”, “WireGuard-iPhone”, “wgWindows” or something along those lines.
  3. PiVPN will tell you where the configuration file is located, in the configs folder on your home directory.

With our profiles created, now we have to add them to our devices. If you want to connect your mobile device (cell phone, tablet), adding the profile is extremely simple and will rely on the camera attached to the device. We unfortunately reintroduce OS-specific steps. Adding it to your computer can be done a number of ways. You can transfer the file using SCP (WinSCP is a great PuTTY-like program for Windows). On Linux, you can use rsync. You can put the config file onto a thumb drive. Or, easiest yet, just copy and paste from your SSH terminal window.

Step 3, Option 1: Adding Profiles to Mobile Devices

  1. On your mobile device, download the WireGuard app from the Android or iOS app store. Look for the red shield and dragon logo.
  2. On your Pi, type the following command:
    pivpn -qr
  3. PiVPN will ask which profile. Select a profile you made for the mobile device.
  4. PiVPN will generate and display a QR code.
  5. Back on your mobile device, open the app and click “Add from QR code.” Grant the necessary camera permissions (you can turn them off immediately after) and aim your device's camera at the QR code.
  6. The WireGuard app should recognize the QR code and prompt you to name the profile. You can choose the same name that you gave it on your Pi. If you foresee adding other configurations from different servers (maybe you have an aunt in the UK and want to leave a Pi at her place to get British Netflix), you should give it a name that identifies to which Pi or location the profile belongs.
  7. Click the toggle switch next to the profile to manage the connection.

Step 3, Option 2: Adding Profiles to Windows/Mac

  1. On your Windows or Mac computer, download the WireGuard Windows or Mac application from wireguard.com.
  2. Open the WireGuard application and click the carrot button over “Add Profile” in the lower left corner.
  3. Select “Create Blank Tunnel.”
  4. Delete the suggested text.
  5. In your SSH terminal, enter the following command to output the configuration file.
    sudo cat /etc/wireguard/configs/<profile name>.conf
  6. Copy and paste the contents to the blank tunnel prompt on your host machine and save.
  7. Click the toggle switch to manage the connection.

Step 3, Option 3: Adding Profiles to Linux

  1. Open a terminal on your Linux machine. This should be a separate terminal from your SSH session with the Pi.
  2. Install the Linux wireguard application.
    sudo apt install wireguard
  3. Create a configuration file in the WireGuard directory. Best to use the same name as what you used in PiVPN.
    sudo nano /etc/wireguard/<host profile name>.conf
  4. In your SSH terminal, enter the following command to output the configuration file.
    sudo cat /etc/wireguard/configs/<PiVPN profile name>.conf
  5. Copy and paste the contents to <host profile name>.conf in the non-SSH terminal window. Save and exit with ctrl+x.
  6. To establish a connection, use this command:
    sudo wg-quick up <host profile name>
  7. To drop a connection, replace up with down.
    sudo wg-quick down <host profile name>
  8. You can check the status of the connection to make sure that data is being transferred.
    sudo wg

Step 4: Configuring Ports

If you've done everything in the order presented in this guide, PiVPN will automatically create UFW rules. You can double check this by running
sudo ufw status

You should see rules with the comment “allow-wireguard.” If you've gone out of order, or have to re-add the UFW rules, use the following command:
sudo ufw allow proto udp from any to any port <WireGuard port> comment 'allow-wireguard'

Before you can connect, you still have to forward the port on your router. Every router will treat this process differently, but generally speaking, you'll login to the admin interface and find an option for port management, or something similar. Create a port forwarding rule for the port you specified in Step 1 (the default is 51820, we used 51920 in the example). Set the protocol as UDP and ensure that it is forwarding to the local IP address of your Pi.

At this point, test your connection. Make sure you're off of the same network as your Pi (on a mobile device, disable WiFi to use the mobile network). If you can successfully browse the internet, you can stop here. If you can't access the internet, you may need to first enable IP forwarding and manually manipulate ip-tables. This seems to be a crapshoot based on the model of the Pi and the OS installed.

Step 5: Enabling IP Forwarding

  1. For the Raspberry Pi to route traffic correctly between the VPN clients and the internet (or other networks), IP forwarding needs to be enabled. Open the following file for editing:
    sudo nano /etc/sysctl.conf
  2. Un-comment or add the following line to enable IP forwarding:
    net.ipv4.ip_forward=1
  3. Save and exit with ctrl+X
  4. Apply the changes.
    sudo sysctl -p
  5. Next, you'll need to configure NAT on the Raspberry Pi so that traffic from VPN clients can be masqueraded (NATted) to the internet. This assumes your Raspberry Pi's internet-facing interface is eth0. If you haven't disabled WiFi and are using a WiFi connection, replace eth0 below with wlan0.
    sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  6. This far more obscure iptables command is why we'll use UFW whenever possible.

Troubleshooting

Any problem you have with making a connection is most likely a result of UFW rules. Different Pi models and different versions of Raspberry Pi OS sometimes lead to not fully streamlined configuration. Enabling IP forwarding should preemptively fix issues for most, but if it still doesn't work, you can always call PiVPN with the debug flag.
pivpn -d

That will create additional more granular UFW rules. If you wind up having to go this approach, it may be worthwhile deleting and recreating the UFW rules with comments. Otherwise your UFW status page can quickly become bloated with rules you don't remember the purpose of.

If everything was done correctly, your devices can now connect to the Pi from anywhere in the world via a VPN connection. Any web traffic will reflect a point of presence for wherever your Pi is located rather than your actual physical location. By using Pi Hole as the DNS resolver, all DNS requests are encrypted with ads blocked regardless of whether ad blocking browser extensions have been enabled.