Skip to content

Commit b673e24

Browse files
zx2c4davem330
authored andcommitted
wireguard: socket: remove errant restriction on looping to self
It's already possible to create two different interfaces and loop packets between them. This has always been possible with tunnels in the kernel, and isn't specific to wireguard. Therefore, the networking stack already needs to deal with that. At the very least, the packet winds up exceeding the MTU and is discarded at that point. So, since this is already something that happens, there's no need to forbid the not very exceptional case of routing a packet back to the same interface; this loop is no different than others, and we shouldn't special case it, but rather rely on generic handling of loops in general. This also makes it easier to do interesting things with wireguard such as onion routing. At the same time, we add a selftest for this, ensuring that both onion routing works and infinite routing loops do not crash the kernel. We also add a test case for wireguard interfaces nesting packets and sending traffic between each other, as well as the loop in this case too. We make sure to send some throughput-heavy traffic for this use case, to stress out any possible recursion issues with the locks around workqueues. Fixes: e7096c1 ("net: WireGuard secure network tunnel") Signed-off-by: Jason A. Donenfeld <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a0fd7cc commit b673e24

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

drivers/net/wireguard/socket.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,6 @@ static int send4(struct wg_device *wg, struct sk_buff *skb,
7676
net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n",
7777
wg->dev->name, &endpoint->addr, ret);
7878
goto err;
79-
} else if (unlikely(rt->dst.dev == skb->dev)) {
80-
ip_rt_put(rt);
81-
ret = -ELOOP;
82-
net_dbg_ratelimited("%s: Avoiding routing loop to %pISpfsc\n",
83-
wg->dev->name, &endpoint->addr);
84-
goto err;
8579
}
8680
if (cache)
8781
dst_cache_set_ip4(cache, &rt->dst, fl.saddr);
@@ -149,12 +143,6 @@ static int send6(struct wg_device *wg, struct sk_buff *skb,
149143
net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n",
150144
wg->dev->name, &endpoint->addr, ret);
151145
goto err;
152-
} else if (unlikely(dst->dev == skb->dev)) {
153-
dst_release(dst);
154-
ret = -ELOOP;
155-
net_dbg_ratelimited("%s: Avoiding routing loop to %pISpfsc\n",
156-
wg->dev->name, &endpoint->addr);
157-
goto err;
158146
}
159147
if (cache)
160148
dst_cache_set_ip6(cache, dst, &fl.saddr);

tools/testing/selftests/wireguard/netns.sh

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,11 @@ cleanup() {
4848
exec 2>/dev/null
4949
printf "$orig_message_cost" > /proc/sys/net/core/message_cost
5050
ip0 link del dev wg0
51+
ip0 link del dev wg1
5152
ip1 link del dev wg0
53+
ip1 link del dev wg1
5254
ip2 link del dev wg0
55+
ip2 link del dev wg1
5356
local to_kill="$(ip netns pids $netns0) $(ip netns pids $netns1) $(ip netns pids $netns2)"
5457
[[ -n $to_kill ]] && kill $to_kill
5558
pp ip netns del $netns1
@@ -77,18 +80,20 @@ ip0 link set wg0 netns $netns2
7780
key1="$(pp wg genkey)"
7881
key2="$(pp wg genkey)"
7982
key3="$(pp wg genkey)"
83+
key4="$(pp wg genkey)"
8084
pub1="$(pp wg pubkey <<<"$key1")"
8185
pub2="$(pp wg pubkey <<<"$key2")"
8286
pub3="$(pp wg pubkey <<<"$key3")"
87+
pub4="$(pp wg pubkey <<<"$key4")"
8388
psk="$(pp wg genpsk)"
8489
[[ -n $key1 && -n $key2 && -n $psk ]]
8590

8691
configure_peers() {
8792
ip1 addr add 192.168.241.1/24 dev wg0
88-
ip1 addr add fd00::1/24 dev wg0
93+
ip1 addr add fd00::1/112 dev wg0
8994

9095
ip2 addr add 192.168.241.2/24 dev wg0
91-
ip2 addr add fd00::2/24 dev wg0
96+
ip2 addr add fd00::2/112 dev wg0
9297

9398
n1 wg set wg0 \
9499
private-key <(echo "$key1") \
@@ -230,9 +235,38 @@ n1 ping -W 1 -c 1 192.168.241.2
230235
n1 wg set wg0 private-key <(echo "$key3")
231236
n2 wg set wg0 peer "$pub3" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32 peer "$pub1" remove
232237
n1 ping -W 1 -c 1 192.168.241.2
238+
n2 wg set wg0 peer "$pub3" remove
239+
240+
# Test that we can route wg through wg
241+
ip1 addr flush dev wg0
242+
ip2 addr flush dev wg0
243+
ip1 addr add fd00::5:1/112 dev wg0
244+
ip2 addr add fd00::5:2/112 dev wg0
245+
n1 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk") allowed-ips fd00::5:2/128 endpoint 127.0.0.1:2
246+
n2 wg set wg0 private-key <(echo "$key2") listen-port 2 peer "$pub1" preshared-key <(echo "$psk") allowed-ips fd00::5:1/128 endpoint 127.212.121.99:9998
247+
ip1 link add wg1 type wireguard
248+
ip2 link add wg1 type wireguard
249+
ip1 addr add 192.168.241.1/24 dev wg1
250+
ip1 addr add fd00::1/112 dev wg1
251+
ip2 addr add 192.168.241.2/24 dev wg1
252+
ip2 addr add fd00::2/112 dev wg1
253+
ip1 link set mtu 1340 up dev wg1
254+
ip2 link set mtu 1340 up dev wg1
255+
n1 wg set wg1 listen-port 5 private-key <(echo "$key3") peer "$pub4" allowed-ips 192.168.241.2/32,fd00::2/128 endpoint [fd00::5:2]:5
256+
n2 wg set wg1 listen-port 5 private-key <(echo "$key4") peer "$pub3" allowed-ips 192.168.241.1/32,fd00::1/128 endpoint [fd00::5:1]:5
257+
tests
258+
# Try to set up a routing loop between the two namespaces
259+
ip1 link set netns $netns0 dev wg1
260+
ip0 addr add 192.168.241.1/24 dev wg1
261+
ip0 link set up dev wg1
262+
n0 ping -W 1 -c 1 192.168.241.2
263+
n1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7
264+
ip2 link del wg0
265+
ip2 link del wg1
266+
! n0 ping -W 1 -c 10 -f 192.168.241.2 || false # Should not crash kernel
233267

268+
ip0 link del wg1
234269
ip1 link del wg0
235-
ip2 link del wg0
236270

237271
# Test using NAT. We now change the topology to this:
238272
# ┌────────────────────────────────────────┐ ┌────────────────────────────────────────────────┐ ┌────────────────────────────────────────┐
@@ -282,6 +316,20 @@ pp sleep 3
282316
n2 ping -W 1 -c 1 192.168.241.1
283317
n1 wg set wg0 peer "$pub2" persistent-keepalive 0
284318

319+
# Test that onion routing works, even when it loops
320+
n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5
321+
ip1 addr add 192.168.242.1/24 dev wg0
322+
ip2 link add wg1 type wireguard
323+
ip2 addr add 192.168.242.2/24 dev wg1
324+
n2 wg set wg1 private-key <(echo "$key3") listen-port 5 peer "$pub1" allowed-ips 192.168.242.1/32
325+
ip2 link set wg1 up
326+
n1 ping -W 1 -c 1 192.168.242.2
327+
ip2 link del wg1
328+
n1 wg set wg0 peer "$pub3" endpoint 192.168.242.2:5
329+
! n1 ping -W 1 -c 1 192.168.242.2 || false # Should not crash kernel
330+
n1 wg set wg0 peer "$pub3" remove
331+
ip1 addr del 192.168.242.1/24 dev wg0
332+
285333
# Do a wg-quick(8)-style policy routing for the default route, making sure vethc has a v6 address to tease out bugs.
286334
ip1 -6 addr add fc00::9/96 dev vethc
287335
ip1 -6 route add default via fc00::1

0 commit comments

Comments
 (0)