2

This summarizes what I want to achieve:

Phone (192.168.1.245) -> Raspberry Pi 1 (wg0 10.8.0.3, wlan0 192.168.1.174) -> VPS (wg0 10.8.0.1 VPN Server) -> Raspberry Pi 2 (wg0 10.8.0.110, wlan0 192.168.0.8) -> Internet

I want the connections made by Phone use the Raspberry Pi 1 as gateway. The packets should be routed to Raspberry Pi 2 over the 10.8.0.0/24 network. Then it should be NATed to the internet so that Phone think it has the public IP Address of Raspberry Pi 2 (wlan0 is the WAN interface). At first I thought I needed iptables and tried the following:

PREROUTING
-i wlan0 -s 192.168.1.0/24 -j DNAT --to-destination 10.8.0.110
FORWARD
-i wlan0 -s 192.168.1.0/24 -d 10.8.0.110/32 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
-i wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT
POSTROUTING
-o wg0 -d 10.8.0.110/32 -j SNAT --to-source 10.8.0.3

For the Raspberry Pi 1. The VPS had the following:

FORWARD -s 10.8.0.0/24 -d 10.8.0.0/24 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

But then I realized those packets arrive at 10.8.0.110 thinking it was the final destination, that is why I was receiving connection refused when testing something like telnet google.com 443

Then I tried the following for Raspberry Pi 1:

FORWARD
-i wlan0 -o wg0 -j ACCEPT
-i wg0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT

and VPS:

FORWARD
-i wg0 -s 192.168.1.0/24 -o wg0 -j ACCEPT
-i wg0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT

And those packets are not reaching Raspberry Pi 2 either.

With the help of GPT4 I checked I could use Policy Based Routing adding IP rules and routes. My understanding is that the packets that arrive at Raspberry Pi 1 over 192.168.1.0/24 should be routed directly to 10.8.0.110 without altering the destination address. GPT4 suggested the following:

# Create a new routing table
echo "200 custom" >> /etc/iproute2/rt_tables
# Add a rule to use this table for traffic from 192.168.1.0/24
ip rule add from 192.168.1.0/24 lookup custom
# Add a route in the custom table to forward traffic to 10.8.0.110
ip route add default via 10.8.0.110 dev wg0 table custom

It did not work and for some reason made the Raspberry Pi 1 ssh connection very laggy.

These are the Raspberry Pi 1 routes:

default via 192.168.1.1 dev wlan0 proto dhcp src 192.168.1.174 metric 600 
10.8.0.0/24 dev wg0 proto kernel scope link src 10.8.0.3 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.18.0.0/16 dev br-352622acd722 proto kernel scope link src 172.18.0.1 
172.19.0.0/16 dev br-e7d4e060a024 proto kernel scope link src 172.19.0.1 
172.20.0.0/16 dev br-b97d3a35bbf0 proto kernel scope link src 172.20.0.1 
192.168.0.0/24 via 192.168.1.1 dev wlan0 proto static metric 600 
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.174 metric 600 

At this point I am not sure what to try since I am not a networking expert. Thanks in advance for some advice.

PS: The Raspberry Pi 1 and VPS have docker containers running, there are iptables rules for docker configured. I think that should not interfere.

asked Nov 7, 2024 at 9:47
11
  • Mainly you need to have AllowedIPs=0.0.0.0/0 under the [Peer] section for the right side of -> in the config on the left side of that for each ->. (Because the phone isn't part of the WG network, what you need would be just the default gateway being the Pi1.) So you need to have that on Pi1 for VPS and on VPS for Pi2). But because you may not want the the two left use the two right as their own respective "default gateway", especially not VPS since it is probably the "server", you'd need to use Table=off on them as well and configure policy routing for the VPN traffics. Commented Nov 7, 2024 at 10:16
  • @TomYan I have AllowedIPs = 10.8.0.3/32 for the Pi 1 and AllowedIPs = 10.8.0.110/32 for the Pi 2 on the VPS. Pi1 has aalready 0.0.0.0/0. You mean I should set also 0.0.0.0/0 for Pi1 on VPS and in Pi2 for VPS? can you please explain Table=off further? Commented Nov 7, 2024 at 10:38
  • No, what you need additionally is AllowedIPs=0.0.0.0/0 on the VPS for Pi 2 (like you have it already on Pi1 for the VPS). And you should NOT have that on Pi 2 for the VPS, for the record. Because you want to route/forward traffics destined at "the Internet" along the path, when any "next" node along the path is WG node, you need to have AllowedIPs=0.0.0.0/0 for the "next" node on the corresponding "this" node, you see the sense? Commented Nov 7, 2024 at 12:03
  • AllowedIPs= lines in a WG conf have (at least) two purpose/meaning. The first being a "guide" for WG to determine which peer should traffics for certain destinations be sent to, like of like a static CAM table in a switch. The second being instruction for WG to add routes to the system route table, so that traffics for any destinations covered by the lines would be routed to the WG interface, obviously. Commented Nov 7, 2024 at 12:10
  • However, as mentioned before, because the main system route table is by default "shared" by traffics from any origin. When you e.g. want a different route / route table to apply to traffics from only certain origin (like from the WG interface but not the host itself or other intetfaces), you would need to customize routing policy and have one that looks up an alternate route table, with e.g. default route that is different from the main table. And Table=off is the way to suppress WG from doing things for you. Commented Nov 7, 2024 at 12:13

2 Answers 2

1

I could finally solve it. This is how I did it with the help of Tom Yan's comments:

Raspberry Pi This is the gateway the phone uses. I set a static IP for the phone too.

iptables

iptables -A FORWARD -s 192.168.1.245/32 -i wlan0 -o wg0 -j ACCEPT
iptables -A FORWARD -d 192.168.1.245/32 -i wg0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
iptables -t nat -A POSTROUTING -s 192.168.1.245/32 -o wg0 -j MASQUERADE

ip rules with custom table

ip rule add from 192.168.1.245 lookup phone_vpn
ip route add default via 10.8.0.110 dev wg0

VPS

iptables

iptables -A FORWARD -s 10.8.0.3/32 -i wg0 -o wg0 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT 
iptables -A FORWARD -s 0.0.0.0/0 -i wg0 -o wg0 -d 10.8.0.3 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t mangle -A PREROUTING -s 10.8.0.3/32 -j MARK --set-xmark 1

ip rules and custom table

ip rule add fwmark 1 table phone_route
ip route add default via 10.8.0.110 dev wg0 table phone_route

Raspberry Pi 2

iptables

iptables -A FORWARD -i wg0 -o wlan0 -j ACCEPT 
iptables -A FORWARD -i wlan0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

Raspberry Pi 1 has AllowedIPs = 0.0.0.0/0 for VPS and so does VPS have for Raspberry Pi 2. Raspberry Pi 2 has AllowedIPs = 10.8.0.0/24 The wireguard configurations need to have Table = off

answered Nov 8, 2024 at 22:19
1

I am going to assume you have two sites:

  • Site 1: Contains Pi 1 and has an internet router with internal IP 192.168.1.1
  • Site 2: Contains Pi 2 and has an internet router with internal IP 192.168.0.1

If you have TOTAL control over the routing on both Pi's and both internet routers and control of DHCP on Site 1 you can do this without any "additional" NAT (given that both internet routers are already NAT'ing).

Specifically you need to:

  • Ensure packet forwarding is turned on, on both Pi's
  • Update the default gateway issued to the phone (via DHCP) to be that of Pi 1 - 192.168.1.174
  • On Pi 1 add an explicit route for the WG endpoint via 192.168.1.1 (this is needed to setup the WG tunnel - hence the target IP is probably the public IP of Site 2)
  • Change the default route on Pi 1 to go via the tunnel: 10.8.0.110
  • -- That gets packets out, then to get them back in --
  • Add a route on the internet router of site 2 for 192.168.1.0/24 via Pi 2 (192.168.0.8)
  • Add a route on Pi 2 for 192.168.1.0/24 via Pi 1 WG (10.8.0.3)

TL;DR

  • The phone sends all its traffic to Pi 1
  • Pi 1 sends all its traffic via the tunnel to Pi2 (except for the tunnel itself).
  • The router at site 2 knows to use the tunnel to gets packets back to Site 1
  • NAT'ing is handled by the internet router at site 2.

EDIT: As a result of Tom Yan's comments I have verified the syntax of the ip route add commands.

  • When specifying a LAN route you would need to specify the next hop router, i.e. ip route add 192.168.1.0/24 via 192.168.0.8
  • However for VPN routes the packet simply has to be routed to the correct interface, for example: ip route add default dev wg0

You could add additional NAT to this setup, but thats only needed if:

  • You don't have control over DHCP / being able to set default route on the phone.
  • The routers are crippled and can't handle multiple internal subnets (somewhat common on home gear).

NOTE: If you have something like OpenWRT on your routers and use them for your VPN endpoints and NAT'ing this setup becomes much simpler, I had to jump through a lot of extra hoops in this setup, because of the extra devices (Pi + routers) at both sites.

PS I did't include any IP tables rules in this answer, because none were needed the whole thing was done with routing.

answered Nov 7, 2024 at 11:00
2
  • Change the default route on Pi 1 to go via the tunnel: 10.8.0.110 Add a route on Pi 2 for 192.168.1.0/24 via Pi 1 WG (10.8.0.3) Either you didn't notice that the Pis aren't directly connected (i.e., they aren't and probably can't be an Endpoint= for each other), or you don't really know how L3 VPN works ("via some_ip" is a (real) thing only when the gateway/nexthop of the route can/will be resolved with e.g. ARP, which is not the case of L3 VPN). Commented Nov 7, 2024 at 21:24
  • Nope. I don't know if you need it on like BSDs or ancient versions of Linux distros though, and the point is, even when you see e.g. OpenVPN would add routes like that, it doesn't mean that the via part has any actual effect (but certainly that's talking about tun mode). Even when you use client-to-client, what you actually need, and what only matters, is iroute on the server, which is pretty much like AllowedIPs= in WG. Commented Nov 8, 2024 at 5:55

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.