diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index 046c86b23..7f14599d2 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -17,7 +17,7 @@ import ( "github.com/v2fly/v2ray-core/v5/proxy" "github.com/v2fly/v2ray-core/v5/transport" "github.com/v2fly/v2ray-core/v5/transport/internet" - "github.com/v2fly/v2ray-core/v5/transport/internet/tls" + "github.com/v2fly/v2ray-core/v5/transport/internet/security" "github.com/v2fly/v2ray-core/v5/transport/pipe" ) @@ -182,9 +182,16 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn go handler.Dispatch(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter}) conn := net.NewConnection(net.ConnectionInputMulti(uplinkWriter), net.ConnectionOutputMulti(downlinkReader)) - if config := tls.ConfigFromStreamSettings(h.streamSettings); config != nil { - tlsConfig := config.GetTLSConfig(tls.WithDestination(dest)) - conn = tls.Client(conn, tlsConfig) + securityEngine, err := security.CreateSecurityEngineFromSettings(ctx, h.streamSettings) + if err != nil { + return nil, newError("unable to create security engine").Base(err) + } + + if securityEngine != nil { + conn, err = securityEngine.Client(conn) + if err != nil { + return nil, newError("unable to create security protocol client from security engine").Base(err) + } } return h.getStatCouterConnection(conn), nil diff --git a/transport/internet/security/errors.generated.go b/transport/internet/security/errors.generated.go new file mode 100644 index 000000000..e8419185e --- /dev/null +++ b/transport/internet/security/errors.generated.go @@ -0,0 +1,9 @@ +package security + +import "github.com/v2fly/v2ray-core/v5/common/errors" + +type errPathObjHolder struct{} + +func newError(values ...interface{}) *errors.Error { + return errors.New(values...).WithPathObj(errPathObjHolder{}) +} diff --git a/transport/internet/security/security.go b/transport/internet/security/security.go new file mode 100644 index 000000000..044a96bbb --- /dev/null +++ b/transport/internet/security/security.go @@ -0,0 +1,33 @@ +package security + +//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen + +import ( + "github.com/v2fly/v2ray-core/v5/common/net" +) + +type Engine interface { + Client(conn net.Conn, opts ...Option) (Conn, error) +} + +type Conn interface { + net.Conn +} + +type Option interface { + isSecurityOption() +} + +type OptionWithALPN struct { + ALPNs []string +} + +func (a OptionWithALPN) isSecurityOption() { +} + +type OptionWithDestination struct { + Dest net.Destination +} + +func (a OptionWithDestination) isSecurityOption() { +} diff --git a/transport/internet/security/util.go b/transport/internet/security/util.go new file mode 100644 index 000000000..1e22a37e0 --- /dev/null +++ b/transport/internet/security/util.go @@ -0,0 +1,23 @@ +package security + +import ( + "context" + + "github.com/v2fly/v2ray-core/v5/common" + "github.com/v2fly/v2ray-core/v5/transport/internet" +) + +func CreateSecurityEngineFromSettings(context context.Context, settings *internet.MemoryStreamConfig) (Engine, error) { + if settings == nil || settings.SecurityType == "" { + return nil, nil + } + securityEngine, err := common.CreateObject(context, settings.SecuritySettings) + if err != nil { + return nil, newError("unable to create security engine from security settings").Base(err) + } + securityEngineTyped, ok := securityEngine.(Engine) + if !ok { + return nil, newError("type assertion error when create security engine from security settings") + } + return securityEngineTyped, nil +} diff --git a/transport/internet/tcp/dialer.go b/transport/internet/tcp/dialer.go index d721e4bbf..1d12f299c 100644 --- a/transport/internet/tcp/dialer.go +++ b/transport/internet/tcp/dialer.go @@ -8,7 +8,7 @@ import ( "github.com/v2fly/v2ray-core/v5/common/serial" "github.com/v2fly/v2ray-core/v5/common/session" "github.com/v2fly/v2ray-core/v5/transport/internet" - "github.com/v2fly/v2ray-core/v5/transport/internet/tls" + "github.com/v2fly/v2ray-core/v5/transport/internet/security" ) // Dial dials a new TCP connection to the given destination. @@ -19,16 +19,16 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me return nil, err } - if config := tls.ConfigFromStreamSettings(streamSettings); config != nil { - tlsConfig := config.GetTLSConfig(tls.WithDestination(dest)) - /* - if config.IsExperiment8357() { - conn = tls.UClient(conn, tlsConfig) - } else { - conn = tls.Client(conn, tlsConfig) - } - */ - conn = tls.Client(conn, tlsConfig) + securityEngine, err := security.CreateSecurityEngineFromSettings(ctx, streamSettings) + if err != nil { + return nil, newError("unable to create security engine").Base(err) + } + + if securityEngine != nil { + conn, err = securityEngine.Client(conn) + if err != nil { + return nil, newError("unable to create security protocol client from security engine").Base(err) + } } tcpSettings := streamSettings.ProtocolSettings.(*Config) diff --git a/transport/internet/tls/engine.go b/transport/internet/tls/engine.go new file mode 100644 index 000000000..b25aa2715 --- /dev/null +++ b/transport/internet/tls/engine.go @@ -0,0 +1,30 @@ +package tls + +import ( + "github.com/v2fly/v2ray-core/v5/common/net" + "github.com/v2fly/v2ray-core/v5/transport/internet/security" +) + +type Engine struct { + config *Config +} + +func (e *Engine) Client(conn net.Conn, opts ...security.Option) (security.Conn, error) { + var options []Option + for _, v := range opts { + switch s := v.(type) { + case security.OptionWithALPN: + options = append(options, WithNextProto(s.ALPNs...)) + case security.OptionWithDestination: + options = append(options, WithDestination(s.Dest)) + default: + return nil, newError("unknown option") + } + } + tlsConn := Client(conn, e.config.GetTLSConfig(options...)) + return tlsConn, nil +} + +func NewTLSSecurityEngineFromConfig(config *Config) (security.Engine, error) { + return &Engine{config: config}, nil +} diff --git a/transport/internet/tls/tls.go b/transport/internet/tls/tls.go index abaec9af7..671cabbf9 100644 --- a/transport/internet/tls/tls.go +++ b/transport/internet/tls/tls.go @@ -66,6 +66,6 @@ func Server(c net.Conn, config *tls.Config) net.Conn { func init() { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { - return nil, newError("tls should be used with v2tls") + return NewTLSSecurityEngineFromConfig(config.(*Config)) })) }