wgengine/netstack: allow UDP listeners to receive traffic on Service VIP addresses

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:
chaosinthecrd 2026-03-11 16:22:18 +00:00
parent 70de111394
commit 0a46d61008
No known key found for this signature in database
GPG Key ID: 52ED56820AF046EE

View File

@ -1205,6 +1205,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) {