Getting started with Wireguard

What is Wireguard

Wireguard is a fast, straightforward, secure, and incredibly easy to set up VPN that aims to be faster than other common VPNs (like OpenVPN and Ipsec) by living inside the linux kernel and using much faster cryptographic primitives. While Wireguard is available for Windows, macOS, BSD, iOS and Android, you still need a linux kernel to benefit from the extra speed. While still in development, it’s already faster than OpenVPN. Wireguard is also different from other VPNs by not utilizing a typically ‘client/server’ relationship, opting instead for peers. Any client can be a server, and any server can be a client, and the setup is almost identical for both. Wireguard uses the GPLv2 license, and even has a positive comment about its code from Linus Torvalds:

Can I just once again state my love for [WireGuard] and hope it gets merged soon? Maybe the code isn't perfect, but I've skimmed it, and compared to the horrors that are OpenVPN and IPSec, it's a work of art

Linus Torvalds

In addition he pulled Wireguard VPN into the 5.6 kernel source tree on January 28th of 2020.

Wireguard encrypts the connection using a pair of cryptographic keys generated with Curve25519. This keypair is used by sharing the public key with the other peer who can then encrypt their data so that it can only be decrypted with the corresponding private key. Each peer will need each other's public key in order for a connection to be made.It also supports Pre-shared Symmetric, if you’d like to future proof for quantum computing.When a packet is sent via a Wireguard interface, the ipv4/ipv6 addresses (in CIDR) are compared with the packet’s destination address to determine where the packet should go. Also, when a packet is received from a known peer on a Wireguard interface, it is used to filter out any packets having a source address that doesn’t match these settings.

Bypassing CGNAT and PersistentKeepAlive

If you’re one of the unfortunate people who have to deal with an ISP that’s using CGNAT instead of ipv6 when dealing with the issue of ipv4 address exhaustion, you can use Wireguard as a solution around this while still maintaining high throughput.

In addition one of the other problems with having a host behind a NAT is that the NAT is monitoring for connections in order to route traffic, so if your peer is behind a NAT or a stateful firewall, you’ll want to maintain that connection by occasionally sending keepalive packets (as Wireguard is otherwise silent by default). The PersistentKeepalive = field tells Wireguard at what interval in seconds to send a packet. Once every 25 seconds is reasonable for most configurations, which you can set with PersistentKeepalive = 25 in your interface configuration file (which we’ll set up later on in this guide).

Setting up a point-to-point wireguard connection.

In this guide we’ll be using Ubuntu 18.04and we’re going to be calling the two peers Client and Wireguard Server (again, any peer can be a server, there is no strict client/server relationship, but for the sake of easy understanding, these names will be used as that is in effect what we’ll be doing with this tutorial)

Step 1: Install Wireguard

Install wireguard with the following command. This package will install all necessary dependencies.

sudo apt-get install wireguard

You can double check to make sure it's installed with

sudo wg help

If installed correctly you should see something like this:

2. Intro to wg command line tool

The wg command is how we’ll be checking the status of wireguard as we set things up. If invoked without parameters, it’s the same as wg show. For example, on our completed setup, invoking wg or wg show will produce something like this. Don’t worry about this now, this is our end result once we get through the tutorial.

The -showconf parameter is also useful if you’d like to see how your config file is being read by wireguard for your current connection. The other commands are used for manually creating peers, and generating keys. However we’ll be setting everything up by editing .conf files so things are a little more understandable for our first go around.

2. Create the wg0.conf file for the wireguard server.

Wireguard will read from a .conf file to create the interface that you’ll be using to connect. Create the file /etc/wireguard/wg0.conf with your editor of choice. For this tutorial, I’ll be using nano.

sudo nano /etc/wireguard/wg0.conf

Enter the following information to set up the server.

PrivateKey = --Private Key of **Wireguard Server**--
Address =
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -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

Explanation of options:

  • Address specifies which address we’re assigning to the server on the vpn. You can also use ipv6 if you’d like, but in this guide we’re using ipv4.
  • PrivateKey is the private key for the server which we’ll generate later. We’ll need this to decrypt traffic that was encrypted for the server.
  • PostUp / PostDown are keywords that define the commands that will be run when the interface is brought up or down, respectively. We’ll be using these iptables commands to set Linux IP masquerade rules to allow each peer to share the server’s IPv4 addresses. When the interface is brought down, the rules are removed.
  • ListenPort tells wireguard which port to use for incoming connections.

We’ll come back to this later to add our peer information and our keys. At this point, wireguard won’t work, so don’t bother to test it.

3. Set up UFW

We’re going to set up our firewall to allow SSH and wireguard tunnel traffic through on the server side.

sudo ufw allow 22/tcp

sudo ufw allow 51820/udp (Make sure it's /udp, wireguard is not TCP!)

sudo ufw enable

Check the status with:

sudo ufw status verbose

4. Generate keypairs

To get started you’ll need to generate a public and private key for each peer. Wireguard encrypts the traffic with public keys so that only the intended recipient can decrypt the traffic. Any peer must have the public key of the peer it is transmitting to, and Wireguard’s config file will need the corresponding private key in order to decrypt that traffic. To put it simply, a peer is the only one that should have its own private key, and it should have the public key of any peer it sends to, and they should have their public key as well.

You’ll place each key into the ‘PrivateKey’ and ‘PublicKey’ variables in the wg0.conf file that we’ll create later. Transferring the keys between each host will be up to you, but examples ahead will show you where to play them.

Generating these keypairs is made simple with this one liner:

wg genkey | tee privatekey | wg pubkey > publickey

If you do this right you shouldn’t get any output at all. Remember, a public key is generated with a private key, and the `tee` utility is how we’re able to save the key to file and also pipe it into the next command.

You can check your keys with:

cat publickey

cat privatekey

Repeat this step for both of your peers so that they each have their own keypair. Put your private key created for the Wireguard Server into the PrivateKey field of the Wireguard Server. We’ll be using the server’s public key in our config file for Client

3. Create the wg0.conf file for Client

Create the /etc/wireguard/wg0.conf file again and input the following

PrivateKey = --Privatekey of Client--
Address =

PublicKey = --Publickey of Wireguard Server--
Endpoint = --Public IP of Wireguard Server>:51820--
AllowedIPs =

We’ve added the [Peer] section to the config file, which is what will allow us to decrypt traffic coming from the Wireguard server that is sent back to us. We’ll have to do this for the server as well.

You can think of AllowedIPs as the set of addresses you expect to be reachable on the other end of the connection. Your mask will inform how packets are filtered, so if you’re just doing a point-to-point connection, then a `/32` is just fine.

Add the peer to the server

Open the /etc/wireguard/wg0.conf file on the Wireguard Server and add the public key of Client along with these options:

PrivateKey = --Private Key of Wireguard Server--
Address =
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -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

PublicKey = --Public key of Client--
AllowedIPs =

We’ve added the peer information for our intended connection, along with their public key, which we’ll need to decrypt the traffic they send to us.

5. Bring interfaces up and create services (Optional)

Now we’ll need to start the wireguard interfaces up on both peers. The command will be the same, but you should start the Wireguard Server first with:

wg-quick up wg0

Note: wg-quick is a wrapper for a bunch of functions in wg. Turning off the interface can be done with wg-quick down wg0

If you’d rather have wireguard as a service that’s up on startup, you can use

sudo systemctl enable wg-quick@wg0

sudo systemctl start wg-quick@wg0

You can check the status with sudo systemctl status wg-quick@wg0

Finally, check to see if you have a connection with:

sudo wg show