wgengine/netstack: allow UDP listeners to receive traffic on Service VIP addresses (#18972)

Fixes UDP listeners on VIP Service addresses not receiving inbound traffic.

- Modified shouldProcessInbound to check for registered UDP transport endpoints when processing packets to service VIPs
- Uses FindTransportEndpoint to determine if a UDP listener exists for the destination VIP/port
- Supports both IPv4 and IPv6

The aim was to mirror the existing TCP logic, providing feature parity for UDP-based services on VIP Services.

Fixes #18971

Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
This commit is contained in:
Tom Meadows
2026-04-08 10:53:50 +01:00
committed by GitHub
parent a182b864ac
commit 5341b26328
2 changed files with 216 additions and 0 deletions
+28
View File
@@ -1231,6 +1231,34 @@ func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool {
return true
}
}
// check if there's a registered UDP endpoint for this service VIP
// This allows userspace UDP listeners (e.g., via tsnet.ListenPacket) to
// receive traffic on service VIP addresses.
if p.IPProto == ipproto.UDP {
var netProto tcpip.NetworkProtocolNumber
var id stack.TransportEndpointID
if p.Dst.Addr().Is4() {
netProto = ipv4.ProtocolNumber
id = stack.TransportEndpointID{
LocalAddress: tcpip.AddrFrom4(p.Dst.Addr().As4()),
LocalPort: p.Dst.Port(),
RemoteAddress: tcpip.AddrFrom4(p.Src.Addr().As4()),
RemotePort: p.Src.Port(),
}
} else {
netProto = ipv6.ProtocolNumber
id = stack.TransportEndpointID{
LocalAddress: tcpip.AddrFrom16(p.Dst.Addr().As16()),
LocalPort: p.Dst.Port(),
RemoteAddress: tcpip.AddrFrom16(p.Src.Addr().As16()),
RemotePort: p.Src.Port(),
}
}
ep := ns.ipstack.FindTransportEndpoint(netProto, udp.ProtocolNumber, id, nicID)
if ep != nil {
return true
}
}
return false
}
if p.IPVersion == 6 && !isLocal && viaRange.Contains(dstIP) {