diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 5c1a025ab..864cc5ee1 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -3341,6 +3341,10 @@ func (b *LocalBackend) TCPHandlerForDst(src, dst netip.AddrPort) (handler func(c fs, ok := b.sys.TailFSForLocal.GetOK() if ok { return func(conn net.Conn) error { + if !b.TailFSAccessEnabled() { + conn.Close() + return nil + } return fs.HandleConn(conn, conn.RemoteAddr()) }, opts } diff --git a/ipn/ipnlocal/tailfs.go b/ipn/ipnlocal/tailfs.go index da5ec080e..4a3b83104 100644 --- a/ipn/ipnlocal/tailfs.go +++ b/ipn/ipnlocal/tailfs.go @@ -46,7 +46,20 @@ func (b *LocalBackend) TailFSSharingEnabled() bool { } func (b *LocalBackend) tailFSSharingEnabledLocked() bool { - return b.netMap != nil && b.netMap.SelfNode.HasCap(tailcfg.NodeAttrsTailFSSharingEnabled) + return b.netMap != nil && b.netMap.SelfNode.HasCap(tailcfg.NodeAttrsTailFSShare) +} + +// TailFSAccessEnabled reports whether accessing TailFS shares on remote nodes +// is enabled. This is currently based on checking for the tailfs:access node +// attribute. +func (b *LocalBackend) TailFSAccessEnabled() bool { + b.mu.Lock() + defer b.mu.Unlock() + return b.tailFSAccessEnabledLocked() +} + +func (b *LocalBackend) tailFSAccessEnabledLocked() bool { + return b.netMap != nil && b.netMap.SelfNode.HasCap(tailcfg.NodeAttrsTailFSAccess) } // TailFSSetFileServerAddr tells tailfs to use the given address for connecting @@ -272,6 +285,10 @@ func (b *LocalBackend) newTailFSListener(ctx context.Context, fs tailfs.FileSyst logf: logf, handler: func(conn net.Conn) error { + if !b.TailFSAccessEnabled() { + conn.Close() + return nil + } return fs.HandleConn(conn, conn.RemoteAddr()) }, bo: backoff.NewBackoff(fmt.Sprintf("tailfs-listener-%d", ap.Port()), logf, 30*time.Second), diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index c036c8a2e..96a1afda2 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -2211,8 +2211,11 @@ const ( // tail end of an active direct connection in magicsock. NodeAttrProbeUDPLifetime NodeCapability = "probe-udp-lifetime" - // NodeAttrsTailFSSharingEnabled enables sharing via TailFS. - NodeAttrsTailFSSharingEnabled NodeCapability = "tailfs:share" + // NodeAttrsTailFSShare enables sharing via TailFS. + NodeAttrsTailFSShare NodeCapability = "tailfs:share" + + // NodeAttrsTailFSAccess enables accessing shares via TailFS. + NodeAttrsTailFSAccess NodeCapability = "tailfs:access" ) // SetDNSRequest is a request to add a DNS record. diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go index 8e433a202..2df8e2bb9 100644 --- a/wgengine/netstack/netstack.go +++ b/wgengine/netstack/netstack.go @@ -932,6 +932,10 @@ func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) { if hittingDNS { go ns.dns.HandleTCPConn(c, addrPort) } else if hittingTailFS { + if !ns.lb.TailFSAccessEnabled() { + c.Close() + return + } err := ns.tailFSForLocal.HandleConn(c, net.TCPAddrFromAddrPort(addrPort)) if err != nil { ns.logf("netstack: tailfs.HandleConn: %v", err)