Navigate back to the homepage

Secure Private Networking with Wireguard

Jarred Kenny
December 3rd, 2020 · 3 min read

I’ve seen a huge amount of hype online in the last few months about Wireguard.

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. It intends to be considerably more performant than OpenVPN.

I’ve mostly skimmed the Wireguard articles and blog posts I’ve come across without ever actually taking it for a spin. However, I’ve recently deployed an entire stack of self-hosted services on Digital Ocean and at the same time have been building up the services I have running on my home server for serving media and handling home automation. For management and backup purposes I decided it would be beneficial for both of these hosts to share a private network so that they could connect to each other as if they were both on my home lan. In the past I would have created an IPSec tunnel between the hosts and given them a route to each other using that tunnel.

But, Wireguard!

Wireguard aims to be as simple to deploy as SSH and will allow us to accomplish this same peer to peer network over an encrypted tunnel. For the purpose of this guide I’ll be referring to servers as HostA and HostB, they will be peers in our Wireguard network.

Before we begin:

  • Wireguard requires support from the Linux kernel. If your system is running kernel 5.6 or newer it has Wireguard support. If your kernel version is 5.5 or lower, there is likely a Wireguard module available in your distributions repositories.
  • Wireguard tools available from the wireguard-tools package in most Linux distributions.

1. Generate Keypairs

Each host in our WIreguard network needs a unique key pair which will identify the node and allow connections from the other nodes in our network.

As our network has two peers, we will generate two keypairs with the following using the wg command line utility:

1umask 077
2wg genkey | tee hosta_private_key | wg pubkey > hosta_public_key
3wg genkey | tee hostb_private_key | wg pubkey > hostb_public_key

This will generate a private_key and a public_key file for each of our hosts. The contents of these files will be used in our WIreguard configuration and will allow for our peers to authenticate with one another.

2. Configure HostA

On HostA, create a file called /etc/wireguard/wg0.conf and add the following content:

1[Interface]
2Address = 10.0.0.1/24
3SaveConfig = true
4PrivateKey = <hosta_private_key>
5ListenPort = 51820
6
7[Peer]
8PublicKey = <hostb_public_key>
9AllowedIPs = 10.0.0.2/32

Address specifies the IP address of the host on the Wireguard network. For simplicity, HostA will be 10.0.0.1 and HostB will be 10.0.0.2 in our configuration. The addresses of each host can be modified as desired.

Be sure to replace <hosta_private_key> and <hostb_public_key> with the keys we generated in the step 1.

The name of the configuration file (wg0) is used as the of the WIreguard interface on your system. You can rename the configuration file if you desire a different interface name.

AllowedIPs in the [Peer] block specifies from what IP addresses (in the Wireguard network space) are allowed to connect to HostA.

3. Configure HostB

Create a file called /etc/wireguard/wg0.conf on HostB with the following content:

1[Interface]
2Address = 10.0.0.2/24p
3PrivateKey = <hostb_private_key>
4
5[Peer]
6PublicKey = <hosta_public_key>
7Endpoint = <hosta_ip_address>:51820
8AllowedIPs = 10.0.0.1/32

Be sure to replace <hostb_private_key> and <hosta_public_key> with their respective keys from step 1.

<hosta_ip_address> should also be replaced with the public IP address of HostA so that the initial connection to the host can be made to establish and support our tunnel.

AllowedIPs once again specifies what range of IP addresses can be routed to over this interface. 10.0.0.1/32 allows traffic to HostA only. However, if you wanted all interface traffic to be routed via the Wireguard tunnel so that HostA acted as a VPN server you could set AllowedIPs to 0.0.0.0/0 which in CIDR notation simply means “all traffic”.

4. Activate wg0 interfaces on both hosts

On HostA:

1wg-quick up wg0

On HostB:

1wg-quick up wg0

If all went well both hosts now have a wg0 network interface which can communicate with the other host over our secure tunnel.

1hosta > ping 10.0.0.2
2PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
364 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=1.70 ms
464 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=1.84 ms
564 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=1.53 ms
664 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=1.41 ms

If you wish to make the tunnel permanent so it returns after rebooting either host, you can enable the wg-quick systemd target which Wireguard provides. To do so, run this on both hosts:

1systemctl enable wg-quick@wg0

What’s next?

We covered how to setup a simple point to point Wireguard tunnel that allows 2 hosts to communicate securely as if they shared a local network. However, Wireguard can be used for much more than simple point to point networking. With only a few more lines in our configuration on either host we could have had HostA serve as a VPN server which securely routed all public traffic from HostB or vice versa.

In fact, running a Wireguard tunnel which connects your laptop to a remote server and routes all traffic is probably the most common use case for Wireguard. Because plenty of guides already exist on using Wireguard as a complete VPN server, I decided not to cover it here. If you want to use Wireguard in that manner Linode has an excellent guide.

Enjoy this article? Join our email list.

Be the first to receive our latest content with the ability to opt-out at anytime. We promise to not spam your inbox or share your email with any third parties.

More articles from BuildSavvy

Single Node Docker Swarms are Awesome

If you've been working in the software development or devops spaces for any amount of time you've probably used docker. At this point in time, I feel docker has become as ubiquitous in the software development workflow as a text editor. Applications are getting larger and harder to manage but we've also developed excellent tooling to manage the growth. Gone are the days of running web and database servers directly on your workstation only to find out after you've pushed your code to master and the production server is running a different version of PHP or a very different web server configuration. Docker and Compose have solved this problem for us.

December 3rd, 2020 · 3 min read

Learn AWS as a non-technical founder

As a second in line technical co-founder and playing the role as the non-technical co-founder handling the business related tasks, I've…

December 16th, 2020 · 4 min read
© 2020 BuildSavvy
Link to $https://twitter.com/SavvyBuildLink to $https://github.com/BuildSavvyLink to $https://instagram.com/BuildSavvy.devLink to $https://www.linkedin.com/company/BuildSavvy/Link to $https://dribbble.com/BuildSavvy