From 7b3e5b5df36276567109f6a924d2866d0f85e503 Mon Sep 17 00:00:00 2001 From: Adrian Dewhurst Date: Thu, 6 Feb 2025 17:21:00 -0500 Subject: [PATCH] wgengine/netstack: respond to service IPs in Linux tun mode When in tun mode on Linux, AllowedIPs are not automatically added to netstack because the kernel is responsible for handling subnet routes. This ensures that virtual IPs are always added to netstack. When in tun mode, pings were also not being handled, so this adds explicit support for ping as well. Fixes tailscale/corp#26387 Change-Id: I6af02848bf2572701288125f247d1eaa6f661107 Signed-off-by: Adrian Dewhurst --- wgengine/netstack/netstack.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go index 76c8754ac..0bbd20b79 100644 --- a/wgengine/netstack/netstack.go +++ b/wgengine/netstack/netstack.go @@ -635,9 +635,10 @@ var v4broadcast = netaddr.IPv4(255, 255, 255, 255) // address slice views. func (ns *Impl) UpdateNetstackIPs(nm *netmap.NetworkMap) { var selfNode tailcfg.NodeView + var serviceAddrSet set.Set[netip.Addr] if nm != nil { vipServiceIPMap := nm.GetVIPServiceIPMap() - serviceAddrSet := set.Set[netip.Addr]{} + serviceAddrSet = make(set.Set[netip.Addr], len(vipServiceIPMap)*2) for _, addrs := range vipServiceIPMap { serviceAddrSet.AddSlice(addrs) } @@ -675,6 +676,11 @@ func (ns *Impl) UpdateNetstackIPs(nm *netmap.NetworkMap) { } } + for addr := range serviceAddrSet { + p := netip.PrefixFrom(addr, addr.BitLen()) + newPfx[p] = true + } + pfxToAdd := make(map[netip.Prefix]bool) for p := range newPfx { if !oldPfx[p] { @@ -1019,12 +1025,18 @@ func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool { return true } } - if ns.lb != nil && p.IPProto == ipproto.TCP && isService { - // An assumption holds for this to work: when tun mode is on for a service, - // its tcp and web are not set. This is enforced in b.setServeConfigLocked. - if ns.lb.ShouldInterceptVIPServiceTCPPort(p.Dst) { + if isService { + if p.IsEchoRequest() { return true } + if ns.lb != nil && p.IPProto == ipproto.TCP { + // An assumption holds for this to work: when tun mode is on for a service, + // its tcp and web are not set. This is enforced in b.setServeConfigLocked. + if ns.lb.ShouldInterceptVIPServiceTCPPort(p.Dst) { + return true + } + } + return false } if p.IPVersion == 6 && !isLocal && viaRange.Contains(dstIP) { return ns.lb != nil && ns.lb.ShouldHandleViaIP(dstIP)