Introduction
With the IPv4 address space depletion, many ISPs have resorted to CGNAT and the assignment of a private IP address instead of giving their residential customers a public one. This presents a problem for those who want to self host their own services out of their home. Fortunately, WireGuard can help to solve this problem by establishing a VPN tunnel between a host on your network and a VPS with a public IP address. In effect, the VPS becomes the entry point for the service(s) that you wish to host.
You do not need a particularly powerful VPS in order to do this. I use Cloudfanatic and they have a low end VPS with 1GB of RAM and 30GB of storage space for $2.99 a month which is plenty. This guide is written for users of Alma Linux so your distro may vary some. You will need to have some sort of reverse proxy running on your VPS to redirect traffic to the service you are hosting. Setting up the reverse proxy is beyond the scope of this article and will be for a future one.
Setting Up The VPS
Prior to configuring WireGuard, we have some Linux-based configuration to do to ensure the tunnel can be established and proper IP forwarding happens. The first step is setting Linux up for IP forwarding. This will turn IP forwarding on and set it permanently on.
# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf# sysctl net.ipv4.ip_forward=1
Now we have to open up port 51820/udp on the firewall. This will vary depending on your Linux distro. Red Hat and Fedora-based distros use firewall-cmd. Alma Linux uses firewall-cmd.
# firewall-cmd --zone=public --add-port 51820/udp --permanent# firewall-cmd --reload
Once the firewall port is open, we have to install the wireguard-tools package. Follow the steps below to install this set of tools.
# dnf install epel-release# dnf install wireguard-tools
Now it is time to actually begin the configuration of WireGuard itself. The first phase is generating the keys. While not strictly necessary, I do recommend using the additional security of a pre-shared key.
# cd /etc/wireguard# wg genkey | tee privkey | wg pubkey > pubkey# openssl rand -base64 32 > presharedkey
Create the wg0.conf
file which will contain the WireGuard tunnel configuration. I use the 192.168.254.0/24
address but you could use any private addressing scheme that you want. Substitute ens3 with the network interface of your VPS.
[Interface]PrivateKey = <private_key>Address = 192.168.254.1/24ListenPort = 51820PostUp = iptables -I FORWARD 1 -i wg0 -j ACCEPTPostUp = iptables -I FORWARD 2 -o wg0 -j ACCEPTPostDown = iptables -D FORWARD -i wg0 -j ACCEPTPostDown = iptables -D FORWARD -o wg0 -j ACCEPT[Peer]PublicKey = <public_key>PresharedKey = <prehsared_key>AllowedIPs = 192.168.254.2/32
The next step is to enable and start the WireGuard service. When the WireGuard service gets started, the firewall rules specific to WireGuard forwarding will automatically get created. Similarly, the rules will get removed when the WireGuard service is stopped.
# systemctl enable --now [email protected]
Once you have started WireGuard, do a quick check to make certain that the tunnel interface, wg0
, has been created. You should get something similar to what you see below.
# ip address show wg03: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 link/none inet 192.168.254.1/32 scope global wg0 valid_lft forever preferred_lft forever
Linux Host
Once the VPS has been configured, it is on to the Linux host in your home. I also happen to be using Alma Linux to run my self hosted services so this will heavily reflect Red Hat and Fedora-based distros. First, we have to enable IP forwarding similarly to the VPS.
# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf# sysctl net.ipv4.ip_forward=1
Similar to the VPS, we must install the wireguard-tools package.
# dnf install epel-release# dnf install wireguard-tools
The next step is creating the keys for the Linux host.
# cd /etc/wireguard# wg genkey | tee privkey | wg pubkey > pubkey# openssl rand -base64 32 > presharedkey
Create the wg0.conf
file.
[Interface]PrivateKey = <private_key>Address = 192.168.254.2/24MTU = 1420[Peer]PublicKey = <public_key>PresharedKey = <preshared_key>Endpoint = <VPS_IP>:51820AllowedIPs = 192.168.254.1/32PersistentKeepalive = 25
Enable and start WireGuard.
# systemctl enable --now [email protected]
Verify that the tunnel has been created.
# ip address show wg03: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 link/none inet 192.168.254.1/32 scope global wg0 valid_lft forever preferred_lft forever
Once we have verified that the tunnel has been created, we can now check to see if the handshake was successful by doing the following. Typing wg
brings up the WireGuard status. If it was successful, you’ll see something similar to the following:
# wginterface: wg0 public key: <public_key> private key: (hidden) listening port: 50209peer: <peer_public_key> preshared key: (hidden) endpoint: <VPS_IP>:51820 allowed ips: 192.168.254.1/32 latest handshake: 1 minute, 13 seconds ago transfer: 359.71 MiB received, 2.50 GiB sent persistent keepalive: every 25 seconds
Try pinging the VPS via its WireGuard IP address. You should see something similar to what is shown below:
# ping 192.168.254.1PING 192.168.254.1 (192.168.254.1) 56(84) bytes of data.64 bytes from 192.168.254.1: icmp_seq=1 ttl=64 time=17.2 ms64 bytes from 192.168.254.1: icmp_seq=2 ttl=64 time=17.1 ms64 bytes from 192.168.254.1: icmp_seq=3 ttl=64 time=18.0 ms64 bytes from 192.168.254.1: icmp_seq=4 ttl=64 time=27.4 ms64 bytes from 192.168.254.1: icmp_seq=5 ttl=64 time=20.3 ms64 bytes from 192.168.254.1: icmp_seq=6 ttl=64 time=53.4 ms64 bytes from 192.168.254.1: icmp_seq=7 ttl=64 time=19.0 ms^C--- 192.168.254.1 ping statistics ---7 packets transmitted, 7 received, 0% packet loss, time 6009msrtt min/avg/max/mdev = 17.134/24.650/53.448/12.207 ms
Conclusion
It is important to note that this is purely a point-to-point tunnel between your home Linux host and your VPS. This is the foundation of setting up your services to make them accessible to the public. As I mentioned before, you will need a reverse proxy like NGINX installed and configured on the VPS and you will reference 192.168.254.2
as the destination for the proxy redirect.