Merge tag 'v1.14.3'

This commit is contained in:
Shtorm
2026-10-19 01:05:55 +03:00
321 changed files with 6750 additions and 5105 deletions
+1 -5
View File
@@ -63,7 +63,7 @@ func NewCertificateProvider(ctx context.Context, _ log.ContextLogger, tag string
}, nil
}
func (p *CertificateProvider) Start(stage adapter.StartStage) error {
func (p *CertificateProvider) Start(stage adapter.StartStage, scope *adapter.Scope) error {
if stage != adapter.StartStateStart {
return nil
}
@@ -82,10 +82,6 @@ func (p *CertificateProvider) Start(stage adapter.StartStage) error {
return nil
}
func (p *CertificateProvider) Close() error {
return nil
}
func (p *CertificateProvider) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
localClient := p.localClient
if localClient == nil {
+57 -34
View File
@@ -59,6 +59,7 @@ type DNSTransport struct {
magicHosts nDNSResolver.MagicDNSHosts
searchDomains []string
defaultResolvers []adapter.DNSTransport
resolverScope *adapter.Scope
}
func NewDNSTransport(ctx context.Context, logger log.ContextLogger, tag string, options option.TailscaleDNSServerOptions) (adapter.DNSTransport, error) {
@@ -77,7 +78,7 @@ func NewDNSTransport(ctx context.Context, logger log.ContextLogger, tag string,
}, nil
}
func (t *DNSTransport) Start(stage adapter.StartStage) error {
func (t *DNSTransport) Start(stage adapter.StartStage, scope *adapter.Scope) error {
if stage != adapter.StartStateInitialize {
return nil
}
@@ -94,6 +95,21 @@ func (t *DNSTransport) Start(stage adapter.StartStage) error {
}
ep.onReconfigHook = t.onReconfig
t.endpoint = ep
scope.Add(func() error {
t.access.Lock()
resolverScope := t.resolverScope
t.routePrefixes = nil
t.routes = nil
t.hosts = nil
t.magicHosts = nil
t.defaultResolvers = nil
t.resolverScope = nil
t.access.Unlock()
if resolverScope != nil {
return resolverScope.Close()
}
return nil
})
return nil
}
@@ -119,13 +135,14 @@ func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *n
directDialer := common.Must1(dialer.NewDefault(t.ctx, option.DialerOptions{}))
return &DNSDialer{transport: t, fallbackDialer: directDialer}
})
resolverScope := adapter.NewScope(t.ctx, t.logger)
routes := make(map[string][]adapter.DNSTransport)
for domain, resolvers := range dnsConfig.Routes {
var myResolvers []adapter.DNSTransport
for _, resolver := range resolvers {
myResolver, err := t.createResolver(directDialerOnce, resolver)
myResolver, err := t.createResolver(resolverScope, directDialerOnce, resolver)
if err != nil {
return err
return E.Errors(err, resolverScope.Close())
}
myResolvers = append(myResolvers, myResolver)
}
@@ -140,25 +157,26 @@ func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *n
})
var defaultResolvers []adapter.DNSTransport
for _, resolver := range dnsConfig.DefaultResolvers {
myResolver, err := t.createResolver(directDialerOnce, resolver)
myResolver, err := t.createResolver(resolverScope, directDialerOnce, resolver)
if err != nil {
return err
return E.Errors(err, resolverScope.Close())
}
defaultResolvers = append(defaultResolvers, myResolver)
}
t.access.Lock()
oldResolvers := t.collectResolversLocked()
oldResolverScope := t.resolverScope
t.routePrefixes = routePrefixes
t.routes = routes
t.hosts = hosts
t.magicHosts = t.endpoint.server.ExportLocalBackend().ExportMagicDNSHosts()
t.searchDomains = searchDomains
t.defaultResolvers = defaultResolvers
t.resolverScope = resolverScope
t.access.Unlock()
for _, transport := range oldResolvers {
transport.Close()
if oldResolverScope != nil {
oldResolverScope.Close()
}
if len(defaultResolvers) > 0 {
@@ -170,7 +188,7 @@ func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *n
return nil
}
func (t *DNSTransport) createResolver(directDialer func() N.Dialer, resolver *dnstype.Resolver) (adapter.DNSTransport, error) {
func (t *DNSTransport) createResolver(resolverScope *adapter.Scope, directDialer func() N.Dialer, resolver *dnstype.Resolver) (adapter.DNSTransport, error) {
serverURL, parseURLErr := url.Parse(resolver.Addr)
isHTTPScheme := parseURLErr == nil && (serverURL.Scheme == "http" || serverURL.Scheme == "https")
var myDialer N.Dialer
@@ -181,27 +199,47 @@ func (t *DNSTransport) createResolver(directDialer func() N.Dialer, resolver *dn
}
if len(resolver.BootstrapResolution) > 0 {
bootstrapTransport := transport.NewUDPRaw(t.logger, t.TransportAdapter, myDialer, M.SocksaddrFrom(resolver.BootstrapResolution[0], 53))
err := bootstrapTransport.Start(adapter.StartStateStart, resolverScope)
if err != nil {
return nil, err
}
myDialer = dialer.NewResolveDialer(t.ctx, myDialer, false, "", adapter.DNSQueryOptions{Transport: bootstrapTransport}, 0)
} else {
myDialer = dialer.NewResolveDialer(t.ctx, myDialer, false, "", t.endpoint.queryOptions, 0)
}
if isHTTPScheme {
if serverURL.Hostname() == "" {
return nil, E.New("missing host in resolver address: ", resolver.Addr)
}
serverAddr := M.ParseSocksaddrHostPortStr(serverURL.Hostname(), serverURL.Port())
switch serverURL.Scheme {
case "https":
if serverAddr.Port == 0 {
serverAddr.Port = 443
}
tlsConfig := common.Must1(tls.NewClient(t.ctx, t.logger, serverAddr.AddrString(), option.OutboundTLSOptions{
tlsConfig, err := tls.NewClient(t.ctx, t.logger, serverAddr.AddrString(), option.OutboundTLSOptions{
Enabled: true,
ALPN: []string{http2.NextProtoTLS, "http/1.1"},
}))
return transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, tlsConfig), nil
})
if err != nil {
return nil, E.Cause(err, "create TLS config for resolver ", resolver.Addr)
}
httpsTransport := transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, tlsConfig)
err = httpsTransport.Start(adapter.StartStateStart, resolverScope)
if err != nil {
return nil, err
}
return httpsTransport, nil
case "http":
if serverAddr.Port == 0 {
serverAddr.Port = 80
}
return transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, nil), nil
httpTransport := transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, nil)
err := httpTransport.Start(adapter.StartStateStart, resolverScope)
if err != nil {
return nil, err
}
return httpTransport, nil
}
}
serverAddr := M.ParseSocksaddr(resolver.Addr)
@@ -214,7 +252,12 @@ func (t *DNSTransport) createResolver(directDialer func() N.Dialer, resolver *dn
if serverAddr.Port == 0 {
serverAddr.Port = 53
}
return transport.NewUDPRaw(t.logger, t.TransportAdapter, myDialer, serverAddr), nil
udpTransport := transport.NewUDPRaw(t.logger, t.TransportAdapter, myDialer, serverAddr)
err := udpTransport.Start(adapter.StartStateStart, resolverScope)
if err != nil {
return nil, err
}
return udpTransport, nil
}
func buildRoutePrefixes(routeConfig *router.Config) []netip.Prefix {
@@ -238,26 +281,6 @@ func buildRoutePrefixes(routeConfig *router.Config) []netip.Prefix {
return ipSet.Prefixes()
}
func (t *DNSTransport) Close() error {
t.access.Lock()
transports := t.collectResolversLocked()
t.routePrefixes = nil
t.routes = nil
t.hosts = nil
t.magicHosts = nil
t.defaultResolvers = nil
t.access.Unlock()
var err error
for _, transport := range transports {
name := "resolver/" + transport.Type() + "[" + transport.Tag() + "]"
err = E.Append(err, transport.Close(), func(err error) error {
return E.Cause(err, "close ", name)
})
}
return err
}
func (t *DNSTransport) Raw() bool {
return true
}
+69 -68
View File
@@ -48,7 +48,6 @@ import (
tailscaleroot "github.com/sagernet/tailscale"
_ "github.com/sagernet/tailscale/feature/relayserver"
"github.com/sagernet/tailscale/ipn"
"github.com/sagernet/tailscale/ipn/ipnlocal"
tsDNS "github.com/sagernet/tailscale/net/dns"
"github.com/sagernet/tailscale/net/netmon"
"github.com/sagernet/tailscale/net/netns"
@@ -68,6 +67,7 @@ import (
var (
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
_ adapter.Referrer = (*Endpoint)(nil)
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
_ tun.Port = (*Endpoint)(nil)
)
@@ -89,9 +89,9 @@ type Endpoint struct {
dnsRouter adapter.DNSRouter
network adapter.NetworkManager
platformInterface adapter.PlatformInterface
detour string
server *tsnet.Server
stack *stack.Stack
icmpForwarder *tun.ICMPForwarder
returnAccess sync.Mutex
returnPath tun.Return
wgEngine wgengine.ExportedUserspaceEngine
@@ -120,17 +120,13 @@ type Endpoint struct {
sshServerInstance *tailssh.Server
sshServerOptions *option.TailscaleSSHServerOptions
taildrop *taildropManager
localBackend *ipnlocal.LocalBackend
systemInterface bool
systemInterfaceName string
systemInterfaceMTU uint32
keyAuth bool
serverStarted bool
started atomic.Bool
systemTun tun.Tun
systemDialer *dialer.DefaultDialer
fallbackTCPCloser func()
}
func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TailscaleEndpointOptions) (adapter.Endpoint, error) {
@@ -200,6 +196,7 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
queryOptions: dialerQueryOptions,
network: service.FromContext[adapter.NetworkManager](ctx),
platformInterface: platformInterface,
detour: options.Detour,
server: &tsnet.Server{
Dir: stateDirectory,
Hostname: hostname,
@@ -251,7 +248,14 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
}, nil
}
func (t *Endpoint) Start(stage adapter.StartStage) error {
func (t *Endpoint) References() []string {
if t.detour == "" {
return nil
}
return []string{t.detour}
}
func (t *Endpoint) Start(stage adapter.StartStage, scope *adapter.Scope) error {
switch stage {
case adapter.StartStateInitialize:
mkdirErr := filemanager.MkdirAll(t.ctx, t.server.Dir, 0o700)
@@ -266,14 +270,14 @@ func (t *Endpoint) Start(stage adapter.StartStage) error {
}
t.server.PeerDNSQueryHandler = (*peerDNSQueryHandler)(t)
case adapter.StartStateStart:
return t.start()
return t.start(scope)
case adapter.StartStatePostStart:
return t.postStart()
return t.postStart(scope)
}
return nil
}
func (t *Endpoint) start() error {
func (t *Endpoint) start(scope *adapter.Scope) error {
if t.platformInterface != nil && t.platformInterface.UsePlatformNetworkInterfaces() {
err := t.network.UpdateInterfaces()
if err != nil {
@@ -298,6 +302,10 @@ func (t *Endpoint) start() error {
}
}), nil
})
scope.Add(func() error {
netmon.RegisterInterfaceGetter(nil)
return nil
})
}
if t.systemInterface {
mtu := t.systemInterfaceMTU
@@ -323,14 +331,13 @@ func (t *Endpoint) start() error {
if err != nil {
return err
}
scope.Add(systemTun.Close)
err = systemTun.Start()
if err != nil {
_ = systemTun.Close()
return err
}
wgTunDevice, err := newTunDeviceAdapter(systemTun, int(mtu), t.logger)
if err != nil {
_ = systemTun.Close()
return err
}
systemDialer, err := dialer.NewDefault(t.ctx, option.DialerOptions{
@@ -339,15 +346,17 @@ func (t *Endpoint) start() error {
},
})
if err != nil {
_ = systemTun.Close()
return err
}
t.systemTun = systemTun
t.systemDialer = systemDialer
t.server.Tun = wgTunDevice
}
if t.network.AutoRedirectOutputMark() != 0 {
netns.SetControlFunc(t.network.AutoRedirectOutputMarkFunc())
scope.Add(func() error {
netns.SetControlFunc(nil)
return nil
})
} else if t.platformInterface != nil && t.platformInterface.UsePlatformNetworkInterfaces() {
if t.platformInterface.UsePlatformAutoDetectInterfaceControl() {
netns.SetControlFunc(func(network, address string, conn syscall.RawConn) error {
@@ -355,6 +364,10 @@ func (t *Endpoint) start() error {
return t.platformInterface.AutoDetectInterfaceControl(int(fileDescriptor))
})
})
scope.Add(func() error {
netns.SetControlFunc(nil)
return nil
})
} else {
// NEPacketTunnelProvider sockets are excluded from tunnel routes by
// NECP; the empty override only suppresses tailscale's own
@@ -362,12 +375,21 @@ func (t *Endpoint) start() error {
netns.SetControlFunc(func(string, string, syscall.RawConn) error {
return nil
})
scope.Add(func() error {
netns.SetControlFunc(nil)
return nil
})
}
} else {
bindFunc := t.network.AutoDetectInterfaceFunc()
if bindFunc != nil {
netns.SetControlFunc(bindFunc)
netns.SetListenPacketFunc(t.listenPacket)
scope.Add(func() error {
netns.SetControlFunc(nil)
netns.SetListenPacketFunc(nil)
return nil
})
}
}
return nil
@@ -398,29 +420,35 @@ func (t *Endpoint) listenPacket(ctx context.Context, network string, address str
return tun.NewUDPEgressConn(udpConn, egressPool), nil
}
func (t *Endpoint) postStart() error {
func (t *Endpoint) postStart(scope *adapter.Scope) error {
err := t.server.Start()
if err != nil {
if t.systemTun != nil {
_ = t.systemTun.Close()
}
return err
}
t.serverStarted = true
if t.fallbackTCPCloser == nil {
t.fallbackTCPCloser = t.server.RegisterFallbackTCPHandler(func(src, dst netip.AddrPort) (handler func(net.Conn), intercept bool) {
return func(conn net.Conn) {
ctx := log.ContextWithNewID(t.ctx)
source := M.SocksaddrFrom(src.Addr(), src.Port())
destination := M.SocksaddrFrom(dst.Addr(), dst.Port())
t.NewConnectionEx(ctx, conn, source, destination, nil)
}, true
})
}
scope.Add(t.server.Close)
fallbackTCPCloser := t.server.RegisterFallbackTCPHandler(func(src, dst netip.AddrPort) (handler func(net.Conn), intercept bool) {
return func(conn net.Conn) {
ctx := log.ContextWithNewID(t.ctx)
source := M.SocksaddrFrom(src.Addr(), src.Port())
destination := M.SocksaddrFrom(dst.Addr(), dst.Port())
t.NewConnectionEx(ctx, conn, source, destination, nil)
}, true
})
scope.Add(func() error {
fallbackTCPCloser()
return nil
})
localBackend := t.server.ExportLocalBackend()
t.localBackend = localBackend
scope.Add(func() error {
t.taildrop.close()
return nil
})
if !version.IsAppleTV() {
registerTaildropEndpoint(localBackend, t)
scope.Add(func() error {
unregisterTaildropEndpoint(localBackend)
return nil
})
go t.taildrop.start()
}
wgEngine := localBackend.ExportEngine().(wgengine.ExportedUserspaceEngine)
@@ -437,10 +465,10 @@ func (t *Endpoint) postStart() error {
return gonet.TranslateNetstackError(gErr)
}
icmpForwarder := tun.NewICMPForwarder(ipStack, t, t.logger)
scope.Add(icmpForwarder.Close)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber4, icmpForwarder.HandlePacket)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber6, icmpForwarder.HandlePacket)
t.stack = ipStack
t.icmpForwarder = icmpForwarder
netstack := t.server.ExportNetstack()
if netstack != nil {
previousTCP := netstack.GetTCPHandlerForFlow
@@ -500,15 +528,20 @@ func (t *Endpoint) postStart() error {
if err != nil {
return E.Cause(err, "start SSH server")
}
scope.Add(sshServer.Close)
t.sshReconfigHook = sshServer.OnReconfig
t.sshServerInstance = sshServer
}
go t.watchState()
go t.watchState(scope.Context())
t.started.Store(true)
scope.Add(func() error {
t.started.Store(false)
return nil
})
return nil
}
func (t *Endpoint) watchState() {
func (t *Endpoint) watchState(ctx context.Context) {
localBackend := t.server.ExportLocalBackend()
var reportedAuthURL string
exitNodePending := t.exitNode != ""
@@ -523,7 +556,7 @@ func (t *Endpoint) watchState() {
}
for {
var busError string
localBackend.WatchNotifications(t.ctx, ipn.NotifyInitialState|ipn.NotifyPeerPatches, nil, func(roNotify *ipn.Notify) (keepGoing bool) {
localBackend.WatchNotifications(ctx, ipn.NotifyInitialState|ipn.NotifyPeerPatches, nil, func(roNotify *ipn.Notify) (keepGoing bool) {
if roNotify.ErrMessage != nil {
busError = *roNotify.ErrMessage
return false
@@ -568,7 +601,7 @@ func (t *Endpoint) watchState() {
}
return true
})
if t.ctx.Err() != nil {
if ctx.Err() != nil {
return
}
if busError != "" {
@@ -577,7 +610,7 @@ func (t *Endpoint) watchState() {
t.logger.Warn("state watcher stopped unexpectedly, restarting")
}
select {
case <-t.ctx.Done():
case <-ctx.Done():
return
case <-time.After(time.Second):
}
@@ -709,38 +742,6 @@ func (t *Endpoint) Logout(ctx context.Context) error {
return nil
}
func (t *Endpoint) Close() error {
var err error
t.started.Store(false)
if t.localBackend != nil {
unregisterTaildropEndpoint(t.localBackend)
t.localBackend = nil
}
t.taildrop.close()
if t.icmpForwarder != nil {
t.icmpForwarder.Close()
t.icmpForwarder = nil
}
common.Close(common.PtrOrNil(t.sshServerInstance))
t.sshServerInstance = nil
if t.serverStarted {
err = common.Close(common.PtrOrNil(t.server))
t.serverStarted = false
}
netmon.RegisterInterfaceGetter(nil)
netns.SetControlFunc(nil)
netns.SetListenPacketFunc(nil)
if t.fallbackTCPCloser != nil {
t.fallbackTCPCloser()
t.fallbackTCPCloser = nil
}
if t.systemTun != nil {
t.systemTun.Close()
t.systemTun = nil
}
return err
}
func (t *Endpoint) InterfaceUpdated(ctx context.Context) {
if !t.started.Load() {
return
+1 -1
View File
@@ -361,7 +361,7 @@ func validateTaildropFileName(name string) error {
var (
taildropExtensionSuffix = regexp.MustCompile(`(\.[a-zA-Z0-9]{0,3}[a-zA-Z][a-zA-Z0-9]{0,3})*$`)
taildropNumberSuffix = regexp.MustCompile(` \([0-9]+\)`)
taildropNumberSuffix = regexp.MustCompile(` \([0-9]+\)$`)
)
func nextFileName(name string) string {
+2 -2
View File
@@ -55,7 +55,7 @@ func (t *Endpoint) SendTaildropFile(ctx context.Context, peerStableID string, fi
if !peer.Valid() {
return E.New("taildrop: peer not found: ", peerStableID)
}
if peer.Hostinfo().OS() == "tvOS" {
if !peer.Hostinfo().Valid() || peer.Hostinfo().OS() == "tvOS" {
return E.New("taildrop: peer cannot receive files")
}
if self.User() != peer.User() && !nodeBackend.PeerHasCap(peer, tailcfg.PeerCapabilityFileSharingTarget) {
@@ -187,7 +187,7 @@ func (t *Endpoint) taildropTargets() (canShareFiles bool, targets map[string]boo
}
targets = make(map[string]bool)
for _, peer := range nodeBackend.Peers() {
if !peer.Valid() || peer.Hostinfo().OS() == "tvOS" {
if !peer.Valid() || !peer.Hostinfo().Valid() || peer.Hostinfo().OS() == "tvOS" {
continue
}
if self.User() != peer.User() && !nodeBackend.PeerHasCap(peer, tailcfg.PeerCapabilityFileSharingTarget) {
+26 -20
View File
@@ -252,28 +252,25 @@ func (s *Server) Close() error {
}
func (s *Server) serverConfig(ctx gliderssh.Context) *gossh.ServerConfig {
var preAuthConn gossh.ServerPreAuthConn
config := &gossh.ServerConfig{
PreAuthConnCallback: func(conn gossh.ServerPreAuthConn) {
preAuthConn = conn
},
NoClientAuthCallback: func(conn gossh.ConnMetadata) (*gossh.Permissions, error) {
return s.authenticate(ctx, conn)
return s.authenticate(ctx, preAuthConn, conn)
},
PasswordCallback: func(conn gossh.ConnMetadata, password []byte) (*gossh.Permissions, error) {
return s.authenticate(ctx, conn)
return s.authenticate(ctx, preAuthConn, conn)
},
PublicKeyCallback: func(conn gossh.ConnMetadata, key gossh.PublicKey) (*gossh.Permissions, error) {
return s.authenticate(ctx, conn)
},
BannerCallback: func(conn gossh.ConnMetadata) string {
connInfo := s.connInfoFromContext(ctx)
if connInfo != nil && connInfo.action.Message != "" {
return connInfo.action.Message
}
return ""
return s.authenticate(ctx, preAuthConn, conn)
},
}
return config
}
func (s *Server) authenticate(ctx gliderssh.Context, conn gossh.ConnMetadata) (*gossh.Permissions, error) {
func (s *Server) authenticate(ctx gliderssh.Context, preAuthConn gossh.ServerPreAuthConn, conn gossh.ConnMetadata) (*gossh.Permissions, error) {
if s.connInfoFromContext(ctx) != nil {
return &gossh.Permissions{}, nil
}
@@ -298,12 +295,22 @@ func (s *Server) authenticate(ctx gliderssh.Context, conn gossh.ConnMetadata) (*
s.logger.Info("SSH auth rejected for ", userProfile.LoginName, " -> ", conn.User(), ": ", err)
return nil, &gossh.PartialSuccessError{}
}
if connInfo.action.Reject {
s.logger.Info("SSH auth rejected for ", userProfile.LoginName, " -> ", conn.User())
return nil, &gossh.PartialSuccessError{}
}
connInfo.action0 = connInfo.action
for hops := 0; connInfo.action.HoldAndDelegate != ""; hops++ {
for hops := 0; ; hops++ {
if connInfo.action.Message != "" {
err = preAuthConn.SendAuthBanner(connInfo.action.Message)
if err != nil {
s.logger.Info("SSH auth: send banner: ", err)
return nil, &gossh.PartialSuccessError{}
}
}
if connInfo.action.Reject {
s.logger.Info("SSH auth rejected for ", userProfile.LoginName, " -> ", conn.User())
return nil, &gossh.PartialSuccessError{}
}
if connInfo.action.HoldAndDelegate == "" {
break
}
if hops >= 10 {
s.logger.Info("SSH auth rejected: hold-and-delegate chain too long")
return nil, &gossh.PartialSuccessError{}
@@ -314,10 +321,6 @@ func (s *Server) authenticate(ctx gliderssh.Context, conn gossh.ConnMetadata) (*
return nil, &gossh.PartialSuccessError{}
}
connInfo.action = delegatedAction
if connInfo.action.Reject {
s.logger.Info("SSH auth rejected for ", userProfile.LoginName, " -> ", conn.User())
return nil, &gossh.PartialSuccessError{}
}
}
if !connInfo.action.Accept {
s.logger.Info("SSH auth rejected for ", userProfile.LoginName, " -> ", conn.User())
@@ -334,6 +337,9 @@ func (s *Server) authenticate(ctx gliderssh.Context, conn gossh.ConnMetadata) (*
func (s *Server) evaluatePolicy(policy *tailcfg.SSHPolicy, sshUser string, node tailcfg.NodeView, userProfile tailcfg.UserProfile, srcIP netip.Addr) (*sshConnInfo, error) {
now := time.Now()
for _, rule := range policy.Rules {
if rule == nil {
continue
}
if rule.RuleExpires != nil && now.After(*rule.RuleExpires) {
continue
}