From b481eca4a420907a466c4cfefc4210cab2430b75 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 17 Aug 2025 16:14:20 +0800 Subject: [PATCH] chore: allow vision with vless encryption --- adapter/outbound/vless.go | 6 ------ listener/inbound/vless_test.go | 5 +++++ listener/sing_vless/server.go | 16 ++++++++++++++++ transport/vless/vision/vision.go | 13 +++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index b26ddb07..3db99e1f 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -3,7 +3,6 @@ package outbound import ( "context" "crypto/tls" - "errors" "fmt" "net" "net/http" @@ -457,11 +456,6 @@ func NewVless(option VlessOption) (*Vless, error) { if err != nil { return nil, err } - if v.encryption != nil { - if option.Flow != "" { - return nil, errors.New(`vless "encryption" doesn't support "flow" yet`) - } - } v.realityConfig, err = v.option.RealityOpts.Parse() if err != nil { diff --git a/listener/inbound/vless_test.go b/listener/inbound/vless_test.go index e344aa2e..c110228d 100644 --- a/listener/inbound/vless_test.go +++ b/listener/inbound/vless_test.go @@ -102,6 +102,11 @@ func TestInboundVless_Encryption(t *testing.T) { Encryption: "8min-vless-mlkem768client-" + clientBase64, } testInboundVless(t, inboundOptions, outboundOptions) + t.Run("xtls-rprx-vision", func(t *testing.T) { + outboundOptions := outboundOptions + outboundOptions.Flow = "xtls-rprx-vision" + testInboundVless(t, inboundOptions, outboundOptions) + }) }) t.Run("-xored-", func(t *testing.T) { inboundOptions := inbound.VlessOption{ diff --git a/listener/sing_vless/server.go b/listener/sing_vless/server.go index 0e729cab..d386ef67 100644 --- a/listener/sing_vless/server.go +++ b/listener/sing_vless/server.go @@ -43,6 +43,22 @@ func init() { } return true, tlsConn.NetConn(), reflect.TypeOf(tlsConn.Conn).Elem(), unsafe.Pointer(tlsConn.Conn) }) + + vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) { + tlsConn, loaded := common.Cast[*encryption.ClientConn](conn) + if !loaded { + return + } + return true, tlsConn.Conn, reflect.TypeOf(tlsConn).Elem(), unsafe.Pointer(tlsConn) + }) + + vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) { + tlsConn, loaded := common.Cast[*encryption.ServerConn](conn) + if !loaded { + return + } + return true, tlsConn.Conn, reflect.TypeOf(tlsConn).Elem(), unsafe.Pointer(tlsConn) + }) } type Listener struct { diff --git a/transport/vless/vision/vision.go b/transport/vless/vision/vision.go index 01f3a5d6..32634f0c 100644 --- a/transport/vless/vision/vision.go +++ b/transport/vless/vision/vision.go @@ -12,6 +12,7 @@ import ( N "github.com/metacubex/mihomo/common/net" tlsC "github.com/metacubex/mihomo/component/tls" + "github.com/metacubex/mihomo/transport/vless/encryption" "github.com/gofrs/uuid/v5" "github.com/metacubex/sing/common" @@ -58,6 +59,18 @@ func NewConn(conn connWithUpstream, userUUID *uuid.UUID) (*Conn, error) { t = reflect.TypeOf(underlying.Conn).Elem() //log.Debugln("t:%v", t) p = unsafe.Pointer(underlying.Conn) + case *encryption.ClientConn: + //log.Debugln("type *encryption.ClientConn") + c.Conn = underlying.Conn + c.tlsConn = underlying + t = reflect.TypeOf(underlying).Elem() + p = unsafe.Pointer(underlying) + case *encryption.ServerConn: + //log.Debugln("type *encryption.ServerConn") + c.Conn = underlying.Conn + c.tlsConn = underlying + t = reflect.TypeOf(underlying).Elem() + p = unsafe.Pointer(underlying) default: return nil, fmt.Errorf(`failed to use vision, maybe "security" is not "tls" or "utls"`) }