One (potential) downside to running public services on your homelab, is that you expose your IP address. That may, or may not, be a problem — but here are ways around it. The simplest way is to put Cloudflare in front, but this will only handle web traffic, and is a bit of a black box.
Another, more hands-on, approach is to use a VPS (or LXC container); WireGuard and iptables. We will create a secure tunnel between the VPS/container and the homelab HAProxy instance, and forward traffic using iptables.
User --> VPS --> Wireguard tunnel --> Haproxy --> Service
^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
Internet The homelab LAN
Table of contents
WireGuard
Server
By letting the VPS, or container, be the WireGuard server — we don’t have to open any ports on the home network.
First we need to install WireGuard:
$ sudo apt install wireguard
Then generate the private and public keys:
$ sudo -i
# cd /etc/wireguard/
# umask 077; wg genkey | tee privatekey | wg pubkey > publickey
And make the configuration:
$ sudo vim /etc/wireguard/wg0.conf
[Interface]
PrivateKey = private-key-we-generated-in-previous-step
Address = 10.0.0.1/24
ListenPort = 42295
…enable the service:
$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0
Let’s check that the interface is active:
$ sudo wg
interface: wg0
public key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
private key: (hidden)
listening port: 42295
$ sudo ip a show wg0
5: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 10.0.0.1/24 scope global wg0
valid_lft forever preferred_lft forever
Lastly: make sure your port, 42295 in this example, is open for UDP traffic.
Client
Now we need to repeat the process, but for the client.
Installing:
$ sudo apt install wireguard
Generating private and public keys:
$ umask 077; wg genkey | tee privatekey | wg pubkey > publickey
Configuring:
$ sudo vim /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.2/24
ListenPort = 42295
PrivateKey = private-key-we-generated-in-previous-step
[Peer]
PublicKey = public-key-of-the-server
AllowedIPs = 10.0.0.0/24
Endpoint = server-ip:42295
PersistentKeepalive = 15
Enable:
$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0
Check:
$ sudo wg
$ sudo ip a show wg0
Now we need to add the client public key to the server configuration, to allow the client to connect:
$ sudo vim /etc/wireguard/wg0.conf
# existing server configuration
[Peer]
PublicKey = public-key-of-the-client
AllowedIPs = 10.0.0.2/24
You should now have a tunnel between your local HAProxy and the VPS, the next step is to forward some traffic through it.
iptables
On the server (VPS/container) — we need to define some rules to forward traffic though our WireGuard tunnel:
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:80
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 10.0.0.2:443
$ sudo iptables -t nat -A POSTROUTING -j MASQUERADE
This will route traffic on TCP port 80 and 443 to IP 10.0.0.2, which is our WireGuard client.
iptables rules are not restored on boot, but there are ways to do this: https://www.cyberciti.biz/faq/how-to-save-iptables-firewall-rules-permanently-on-linux/
I used iptables-persistent
.
Enabling packet forwarding:
$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
/etc/sysctl.conf
. Look for net.ipv4.ip_forward
.
Wrapping up
Any incoming traffic on our VPS, or container, on port 80 or 443 — will now be forwarded through the WireGuard tunnel to the HAProxy instance in our homelab.
This will work for all TCP and UDP ports, just change your iptables rules accordingly.
Instead of iptables; it is also possible to use HAProxy. This has some advantages, and some drawbacks:
HAProxy > iptables:
- SSL termination
- Forward IPv6 traffic to IPv4
- Hostname based rules
iptables > HAProxy:
- Simpler configuration
- Can forward UDP packages
I chose iptables because I’d like all the configuration to be done on my homelab HAProxy, and I needed to forward UDP packages.
Last commit 2024-11-11, with message: Add lots of tags to posts.