aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@noconroy.net>2021-04-19 00:48:09 +1000
committerMatt Dunwoodie <ncon@noconroy.net>2021-04-19 10:54:24 +1000
commit7d6056cff84695ac44f70ad4858e01a0bf4dce8c (patch)
tree72ebc64a9569d310d1cb0c3e626a7a05519905c7
parentif_wg: replace wg_tag with wg_packet (diff)
downloadwireguard-freebsd-7d6056cff84695ac44f70ad4858e01a0bf4dce8c.tar.xz
wireguard-freebsd-7d6056cff84695ac44f70ad4858e01a0bf4dce8c.zip
if_wg: add packet loop detection
This is more sophisticated loop detection than OpenBSD, due to the loop detection relying on a "cookie". Each "cookie" is unique to the peer (in this case we use the peer id) and allows us to track which peers a packet has been sent to. Each time a packet hits wg_transmit, if_tunnel_check_nesting will count the number of correspinding tags (indexed by ifp, peer->p_id). If this is greater than or equal to 1 (i.e. it has been sent to this peer before), then raise an error. Currently the cookie is a uint32_t, which means the p_id gets truncated. This isn't ideal as it may cause conflicts (if a user adds 2**32 + 1 peers to an interface). However, I'm not too concerned about this for the time being because nested routing is uncommon and this is an improvement over the current situation which would likely DoS a host if a packet was sent in a nested configuration. Signed-off-by: Matt Dunwoodie <ncon@noconroy.net>
-rw-r--r--src/if_wg.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index e583f14..f089e8d 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -2172,6 +2172,14 @@ wg_transmit(struct ifnet *ifp, struct mbuf *m)
goto err;
}
+ /* Detect packet loops, TODO make better unique identifier than p_id
+ * (because it is truncated from uint64_t to uint32_t). */
+ if (__predict_false(if_tunnel_check_nesting(ifp, m, peer->p_id, 1))) {
+ DPRINTF(sc, "Packet looped");
+ rc = ELOOP;
+ goto err;
+ }
+
peer_af = peer->p_endpoint.e_remote.r_sa.sa_family;
if (__predict_false(peer_af != AF_INET && peer_af != AF_INET6)) {
DPRINTF(sc, "No valid endpoint has been configured or "