Skip to main content

Wireguard Server

Technically Wireguard is considered serverless, and each connection is called a "peer". However, in this particular setup, we will be listening for VPN connections only on our homelab server.

For setup, I opted to using the native NetworkManager integration with Wireguard. The reasoning is simply keeping network profiles managed through one system.

This process is well documented at https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_and_managing_networking/assembly_setting-up-a-wireguard-vpn_configuring-and-managing-networking. However, for thoroughness I will document the steps here.

Generate Keys

First we will login to the sudoers shell, install wireguard-tools, generate a private and public key, and set the correct permissions on those files.

This is not unlike generating SSH keys, where the public key is shared to peers.

sudo -s
dnf install wireguard-tools
wg genkey | tee /etc/wireguard/$HOSTNAME.private.key | wg pubkey > /etc/wireguard/$HOSTNAME.public.key
chmod 600 /etc/wireguard/$HOSTNAME.private.key /etc/wireguard/$HOSTNAME.public.key

We will use these keys in later steps.

warning

Keep these keys secret and safe.

Create Wireguard Profile

Now we will create a new wireguard profile in NetworkManager using nmcli, set its IPv4 and IPv6 addresses, set its wireguard private key, and define the port which we will listen to VPN connections through.

nmcli connection add type wireguard con-name server-wg0 ifname wg0 autoconnect no
nmcli connection modify server-wg0 ipv4.method manual ipv4.addresses 192.0.2.1/24
nmcli connection modify server-wg0 ipv6.method manual ipv6.addresses 2001:db8:1::1/32
nmcli connection modify server-wg0 wireguard.private-key $(cat /etc/wireguard/$HOSTNAME.private.key)
nmcli connection modify server-wg0 wireguard.listen-port 51820

This new profile will remain unconnected (autoconnect no) until we finalize setup.

This new profile is saved to a file located at /etc/NetworkManager/system-connections/server-wg0.nmconnection

Setting the MTU

One difference between NetworkManager's Wireguard integration and that of using wg-quick is that it does not take care of setting an appropriate MTU (Maximum Transmission Unit) for packets.

This potentially has impactful consequences over a limited network.

The algorithm wg-quick up uses iterates through relevant devices on your network and picks the lowest set MTU. Since wireguard introduces overhead to packets, it will set the final MTU to (lowest device MTU) - 80.

The popular default MTU for devices is 1500. So if the algorithm fails, it picks a safe MTU of 1420.

For our general case, and our utilization of a large limited public network (Google Fi mobile), we will stick with the safe MTU:

nmcli connection modify server-wg0 wireguard.mtu 1420

If you suspect issues with the MTU and dropped packets, see the #troubleshooting section.

Firewall

We will need to allow our listening port through the firewall on the specific zone that our internet-facing interface is assigned to.

In the RedHat instructions above, that was the Public zone. But in my particular case, the Public zone was not active, and my interface was assigned to the FedoraServer zone.

Using nmcli and firewall-cmd we can confirm what zone we need to open the port on:

nmcli device

DEVICE TYPE STATE CONNECTION
bridge0 bridge connected bridge0
wg0 wireguard connected server-wg0
enp1s0 ethernet connected enp1s0

We can see our Wired internet-facing ethernet connection's interface is enp1s0. Let's find the appropriate zone:

firewall-cmd --get-zone-of-interface=enp1s0
FedoraServer

firewall-cmd --list-all --zone=FedoraServer
FedoraServer (default, active)
target: default
ingress-priority: 0
egress-priority: 0
icmp-block-inversion: no
interfaces: bridge0 enp1s0
sources:
services: cockpit dhcpv6-client glances nfs ssh
ports: 61208/tcp 10000/udp
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

We see our zone is FedoraServer and we confirm that the enp1s0 interface is connected to it and we confirm that the zone is active.

Let's go ahead and open the port, and set it to be permanent so it persists on reloads:

firewall-cmd --add-port=51820/udp --zone=FedoraServer --permanent

We should also assign our Wireguard interface to the public zone, so that we can have control over traffic sent.

nmcli connection modify server-wg0 connection.zone public

Router

Router setup simply involved setting up port-forwarding for the listening port (UDP 51820) to the IP address of the homelab server.