Wireguard tunnel for self-hosting
use wireguard to tunnel an external ip to a machine in your LAN
July 15, 2020
sysadmin
wireguard
vpn
self hosting
So you want to self host ?
Finally decided to stop renting servers and have your own platform at home ? Possibly on an old PC, or a tiny SBC ( raspberry, orange pi, etc… ? )
In this article, I am not going to explain how to setup your server at home, but rather quickly outline how to use a wireguard VPN to mask your home public ip, and provide you with a fixed ip for external services. It also is useful if you self host your email, avoiding being flagged as spam because of a residential ip.
Prerequisites:
- 1 cheap vps somewhere.
- 1 server at home.
Global steps:
- Install wireguard on both servers.
- Configure wireguard on both servers
On the cheap vps:
/etc/wireguard/wg0.conf:
[Interface]
PrivateKey = VPSPRIVATEKEY
ListenPort = 3456
Address = 10.100.100.1/24,fd10:100:100::1/64
PostUp = /etc/wireguard/tunnel.sh up
PostDown = /etc/wireguard/tunnel.sh down
[Peer]
PublicKey = PEERPUBLICKEY
PersistentKeepalive = 25
AllowedIPs = 10.100.100.20/32,fd10:100:100::20/128
/etc/wireguard/tunnel.sh:
#!/bin/bash
if [ "$1" = "up" ]; then
# global routing config
iptables -I FORWARD 1 -i wg0 -j ACCEPT;
ip6tables -I FORWARD 1 -i wg0 -j ACCEPT;
iptables -t nat -I POSTROUTING 1 -o VPSPUBLICIFACE -j MASQUERADE;
ip6tables -t nat -I POSTROUTING 1 -o VPSPUBLICIFACE -j MASQUERADE;
echo 1 > /proc/sys/net/ipv4/ip_forward;
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding;
# Setup NAT for ports to redirect to the self hosted box by hand
iptables -I PREROUTING 1 -t nat -i VPSPUBLICIFACE -p tcp --dport 6482 -j DNAT --to 10.100.100.20:6482
iptables -I PREROUTING 1 -t nat -i VPSPUBLICIFACE -p udp --dport 6482 -j DNAT --to 10.100.100.20:6482
iptables -I FORWARD 1 -p tcp -d 10.100.100.20 --dport 6482 -j ACCEPT
iptables -I FORWARD 1 -p udp -d 10.100.100.20 --dport 6482 -j ACCEPT
# Or do a bunch of ports in batch
for port in {8,4897,4546,80,443}; do
iptables -I PREROUTING 1 -t nat -i VPSPUBLICIFACE -p tcp --dport $port -j DNAT --to 10.100.100.20:$port
iptables -I FORWARD 1 -p tcp -d 10.100.100.20 --dport $port -j ACCEPT
done
elif [ "$1" = "down" ]; then
# Undo specific NAT
iptables -D PREROUTING -t nat -i VPSPUBLICIFACE -p tcp --dport 6482 -j DNAT --to 10.100.100.20:6482
iptables -D PREROUTING -t nat -i VPSPUBLICIFACE -p udp --dport 6482 -j DNAT --to 10.100.100.20:6482
iptables -D FORWARD -p tcp -d 10.100.100.20 --dport 6482 -j ACCEPT
iptables -D FORWARD -p udp -d 10.100.100.20 --dport 6482 -j ACCEPT
for port in {8,4897,4546,80,443}; do
iptables -D PREROUTING -t nat -i VPSPUBLICIFACE -p tcp --dport $port -j DNAT --to 10.100.100.20:$port
iptables -D FORWARD -p tcp -d 10.100.100.20 --dport $port -j ACCEPT
done
# Undo global routing config
iptables -D FORWARD -i wg0 -j ACCEPT;
ip6tables -D FORWARD -i wg0 -j ACCEPT;
iptables -t nat -D POSTROUTING -o VPSPUBLICIFACE -j MASQUERADE;
ip6tables -t nat -D POSTROUTING -o VPSPUBLICIFACE -j MASQUERADE;
fi
On the server at home:
/etc/wireguard/wg0.conf:
[Interface]
PrivateKey = PEERPRIVATEKEY
Address = 10.100.100.20/32,fd10:100:100::20/128
Table = off
PostUp = /etc/wireguard/tunnel.sh up
PostDown = /etc/wireguard/tunnel.sh down
[Peer]
PublicKey = VPSPUBLICKEY
Endpoint = VPSPUBLICIP:3456
AllowedIPs = 0.0.0.0/0,::/0
PersistentKeepalive = 21
/etc/wireguard/tunnel.sh:
#!/bin/bash
if [ "$1" = "up" ]; then
# add vpn net routes
ip route add 10.100.100.0/24 dev wg0
ip -6 route add fd10:100:100::/56 dev wg0
# add any local route that could be useful since default gateway will change
route add -net 192.168.0.0/24 gw 10.0.0.1
# we are going to mark the traffic and use a different table
# this will allow to route req coming from the lan interface to go back through it
# ( think if you want to route some things through the vpn OR your local LAN ip )
wg set wg0 fwmark 100
ip route add default dev wg0 table 100
ip -6 route add default dev wg0 table 100
# now let's mark packets coming from the LAN iface
# Set the LAN mark LOCALIFACE = eth0 for example
iptables -I PREROUTING 1 -t mangle -i LOCALIFACE -j MARK --set-mark 10
iptables -I PREROUTING 2 -t mangle -i LOCALIFACE -j CONNMARK --save-mark
iptables -I OUTPUT 1 -t mangle -j CONNMARK --restore-mark
iptables -I POSTROUTING 1 -t mangle -j CONNMARK --restore-mark
ip6tables -I PREROUTING 1 -t mangle -i LOCALIFACE -j MARK --set-mark 10
ip6tables -I PREROUTING 2 -t mangle -i LOCALIFACE -j CONNMARK --save-mark
ip6tables -I OUTPUT 1 -t mangle -j CONNMARK --restore-mark
ip6tables -I POSTROUTING 1 -t mangle -j CONNMARK --restore-mark
# and now set the default routes to use depending on the fw mark
ip rule add table main suppress_prefixlength 0 priority 99
ip rule add fwmark 10 table main priority 100
ip rule add not fwmark 100 table 100 priority 101
ip -6 rule add table main suppress_prefixlength 0 priority 99
ip -6 rule add fwmark 10 table main priority 100
ip -6 rule add not fwmark 100 table 100 priority 101
elif [ "$1" = "down" ]; then
# let's tear down everything
ip route del 10.100.100.0/24 dev wg0
ip -6 route del fd10:100:100::/56 dev wg0
ip route flush table 100
ip -6 route flush table 100
ip rule del not fwmark 100 table 100
ip rule del fwmark 10 table main
ip rule del table main suppress_prefixlength 0
ip -6 rule del not fwmark 100 table 100
ip -6 rule del fwmark 10 table main
ip -6 rule del table main suppress_prefixlength 0
iptables -D PREROUTING -t mangle -i LOCALIFACE -j MARK --set-mark 1
iptables -D PREROUTING -t mangle -i LOCALIFACE -j CONNMARK --save-mark
iptables -D OUTPUT -t mangle -j CONNMARK --restore-mark
iptables -D POSTROUTING -t mangle -j CONNMARK --restore-mark
ip6tables -D PREROUTING -t mangle -i LOCALIFACE -j MARK --set-mark 1
ip6tables -D PREROUTING -t mangle -i LOCALIFACE -j CONNMARK --save-mark
ip6tables -D OUTPUT -t mangle -j CONNMARK --restore-mark
ip6tables -D POSTROUTING -t mangle -j CONNMARK --restore-mark
fi
Last steps:
- restart wg-quick@wg0 on each server
- check pings etc…
- enjoy :)
Conclusion:
This is a simple setup to forward some ports from a cheap machine to a server in your local lan. Of course this does NOT cover LAN isolation at home, your home firewall, the general firewall of the VPS, or even using NGINX as a proxy on the cheap VPS to terminate services locally on forward to your home server ( which should make for an other article ).
This setup will allow your home server to route everything by default through the wireguard vpn, but to also respond via the LAN interface when requests are received through it.