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 <adrian@tailscale.com>
This commit is contained in:
Adrian Dewhurst 2025-02-06 17:21:00 -05:00 committed by Adrian Dewhurst
parent e1523fe686
commit 7b3e5b5df3

View File

@ -635,9 +635,10 @@ var v4broadcast = netaddr.IPv4(255, 255, 255, 255)
// address slice views. // address slice views.
func (ns *Impl) UpdateNetstackIPs(nm *netmap.NetworkMap) { func (ns *Impl) UpdateNetstackIPs(nm *netmap.NetworkMap) {
var selfNode tailcfg.NodeView var selfNode tailcfg.NodeView
var serviceAddrSet set.Set[netip.Addr]
if nm != nil { if nm != nil {
vipServiceIPMap := nm.GetVIPServiceIPMap() vipServiceIPMap := nm.GetVIPServiceIPMap()
serviceAddrSet := set.Set[netip.Addr]{} serviceAddrSet = make(set.Set[netip.Addr], len(vipServiceIPMap)*2)
for _, addrs := range vipServiceIPMap { for _, addrs := range vipServiceIPMap {
serviceAddrSet.AddSlice(addrs) 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) pfxToAdd := make(map[netip.Prefix]bool)
for p := range newPfx { for p := range newPfx {
if !oldPfx[p] { if !oldPfx[p] {
@ -1019,12 +1025,18 @@ func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool {
return true return true
} }
} }
if ns.lb != nil && p.IPProto == ipproto.TCP && isService { if isService {
// An assumption holds for this to work: when tun mode is on for a service, if p.IsEchoRequest() {
// its tcp and web are not set. This is enforced in b.setServeConfigLocked.
if ns.lb.ShouldInterceptVIPServiceTCPPort(p.Dst) {
return true 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) { if p.IPVersion == 6 && !isLocal && viaRange.Contains(dstIP) {
return ns.lb != nil && ns.lb.ShouldHandleViaIP(dstIP) return ns.lb != nil && ns.lb.ShouldHandleViaIP(dstIP)