Setting up a VPN server using WireGuard

27. November, 2021 6 min read VPN

Understanding the VPN options

Accessing network resources through various open ports on a firewall isn't the most secure option. It's safer to create a VPN tunnel and block other traffic from your network.

Setting up a VPN server isn’t always that easy. If your router doesn’t support VPN out of the box, you may need to use third-party firmware or host a VPN server yourself.

Creating a VPN server, however, has its own set of problems. Both Windows and Apple offer VPN services by themselves. These aren’t the most secure options around and difficult to get working right.

OpenVPN, ProtonVPN and the likes offer you friendly services to get started, but I wanted to host my server to have complete control without external influence.

Hello WireGuard

This is where WireGuard comes in. It works on Windows, macOS, Linux, iOS and Android, covering most use cases.

It is built on top of SSH, uses standard network protocols, is very secure and incredibly fast. Specifically, the latter is not the case with some of the alternatives.

WireGuard knows the concept of servers and clients. The server is where you set up your VPN to connect to, that forwards the traffic to your internal network. Clients connect to the server. For this to work, the server needs to know the peers (clients) public keys and IPs that want to connect and the clients the server location and its public key. This approach allows for a very secure connection.

The following sections guide you through a step-by-step guide on setting up the server and a client example using macOS.

Configuring the server

Consult the official installation instructions for in-depth information and configuration options.

I set up my VPN server using a virtualized Ubuntu server 20.04 instance. Any other OS will do; just consult the setup instructions for your preferred OS.

After the initial installation and security updates, run the following commands to install WireGuard:

sudo -i
apt install wireguard

Check that there are no error messages or warnings. If everything ran smoothly, generate a public and private key by running:

cd /etc/wireguard/
umask 077; wg genkey | tee privatekey | wg pubkey > publickey
cat publickey
cat privatekey

The last two commands will output the public and private keys (in that order). You will need these for future references.

Next, create a WireGuard configuration file using sudo vim /etc/wireguard/wg0.conf. “wg0” will be used as a network interface name to establish the connection.

That’s the intelligent thing about WireGuard. It uses standard network protocols to transmit and receive data.

Add the following content to that file:

# VPN Server
[Interface]
PrivateKey = {the private key shown earlier}
Address = 192.168.x.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens160 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens160 -j MASQUERADE

# macOS
[Peer]
PublicKey = {to be added later}
AllowedIPs = {to be added later}

Important replace the following entries:

  • 192.168.x.1/24 with your desired IP. That should be a different IP subnet from your internal network. It will be used to connect to and redirect traffic. E.g. if you use 10.0.0.0 for your internal network, choose something like 10.0.10.1.
  • ens160 replace this with your primary network interface. It is the interface that’s connected to your internal network.
  • 51820 you can choose another port. When doing so, adapt it to other places as well. I will use the standard port in this example.

PostUp ensures that the VPN server automatically forwards the traffic through NAT into your network once the service is started. PostDown accordingly resets the configuration.

Next, if you have a firewall setup, run the following commands:

sudo ufw allow 22/tcp
sudo ufw allow 51820/udp
sudo ufw status

Let’s see if everything worked correctly, start the service and check that everything is working as expected by running:

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
sudo systemctl status wg-quick@wg0
sudo wg
sudo ip a show wg0

Configuring a client

Once the server is set up, we need clients that connect to it. Clients have their WireGuard service configured with private and public keys. They can only link to the server if the server is aware that they exist. As such, we need to create a client and add the information to the server.

In our example, I’ll use a macOS computer to connect to my VPN server. Go to the WireGuard installation section and choose the software for your OS.

Open the application and click on the ”+” to “Add an empty tunnel”. Choose a name and create the following configuration:

[Interface]
PrivateKey = {should already be there}
Address = 192.168.x.2/32
DNS = 192.168.1.1

[Peer]
PublicKey = {public key from the server}
AllowedIPs = 0.0.0.0/0
Endpoint = server-ip-address:51820
PersistentKeepalive = 25

Important replace the following entries:

  • 192.168.x.2/32 use here the same IP as configured on the server. Just increment the host part 1. Further clients will keep increasing the IP host, e.g. 192.168.x.3/32.
  • DNS = make sure you add there the default DNS address of your router. This step ensures that the internet will continue to work when establishing a VPN connection.
  • server-ip-address replace this with the public IP address of your VPN server. DynDNS entries work here as well.

Once that configuration is done, go back to the servers configuration file and adapt the following information:

# macOS
[Peer]
PublicKey = {public key from the client}
AllowedIPs = 192.168.x.2/32

The allowed IP will be the same configured on the client. Also, copy and paste the client public key into the configuration.

Once done, configure port forwarding and activate the connection on the client.

Configure port forwarding

Check the manual for your router and enable port forwarding for 51820. This configuration will allow connections from the internet to your VPN server.

Save all configuration files and restart WireGuard on the server with sudo systemctl restart wg-quick@wg0.

Finally, go to your client and activate the connection. Congratulations, you have now access to your network through a subscription-free service you own yourself ;)

‘Till next time!