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.
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.