fix(relay): XDP_PASS non-STUN UDP traffic (#10292)

To prevent userspace relaying, all traffic that seemingly looked like
STUN/TURN but we couldn't handle via the eBPF codepath we would
`XDP_DROP`.

This turned out to be too heavy-handed of an approach since it end up
matching DNS query responses as well due to them arriving within the
TURN ephemeral port range.

To fix this, we `XDP_PASS` the traffic up the stack so that the kernel
is able to match it to existing conntrack entries.

We've identified a minor race condition where the first few channel data
packets might be dropped when a channel is first being bound, but fixing
this will be saved for a later PR.

Related: https://github.com/firezone/infra/pull/132
This commit is contained in:
Jamil
2025-09-05 16:24:02 -04:00
committed by GitHub
parent b8e0cf9b53
commit 5e0ca45c67

View File

@@ -26,6 +26,7 @@ pub fn handle_turn(ctx: aya_ebpf::programs::XdpContext) -> u32 {
| Error::InterfaceIpv6AddressAccessFailed
| Error::PacketTooShort
| Error::NotTurn
| Error::NoEntry(_)
| Error::NotAChannelDataMessage
| Error::UdpChecksumMissing
| Error::Ipv4PacketWithOptions => {
@@ -34,16 +35,18 @@ pub fn handle_turn(ctx: aya_ebpf::programs::XdpContext) -> u32 {
xdp_action::XDP_PASS
}
Error::InterfaceIpv4AddressNotConfigured
| Error::PacketLoop
| Error::NoEntry(_)
| Error::InterfaceIpv6AddressNotConfigured => {
// TODO: Remove this when same-host relay-relay is supported.
Error::PacketLoop => {
debug!(&ctx, "Dropping packet: {}", e);
xdp_action::XDP_DROP
}
Error::BadChannelDataLength | Error::XdpAdjustHeadFailed(_) => {
// These are exceptions and shouldn't happen in practice - WARN.
Error::BadChannelDataLength
| Error::InterfaceIpv4AddressNotConfigured
| Error::InterfaceIpv6AddressNotConfigured
| Error::XdpAdjustHeadFailed(_) => {
warn!(&ctx, "Dropping packet: {}", e);
xdp_action::XDP_DROP