Introducing grlx
Background In a recent blog post, I discussed a few of the reasons why in 2021, I began working on a new Fleet Configuration Management tool to …
Read ArticleWireGuard is a VPN, which tunnels traffic over encrypted, secure UDP packet streams. Once a tunnel is established, the endpoints are allowed to roam (change IP addresses, such as might happen switching between WiFi networks or when connected to a cell tower). It is special when compared to other VPN technologies for many technical reasons, which led to its rapid adoption into the Linux Kernel, but three features in particular make WireGuard stand out: the CryptoKey Routing Table, the way public/private keypairs are handled, and the “silent by default” behavior.
According to the wireguard website,
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. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.
Unlike traditional VPN technologies, WireGuard has no concept of Client or Server, but instead all nodes on the network are simply Peer
s, connecting Point-to-Point.
This allows for some really interesting scenarios where packets sent through the VPN can be sent through very specific routes by setting IP masks appropriately, and if all Peer
s on the VPN have public IP addresses (or else they can ‘see’ each other in some other way, perhaps by sharing an insecure local network), the single point of failure built into the Hub-and-Spoke model becomes optional.
However, even if WireGuard doesn’t specifically recognize the Hub and Spoke model, it’s still a valid configuration,and we’ll be using it for this tutorial. Let’s see how easy it is to configure a Hub and Spoke-style, simple WireGuard VPN ready for personal or commercial use.
Choose a private IP block to reserve. In order to use WireGuard inside of a Spoke and Hub paradigm, it’s necessary to reserve a block of IP addresses for all the nodes. (When running Peer to Peer, it’s not necessary for these addresses to share a subnet, as a CIDR of /32 can be used for each peer.) Private IP ranges include:
10.0.0.0
to 10.255.255.255
172.16.0.0
to 172.31.255.255
192.168.0.0
to 192.168.255.255
An example range for WireGuard might look like: 192.168.2.1-192.168.2.255
(be sure this range doesn’t conflict with that of your router).
In CIDR notation, this range would be: 192.168.2.0/24
.
You can use a
CIDR Calculator to determine the proper format for a given range.
Choose a port for your tunneled traffic to use.
WireGuard traffic flows over UDP, and by default uses port 51820
.
For this tutorial, we will assume you are using the default port, but if you are running multiple WireGuard VPNs on the same server, you will need to choose a different port for each one.
Choose a cloud provider that provides you with a public IP address. My personal preference is Linode/Akamai (by using my signup link you’ll get free credits, as will I.)
Once you are ready to spin up a server, be sure to choose a distribution/flavor which ships Linux 5.6 or above.
(Some versions of Ubuntu with older kernels also received backports, but if you have the option, go with the latest stable release available.)
It is possible to use WireGuard in Userspace (if you don’t know what this means, don’t worry about it, just use a newer installation image) but it is much slower than the version running in the kernel.
Going forward, we will assume you have the public IP of 93.184.216.34
(used for
example.com).
Install WireGuard and its helper utilities.
The name of the helper utilities package is usually wireguard-tools
, and installing that package should bring in wireguard
as well.
If you don’t already have iptables
installed, you will need to install that as well.
(On Debian-based systems, run apt install wireguard-tools iptables
.)
Enable IP forwarding.
This is a necessary step for the server to act as a router.
On Linux, this is done by running sysctl -w net.ipv4.ip_forward=1
.
To make this change permanent, edit or create /etc/sysctl.conf
and add the line net.ipv4.ip_forward=1
.
Create a keypair for your server.
Once WireGuard is installed, you can generate a private key by running wg genkey
.
To get the public key, run wg pubkey
and paste (or pipe) in the private key.
This keypair is just like an SSH public/private keypair, so keep it safe!
Use the keypairs to create a configuration file. The next step is to create a configuration file for your server. There are three main pieces of information required:
192.168.2.1/24
)Create a file at /etc/wireguard/my-vpn.conf
and add in the following:
[Interface]
ListenPort = 51820
PrivateKey = <SERVER PRIVATE KEY HERE> # <SERVER PUBLIC KEY HERE>
Address = 192.168.2.1/24
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Many systems use eth0
as the name of the primary network interface, but if yours is different, you will need to change it in the PostUp
and PostDown
commands.
If you are unsure of your default gateway’s interfacve name, run ip a
and look for the interface with the public IP address you are using to connect to the server.
Additionally, you will add a block for each Peer
, but we’ll need to generate those keypairs first.
More on that later.
Be sure the connection port is exposed through your hosting provider (for UDP traffic). Instructions for Linode can be found here. You may need to consult your provider’s documentation for more information.
Before we start up our server, we need some more information from our clients. We’ll come back to the server later.
apt install wireguard-tools
/etc/wireguard/
wg genkey
my-vpn.conf
and save it, along with the details you got from the server.
The format is as follows:[Interface]
PrivateKey = <CLIENT PRIVATE KEY HERE> # <CLIENT PUBLIC KEY HERE>
Address = 192.168.2.4/24 # Or whatever IP you want your client to use on the VPN
[Peer]
PublicKey = <SERVER PUBLIC KEY HERE>
AllowedIPs = 192.168.2.0/24 # This is the subnet you chose for your VPN, and should match the server's
Endpoint = 93.184.216.34:51820 # This is the public IP of your server, and the port you chose
# Note you can also use a domain name, if you want:
# Endpoint = example.com:51820
PersistentKeepalive = 25 # allow your client to roam without dropping the connection
chmod
the config file and the /etc/wireguard
directory to 400
and chown
it to root:root
.systemctl enable wg-quick@my-vpn
.Save
.my-vpn.conf
file, create a Peer
block following the pattern of the previous entries:[Peer] # name of client
PublicKey = <CLIENT PUBLIC KEY HERE>
AllowedIPs = 192.168.2.<n>/32 # replace `<n>` with the last octet of the Client's WireGuard private IP
root
and has permissions of 400
.systemctl enable --now wg-quick@my-vpn
to start the WireGuard tunnel and set it to start automatically on boot.Same as for the server, run systemctl enable --now wg-quick@my-vpn
Validate the VPN is running with wg
.
You should see something like this:
interface: my-vpn
public key: <CLIENT PUBLIC KEY HERE>
private key: (hidden)
listening port: 58341
peer: <SERVER PUBLIC KEY HERE>
endpoint: 93.184.216.34:51820
allowed ips: 192.168.2.0/24
latest handshake: 13 seconds ago
transfer: 5.37 MiB received, 6.40 MiB sent
persistent keepalive: every 25 seconds
If you see an error, check the logs with journalctl -u wg-quick@my-vpn
.
Save
.Network
and check the box for Enable VPN on Demand
.You should now have a working WireGuard VPN, ready for roaming and personal use. There’s only one client for now, but you can add as many as you like by repeating the client steps on each new device. (Be sure to pick a unique private IP address inside of the subnet you chose for your VPN for each client.) Then, you can jump directly from one client to another using the WireGuard private IP addresses. This can be particularly useful when pairing the WireGuard app for Android with Termux or JuiceSSH to access your laptop or desktop on the go.
Once the client side setup is done, simply add a Peer
block for each client in the server’s config file, using a unique private IP address, then run systemctl restart wg-quick@my-vpn
on the server to restart the tunnel with the new configuration.
It is normal for the tunnel to drop when you run the restart command, but it should come back up within a few seconds.
If you have any issues, check the logs with journalctl -u wg-quick@my-vpn
.
If you’re stumped, feel free to reach out to the community in my
Discord, and someone may be able to help you out.
If you want to take your WireGuard VPN to the next level, you can add a DNS server to your server’s config file, and then add a DNS
entry to each client’s Interface
block.
You can read more about that
here.
It’s possible to use WireGuard to route all of your traffic through the VPN, pair WireGuard with netns or Docker containers to force applications to use the VPN, or even use WireGuard to create a mesh network. I’ll likely be writing more about these topics in the future. For now, there are great resources available on the WireGuard website and on YouTube.
“WireGuard” and the “WireGuard” logo are registered trademarks of Jason A. Donenfeld.
Background In a recent blog post, I discussed a few of the reasons why in 2021, I began working on a new Fleet Configuration Management tool to …
Read ArticleThis post has been a long time in the making. Anyone who has followed me and my work for any period of time probably knows by know that I’ve …
Read Article