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.
2 Answers 2
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
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.
-
Change the default route on Pi 1 to go via the tunnel: 10.8.0.110Add 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 anEndpoint=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).Tom Yan– Tom Yan2024年11月07日 21:24:31 +00:00Commented 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, isirouteon the server, which is pretty much likeAllowedIPs=in WG.Tom Yan– Tom Yan2024年11月08日 05:55:31 +00:00Commented Nov 8, 2024 at 5:55
You must log in to answer this question.
Explore related questions
See similar questions with these tags.
AllowedIPs=0.0.0.0/0under 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 useTable=offon them as well and configure policy routing for the VPN traffics.AllowedIPs=0.0.0.0/0on 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 haveAllowedIPs=0.0.0.0/0for the "next" node on the corresponding "this" node, you see the sense?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.Table=offis the way to suppress WG from doing things for you.