mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-11-06 10:12:37 +00:00
Merge tag 'v1.14.3'
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user