Browse Source

ktls: Add warning for inappropriate scenarios

世界 1 month ago
parent
commit
ef5a41a134

+ 37 - 7
common/tls/client.go

@@ -20,7 +20,12 @@ func NewDialerFromOptions(ctx context.Context, logger logger.ContextLogger, dial
 	if !options.Enabled {
 		return dialer, nil
 	}
-	config, err := NewClient(ctx, logger, serverAddress, options)
+	config, err := NewClientWithOptions(ClientOptions{
+		Context:       ctx,
+		Logger:        logger,
+		ServerAddress: serverAddress,
+		Options:       options,
+	})
 	if err != nil {
 		return nil, err
 	}
@@ -28,15 +33,40 @@ func NewDialerFromOptions(ctx context.Context, logger logger.ContextLogger, dial
 }
 
 func NewClient(ctx context.Context, logger logger.ContextLogger, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
-	if !options.Enabled {
+	return NewClientWithOptions(ClientOptions{
+		Context:       ctx,
+		Logger:        logger,
+		ServerAddress: serverAddress,
+		Options:       options,
+	})
+}
+
+type ClientOptions struct {
+	Context        context.Context
+	Logger         logger.ContextLogger
+	ServerAddress  string
+	Options        option.OutboundTLSOptions
+	KTLSCompatible bool
+}
+
+func NewClientWithOptions(options ClientOptions) (Config, error) {
+	if !options.Options.Enabled {
 		return nil, nil
 	}
-	if options.Reality != nil && options.Reality.Enabled {
-		return NewRealityClient(ctx, logger, serverAddress, options)
-	} else if options.UTLS != nil && options.UTLS.Enabled {
-		return NewUTLSClient(ctx, logger, serverAddress, options)
+	if !options.KTLSCompatible {
+		if options.Options.KernelTx {
+			options.Logger.Warn("enabling kTLS TX in current scenarios will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_tx")
+		}
+	}
+	if options.Options.KernelRx {
+		options.Logger.Warn("enabling kTLS RX will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_rx")
+	}
+	if options.Options.Reality != nil && options.Options.Reality.Enabled {
+		return NewRealityClient(options.Context, options.Logger, options.ServerAddress, options.Options)
+	} else if options.Options.UTLS != nil && options.Options.UTLS.Enabled {
+		return NewUTLSClient(options.Context, options.Logger, options.ServerAddress, options.Options)
 	}
-	return NewSTDClient(ctx, logger, serverAddress, options)
+	return NewSTDClient(options.Context, options.Logger, options.ServerAddress, options.Options)
 }
 
 func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, error) {

+ 27 - 4
common/tls/server.go

@@ -12,14 +12,37 @@ import (
 	aTLS "github.com/sagernet/sing/common/tls"
 )
 
+type ServerOptions struct {
+	Context        context.Context
+	Logger         log.ContextLogger
+	Options        option.InboundTLSOptions
+	KTLSCompatible bool
+}
+
 func NewServer(ctx context.Context, logger log.ContextLogger, options option.InboundTLSOptions) (ServerConfig, error) {
-	if !options.Enabled {
+	return NewServerWithOptions(ServerOptions{
+		Context: ctx,
+		Logger:  logger,
+		Options: options,
+	})
+}
+
+func NewServerWithOptions(options ServerOptions) (ServerConfig, error) {
+	if !options.Options.Enabled {
 		return nil, nil
 	}
-	if options.Reality != nil && options.Reality.Enabled {
-		return NewRealityServer(ctx, logger, options)
+	if !options.KTLSCompatible {
+		if options.Options.KernelTx {
+			options.Logger.Warn("enabling kTLS TX in current scenarios will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_tx")
+		}
+	}
+	if options.Options.KernelRx {
+		options.Logger.Warn("enabling kTLS RX will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_rx")
+	}
+	if options.Options.Reality != nil && options.Options.Reality.Enabled {
+		return NewRealityServer(options.Context, options.Logger, options.Options)
 	}
-	return NewSTDServer(ctx, logger, options)
+	return NewSTDServer(options.Context, options.Logger, options.Options)
 }
 
 func ServerHandshake(ctx context.Context, conn net.Conn, config ServerConfig) (Conn, error) {

+ 4 - 0
common/tls/std_server.go

@@ -11,6 +11,7 @@ import (
 
 	"github.com/sagernet/fswatch"
 	"github.com/sagernet/sing-box/adapter"
+	C "github.com/sagernet/sing-box/constant"
 	"github.com/sagernet/sing-box/log"
 	"github.com/sagernet/sing-box/option"
 	"github.com/sagernet/sing/common"
@@ -301,6 +302,9 @@ func NewSTDServer(ctx context.Context, logger log.ContextLogger, options option.
 	}
 	var config ServerConfig = serverConfig
 	if options.KernelTx || options.KernelRx {
+		if !C.IsLinux {
+			return nil, E.New("kTLS is only supported on Linux")
+		}
 		config = &KTlSServerConfig{
 			ServerConfig: config,
 			logger:       logger,

+ 6 - 1
protocol/http/inbound.go

@@ -43,7 +43,12 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
 		authenticator: auth.NewAuthenticator(options.Users),
 	}
 	if options.TLS != nil {
-		tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
+		tlsConfig, err := tls.NewServerWithOptions(tls.ServerOptions{
+			Context:        ctx,
+			Logger:         logger,
+			Options:        common.PtrValueOrDefault(options.TLS),
+			KTLSCompatible: true,
+		})
 		if err != nil {
 			return nil, err
 		}

+ 6 - 1
protocol/mixed/inbound.go

@@ -46,7 +46,12 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
 		authenticator: auth.NewAuthenticator(options.Users),
 	}
 	if options.TLS != nil {
-		tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
+		tlsConfig, err := tls.NewServerWithOptions(tls.ServerOptions{
+			Context:        ctx,
+			Logger:         logger,
+			Options:        common.PtrValueOrDefault(options.TLS),
+			KTLSCompatible: true,
+		})
 		if err != nil {
 			return nil, err
 		}

+ 7 - 1
protocol/trojan/inbound.go

@@ -50,7 +50,13 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
 		users:   options.Users,
 	}
 	if options.TLS != nil {
-		tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
+		tlsConfig, err := tls.NewServerWithOptions(tls.ServerOptions{
+			Context: ctx,
+			Logger:  logger,
+			Options: common.PtrValueOrDefault(options.TLS),
+			KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
+				!common.PtrValueOrDefault(options.Multiplex).Enabled,
+		})
 		if err != nil {
 			return nil, err
 		}

+ 8 - 1
protocol/trojan/outbound.go

@@ -51,7 +51,14 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
 		key:        trojan.Key(options.Password),
 	}
 	if options.TLS != nil {
-		outbound.tlsConfig, err = tls.NewClient(ctx, logger, options.Server, common.PtrValueOrDefault(options.TLS))
+		outbound.tlsConfig, err = tls.NewClientWithOptions(tls.ClientOptions{
+			Context:       ctx,
+			Logger:        logger,
+			ServerAddress: options.Server,
+			Options:       common.PtrValueOrDefault(options.TLS),
+			KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
+				!common.PtrValueOrDefault(options.Multiplex).Enabled,
+		})
 		if err != nil {
 			return nil, err
 		}

+ 10 - 1
protocol/vless/inbound.go

@@ -68,7 +68,16 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
 	}))
 	inbound.service = service
 	if options.TLS != nil {
-		inbound.tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
+		inbound.tlsConfig, err = tls.NewServerWithOptions(tls.ServerOptions{
+			Context: ctx,
+			Logger:  logger,
+			Options: common.PtrValueOrDefault(options.TLS),
+			KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
+				!common.PtrValueOrDefault(options.Multiplex).Enabled &&
+				common.All(options.Users, func(it option.VLESSUser) bool {
+					return it.Flow == ""
+				}),
+		})
 		if err != nil {
 			return nil, err
 		}

+ 9 - 1
protocol/vless/outbound.go

@@ -53,7 +53,15 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
 		serverAddr: options.ServerOptions.Build(),
 	}
 	if options.TLS != nil {
-		outbound.tlsConfig, err = tls.NewClient(ctx, logger, options.Server, common.PtrValueOrDefault(options.TLS))
+		outbound.tlsConfig, err = tls.NewClientWithOptions(tls.ClientOptions{
+			Context:       ctx,
+			Logger:        logger,
+			ServerAddress: options.Server,
+			Options:       common.PtrValueOrDefault(options.TLS),
+			KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
+				!common.PtrValueOrDefault(options.Multiplex).Enabled &&
+				options.Flow == "",
+		})
 		if err != nil {
 			return nil, err
 		}