Accessing a subnet that is behind a WireGuard client using a site-to-site setup
We want to access a local subnet remotely, but it is behind a NAT firewall and we can't setup port forwarding. Outgoing connections work, but all incoming connections get DROPPED by the ISP's routing policy.
We'll create a site-to-site connection with WireGuard allowing us to access the local subnet on a remote device (smartphone, in this example) by connecting through a cloud server in the middle.
First let's define our three hosts. They all have WireGuard installed.
A
the Linux machine on the local subnet, behind the NAT/firewall
B
the Linux cloud server (VPS, like an Amazon EC2 instance)
C
a third WireGuard client; a smartphone in this example
The [RASPI]'s /etc/wireguard/wg0-client.conf
:
[Interface]
Address = 10.0.25.10/32
PrivateKey = <[RASPI] PRIVATE-KEY>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = <PUBLIC KEY OF [VPS]>
Endpoint = host-b-fqdn.tld:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25 # to keep connections alive across NAT
Here's what we need to add to [RASPI]'s iptables
rules, expressed as the commands you would use to ADD them:
# iptables -A FORWARD -i wg0-client -j ACCEPT
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Finally, we need to make sure IP forwarding is enabled in [RASPI]'s kernel:
$ sysctl net.ipv4.ip_forward=1
And also it helps to add the correct routes to /etc/dhcpcd.exit-hook
for some of the other subnets:
ip route add 192.168.12.0/24 via 192.168.25.1 dev eth0 proto static
ip route add 192.168.40.0/24 via 192.168.25.1 dev eth0 proto static
Enable it on boot:
sudo systemctl enable wg-quick@wg0
Restart after config changes:
sudo wg-quick down wg0; sudo wg-quick up wg0
[VPS]'s /etc/wireguard/wg0.conf
:
[Interface]
Address = 10.0.25.1/24
PrivateKey = <[VPS] PRIVATE KEY>
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
# This is the peer that is on the private subnet that we want to access.
#
# Notice the AllowedIPs... without this part, WireGuard will drop the
# packets destined for the [RASPI] subnet. AllowedIPs is acting like
# a routing table and ACL here.
[Peer]
PublicKey = <[RASPI] PUBLIC KEY>
AllowedIPs = 10.0.25.10/32, 192.168.25.0/24, 192.168.40.0/24, 192.168.12.1/32
[Peer] # COVI
PublicKey = <[COVI] PUBLIC KEY>
AllowedIPs = 10.0.25.25/32
[Peer]
PublicKey = <Additional peer pubkey>
AllowedIPs = 10.0.25.4/32
Like we did with [MIKROS], IP forwarding must also be enabled on [VPS]:
$ sysctl net.ipv4.ip_forward=1
[COVI]'s configuration file:
[Interface]
PrivateKey = <[COVI] PRIVATE KEY>
Address = 10.0.25.25/32
[Peer]
PublicKey = <[VPS] PUBLIC KEY>
AllowedIPs = 10.0.25.0/24, 192.168.25.0/24, 192.168.40.0/24, 192.168.12.0/24
# AllowedIPs = 0.0.0.0/0 # Choose this if you want to send *all* traffic. Otherwise just send the stuff that should be local.
Endpoint = host-b-fqdn.tld:51820
PersistentKeepalive = 25
You're finished.
Make sure WireGuard is running on both HOSTS A and B, and then on the smartphone ([COVI]), after connecting to [VPS] with WireGuard you should be able to ping 10.0.25.10
.