diff options
author | Matt Dunwoodie <ncon@noconroy.net> | 2021-04-19 00:48:09 +1000 |
---|---|---|
committer | Matt Dunwoodie <ncon@noconroy.net> | 2021-04-19 10:54:24 +1000 |
commit | 7d6056cff84695ac44f70ad4858e01a0bf4dce8c (patch) | |
tree | 72ebc64a9569d310d1cb0c3e626a7a05519905c7 | |
parent | if_wg: replace wg_tag with wg_packet (diff) | |
download | wireguard-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.c | 8 |
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 " |