Score:1

Route all traffic through Wireguard peer

gh flag

I have a Wireguard VPN setup that basically looks like this:

P1 ---- S ---- P ---- LAN
Px -----|
  • S (ip 192.168.60.1) is a WG server running on Ubuntu 20.04 with ufw enabled, with a public IP (using wg0 interface).
  • P (ip 192.168.60.2) is a WG peer running behind CGNAT, without a public IP, connected to its own LAN.
  • P1..Px are other WG peers (ip 192.168.60.1x).

Ufw has the following configuration:

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
51820/udp                  ALLOW       Anywhere

Anywhere on eth0           ALLOW FWD   Anywhere on wg0
Anywhere on wg0            ALLOW FWD   Anywhere on eth0
Anywhere on wg0            ALLOW FWD   Anywhere on wg0

I want to achieve that all traffic originating from P1..Px peers is routed through P.

I tried the following, but without success:

  • On P1, I set AllowedIPs for S to 0.0.0.0/0. On S I set AllowedIPs for P to 0.0.0.0/0. - This configuration renders S inaccessible through eth0 (and still doesn't route anything to P).

  • On P1, I set AllowedIPs for S to 0.0.0.0/0. On S I tried configuring policy based routing based on source IP:

     sudo ip rule add from 192.168.60.0/24 lookup 200
     sudo ip route add default via 192.168.60.2 dev wg0 table 200
    

    This prevents P1 connecting to anything other than 192.168.60.0/24.

Score:2
in flag

You should probably start with using Table=off in the wg-quick conf on both S and P. The value of AllowedIPs= will not cause changes to the routes / policy routing rules on them then.

EDIT: Actually it should be fine to leave Table= untouched on P unless you need AllowedIPs= of S on it to be 0.0.0.0/0 instead of 192.168.60.0/24 for some reasons, e.g. need traffics originates from itself to be routed S. You don't need to mess with the routes and routing rules on P yourself since even the prefix in Address=192.168.60.2/24 should get the necessary route configured. The next paragraph probably does not apply to what you need -- although it might gives you some extra insights on how things work.

And you should probably use an additional IP subnet for S and P, e.g. 192.168.59.0/30. This will save you the hassle of needing extra ip rule. Remember to add the subnet route for 192.168.60.0/24 on P though, as with Table=off, only prefix routes will be added by the kernel for the prefix(es) in the Address= field(s). Make good use of PostUp= (and PreDown=) btw.

I don't suppose you want to route traffics that originates from S itself to P, so you probably want the following ip rule instead:

# ip rule add iif wg0 from 192.168.60.0/24 lookup 200

If you really need want to route e.g. traffics other than the ssh and wireguard server replies to P, you can additionally have:

# ip rule add iif lo lookup 200
# ip rule add iif lo ipproto tcp sport 22 lookup main
# ip rule add iif lo ipproto udp sport 51820 lookup main

Note: you can't just match with from 192.168.60.1 added in the first rule and omit the other two, because for non-replying traffics, the source address is often (if not always) chosen based on the decided route -- it's not set yet at this point.

Note that the order of the command normally determines the priority, so make sure you add the "superset" rule before the "subset" rules, otherwise the latter will be overridden by the former.

Also it's best to keep table 200 empty until all the desire rules are in position, otherwise remote access of the host could be cut off.

Finally nexthop makes no sense in route to an L3 tunnel:

# ip route add default dev wg0 table 200

P.S. Make sure you didn't just allow IP forwarding in the firewall but also enable it with sysctl.

Andrija Kovačević avatar
gh flag
Thanks, for the tips - I managed to get it working with the following configuration (everything done on S): - add Table = off to wg0.conf - set AllowedIPs = 0.0.0.0/0, for P (not sure if this was actually needed) - add the following to PostUp: ip rule add iif wg0 from 192.168.60.0/24 lookup 200; ip route add default via 192.168.60.2 dev wg0 table 200; - add the following to PostDown: ip rule delete iif wg0 from 192.168.60.0/24 lookup 200; ip route delete default via 192.168.60.2 dev wg0 table 200;
Tom Yan avatar
in flag
I made some edit to the answer. See if it made things clearer to you.
Score:0
bw flag

Internet Gateway as a Spoke

We have an endpoint with WireGuard running on it, Endpoint A, from which we want to access the Internet. To get from Endpoint A to the Internet in this scenario, however, WireGuard traffic needs to go through two hops: one through the VPN hub, Host C; and the second through a spoke of the hub, Host β. However, while we want to use Host β as the Internet gateway for Endpoint A, we don’t want that for Host C — Host C itself can use the default routes at Site C to access the Internet as needed. Hub with an Internet Gateway Spoke

Details of the network used in this explanation

Within our WireGuard network, Endpoint A has an IPv4 address of 10.0.0.1 and an IPv6 address of fd10:0:0:1::1; Host C has an IPv4 address of 10.0.0.3, and an IPv6 address of fd10:0:0:3::1; and Host β has an IPv4 address of 10.0.0.2 and an IPv6 address of fd10:0:0:2::1. Host C has a public IP address of 192.0.2.3, allowing Endpoint A and Host β to each establish a WireGuard tunnel to it.

Endpoint A

On Endpoint A, when the WireGuard network is up, we want to send all Internet traffic through Host C, so we configure AllowedIPs = 0.0.0.0/0, ::/0 for Host C in Endpoint A’s WireGuard config:

# /etc/wireguard/wg0.conf

# local settings for Endpoint A
[Interface]
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=
Address = 10.0.0.1/32, fd10:0:0:1::1/64
ListenPort = 51821

# remote settings for Host C
[Peer]
PublicKey = jUd41n3XYa3yXBzyBvWqlLhYgRef5RiBD7jwo70U+Rw=
Endpoint = 192.0.2.3:51823
AllowedIPs = 0.0.0.0/0, ::/0

0.0.0.0/0 is the entire IPv4 space, and ::/0 is the entire IPv6 space. (If you don’t care about IPv6 traffic, you can omit the IPv6 addresses and address blocks from this and the other WireGuard configurations.)

Host C

On Host C, we want to send all the traffic destined for 10.0.0.1 or fd10:0:0:1::/64 to Endpoint A, and all other traffic that comes through our WireGuard network on to Host β. So we configure WireGuard on Host C with AllowedIPs = 10.0.0.1/32, fd10:0:0:1::/64 for its Endpoint A [Peer] section, and AllowedIPs = 0.0.0.0/0, ::/0 for its Host β [Peer] section.

But since we don’t want all of Host C’s traffic to go to Host β — just traffic forwarded through the WireGuard network — we configure the routes for this WireGuard interface to use a custom routing table, via the interface’s Table = 123 setting. And we use a PreUp command to add a policy routing rule that directs the host to use this table only for traffic coming in from this WireGuard interface (ip rule add iif wg0 table 123 priority 456):

# /etc/wireguard/wg0.conf

# local settings for Host C
[Interface]
PrivateKey = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCGA=
Address = 10.0.0.3/32, fd10:0:0:3::1/64
ListenPort = 51823
Table = 123

# IPv4 forwarding & routing
PreUp = sysctl -w net.ipv4.ip_forward=1
PreUp = ip rule add iif wg0 table 123 priority 456
PostDown = ip rule del iif wg0 table 123 priority 456

# IPv6 forwarding & routing
PreUp = sysctl -w net.ipv6.conf.all.forwarding=1
PreUp = ip -6 rule add iif wg0 table 123 priority 456
PostDown = ip -6 rule del iif wg0 table 123 priority 456

# remote settings for Endpoint A
[Peer]
PublicKey = /TOE4TKtAqVsePRVR+5AA43HkAK5DSntkOCO7nYq5xU=
AllowedIPs = 10.0.0.1/32, fd10:0:0:1::/64

# remote settings for Host β
[Peer]
PublicKey = fE/wdxzl0klVp/IR8UcaoGUMjqaWi3jAd7KzHKFS6Ds=
AllowedIPs = 0.0.0.0/0, ::/0

Host B

Similar to the previous Site Gateway as a Spoke scenario, on Host β, we want to send all the traffic destined for the 10.0.0.0/24 and fd10::/56 networks back through Host C — so that’s what we use as the AllowedIPs setting for Host C in Host β’s WireGuard config:

# /etc/wireguard/wg0.conf

# local settings for Host β
[Interface]
PrivateKey = ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBFA=
Address = 10.0.0.2/32, fd10:0:0:2::1/64
ListenPort = 51822

# IPv4 forwarding
PreUp = sysctl -w net.ipv4.ip_forward=1
# IPv4 masquerading
PreUp = iptables -t mangle -A PREROUTING -i wg0 -j MARK --set-mark 0x30
PreUp = iptables -t nat -A POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE
PostDown = iptables -t mangle -D PREROUTING -i wg0 -j MARK --set-mark 0x30
PostDown = iptables -t nat -D POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE

# IPv6 forwarding
PreUp = sysctl -w net.ipv6.conf.all.forwarding=1
# IPv6 masquerading
PreUp = ip6tables -t mangle -A PREROUTING -i wg0 -j MARK --set-mark 0x30
PreUp = ip6tables -t nat -A POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE
PostDown = ip6tables -t mangle -D PREROUTING -i wg0 -j MARK --set-mark 0x30
PostDown = ip6tables -t nat -D POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE

# remote settings for Host C
[Peer]
PublicKey = jUd41n3XYa3yXBzyBvWqlLhYgRef5RiBD7jwo70U+Rw=
Endpoint = 192.0.2.3:51823
AllowedIPs = 10.0.0.0/24, fd10::/56
PersistentKeepalive = 25

Note that in Host β’s configuration for Host C, we’ve also included a PersistentKeepalive = 25 setting. This ensures that Host β pokes a hole through any NAT (or egress-only) firewalls between Host C and Host β, allowing Endpoint A to initiate connections through the WireGuard network to Host β. You can omit this setting if there are no NAT or egress-only firewalls between Host C and Host β (but if you do that, make sure you instead set up Host C’s WireGuard config to include the public IP address of Host β in its Endpoint setting for Host β).

Also note that we’ve included some iptables rules in Host β’s WireGuard configuration. These iptables rules masquerade packets from the WireGuard network when Host β forwards them out to Site B. You can omit these rules if the LAN router (or each individual endpoint) at Site B is already configured to route traffic destined for the WireGuard network (10.0.0.0/24) back through Host β.

Test It Out

After starting up our configured WireGuard interfaces on each host (Endpoint A, Host C, and Host β), we can run cURL (or a regular webrowser) from Endpoint A to access Google (or any other Internet site) through our WireGuard network: `` $ curl google.com

301 Moved ... ```

Reference :

copy-pasted from https://www.procustodibus.com/blog/2022/06/multi-hop-wireguard/#internet-gateway-as-a-spoke (saved me from 2 weeks of unsuccessful search...)

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.