Browse Source

Update UoT protocol

世界 2 years ago
parent
commit
f57ec13880

+ 10 - 2
app/proxyman/outbound/uot.go

@@ -11,13 +11,21 @@ import (
 )
 
 func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
-	if !dest.Address.Family().IsDomain() || dest.Address.Domain() != uot.UOTMagicAddress {
+	if !dest.Address.Family().IsDomain() {
+		return nil, os.ErrInvalid
+	}
+	var uotVersion int
+	if dest.Address.Domain() == uot.MagicAddress {
+		uotVersion = uot.Version
+	} else if dest.Address.Domain() == uot.LegacyMagicAddress {
+		uotVersion = uot.LegacyVersion
+	} else {
 		return nil, os.ErrInvalid
 	}
 	packetConn, err := internet.ListenSystemPacket(ctx, &net.UDPAddr{IP: net.AnyIP.IP(), Port: 0}, h.streamSettings.SocketSettings)
 	if err != nil {
 		return nil, newError("unable to listen socket").Base(err)
 	}
-	conn := uot.NewServerConn(packetConn)
+	conn := uot.NewServerConn(packetConn, uotVersion)
 	return h.getStatCouterConnection(conn), nil
 }

+ 1 - 1
go.mod

@@ -13,7 +13,7 @@ require (
 	github.com/pires/go-proxyproto v0.6.2
 	github.com/quic-go/quic-go v0.33.0
 	github.com/refraction-networking/utls v1.2.3-0.20230308205431-4f1df6c200db
-	github.com/sagernet/sing v0.1.8
+	github.com/sagernet/sing v0.2.0
 	github.com/sagernet/sing-shadowsocks v0.1.1
 	github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
 	github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb

+ 4 - 2
go.sum

@@ -141,8 +141,10 @@ github.com/refraction-networking/utls v1.2.3-0.20230308205431-4f1df6c200db/go.mo
 github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
 github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
-github.com/sagernet/sing v0.1.8 h1:6DKo2FkSHn0nUcjO7bAext/ai7y7pCusK/+fScBJ5Jk=
-github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
+github.com/sagernet/sing v0.1.9-0.20230315063014-2731df16725b h1:1iKGftQ59+shDSx2RaLaxXJcMK/B+IU9WqUPwyBW+E0=
+github.com/sagernet/sing v0.1.9-0.20230315063014-2731df16725b/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
+github.com/sagernet/sing v0.2.0 h1:iyc4TaeXG5XYXixl48zSDDTw46C9NOEAVFq6ZE0dA2k=
+github.com/sagernet/sing v0.2.0/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
 github.com/sagernet/sing-shadowsocks v0.1.1 h1:uFK2rlVeD/b1xhDwSMbUI2goWc6fOKxp+ZeKHZq6C9Q=
 github.com/sagernet/sing-shadowsocks v0.1.1/go.mod h1:f3mHTy5shnVM9l8UocMlJgC/1G/zdj5FuEuVXhDinGU=
 github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=

+ 10 - 8
infra/conf/shadowsocks.go

@@ -155,14 +155,15 @@ func buildShadowsocks2022(v *ShadowsocksServerConfig) (proto.Message, error) {
 }
 
 type ShadowsocksServerTarget struct {
-	Address  *Address `json:"address"`
-	Port     uint16   `json:"port"`
-	Cipher   string   `json:"method"`
-	Password string   `json:"password"`
-	Email    string   `json:"email"`
-	Level    byte     `json:"level"`
-	IVCheck  bool     `json:"ivCheck"`
-	UoT      bool     `json:"uot"`
+	Address    *Address `json:"address"`
+	Port       uint16   `json:"port"`
+	Cipher     string   `json:"method"`
+	Password   string   `json:"password"`
+	Email      string   `json:"email"`
+	Level      byte     `json:"level"`
+	IVCheck    bool     `json:"ivCheck"`
+	UoT        bool     `json:"uot"`
+	UoTVersion int      `json:"uotVersion"`
 }
 
 type ShadowsocksClientConfig struct {
@@ -193,6 +194,7 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
 			config.Method = server.Cipher
 			config.Key = server.Password
 			config.UdpOverTcp = server.UoT
+			config.UdpOverTcpVersion = uint32(server.UoTVersion)
 			return config, nil
 		}
 	}

+ 26 - 15
proxy/shadowsocks_2022/config.pb.go

@@ -389,11 +389,12 @@ type ClientConfig struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Address    *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
-	Port       uint32          `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
-	Method     string          `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"`
-	Key        string          `protobuf:"bytes,4,opt,name=key,proto3" json:"key,omitempty"`
-	UdpOverTcp bool            `protobuf:"varint,5,opt,name=udp_over_tcp,json=udpOverTcp,proto3" json:"udp_over_tcp,omitempty"`
+	Address           *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+	Port              uint32          `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
+	Method            string          `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"`
+	Key               string          `protobuf:"bytes,4,opt,name=key,proto3" json:"key,omitempty"`
+	UdpOverTcp        bool            `protobuf:"varint,5,opt,name=udp_over_tcp,json=udpOverTcp,proto3" json:"udp_over_tcp,omitempty"`
+	UdpOverTcpVersion uint32          `protobuf:"varint,6,opt,name=udp_over_tcp_version,json=udpOverTcpVersion,proto3" json:"udp_over_tcp_version,omitempty"`
 }
 
 func (x *ClientConfig) Reset() {
@@ -463,6 +464,13 @@ func (x *ClientConfig) GetUdpOverTcp() bool {
 	return false
 }
 
+func (x *ClientConfig) GetUdpOverTcpVersion() uint32 {
+	if x != nil {
+		return x.UdpOverTcpVersion
+	}
+	return 0
+}
+
 var File_proxy_shadowsocks_2022_config_proto protoreflect.FileDescriptor
 
 var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{
@@ -520,7 +528,7 @@ var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{
 	0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
 	0x79, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
 	0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xa5, 0x01,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xd6, 0x01,
 	0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35,
 	0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
 	0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
@@ -531,15 +539,18 @@ var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{
 	0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
 	0x6b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x64, 0x70, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f,
 	0x74, 0x63, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x64, 0x70, 0x4f, 0x76,
-	0x65, 0x72, 0x54, 0x63, 0x70, 0x42, 0x72, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
-	0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f,
-	0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68,
-	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
-	0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64,
-	0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0xaa, 0x02, 0x1a, 0x58,
-	0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77,
-	0x73, 0x6f, 0x63, 0x6b, 0x73, 0x32, 0x30, 0x32, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x33,
+	0x65, 0x72, 0x54, 0x63, 0x70, 0x12, 0x2f, 0x0a, 0x14, 0x75, 0x64, 0x70, 0x5f, 0x6f, 0x76, 0x65,
+	0x72, 0x5f, 0x74, 0x63, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x0d, 0x52, 0x11, 0x75, 0x64, 0x70, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x63, 0x70, 0x56,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
+	0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73,
+	0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74,
+	0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
+	0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61,
+	0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0xaa, 0x02, 0x1a,
+	0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f,
+	0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x32, 0x30, 0x32, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x33,
 }
 
 var (

+ 1 - 0
proxy/shadowsocks_2022/config.proto

@@ -51,4 +51,5 @@ message ClientConfig {
   string method = 3;
   string key = 4;
   bool udp_over_tcp = 5;
+  uint32 udp_over_tcp_version = 6;
 }

+ 14 - 10
proxy/shadowsocks_2022/outbound.go

@@ -11,7 +11,6 @@ import (
 	C "github.com/sagernet/sing/common"
 	B "github.com/sagernet/sing/common/buf"
 	"github.com/sagernet/sing/common/bufio"
-	M "github.com/sagernet/sing/common/metadata"
 	N "github.com/sagernet/sing/common/network"
 	"github.com/sagernet/sing/common/uot"
 	"github.com/xtls/xray-core/common"
@@ -29,10 +28,10 @@ func init() {
 }
 
 type Outbound struct {
-	ctx    context.Context
-	server net.Destination
-	method shadowsocks.Method
-	uot    bool
+	ctx       context.Context
+	server    net.Destination
+	method    shadowsocks.Method
+	uotClient *uot.Client
 }
 
 func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
@@ -43,7 +42,6 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
 			Port:    net.Port(config.Port),
 			Network: net.Network_TCP,
 		},
-		uot: config.UdpOverTcp,
 	}
 	if C.Contains(shadowaead_2022.List, config.Method) {
 		if config.Key == "" {
@@ -57,6 +55,9 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
 	} else {
 		return nil, newError("unknown method ", config.Method)
 	}
+	if config.UdpOverTcp {
+		o.uotClient = &uot.Client{Version: uint8(config.UdpOverTcpVersion)}
+	}
 	return o, nil
 }
 
@@ -77,7 +78,7 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
 	newError("tunneling request to ", destination, " via ", o.server.NetAddr()).WriteToLog(session.ExportIDToError(ctx))
 
 	serverDestination := o.server
-	if o.uot {
+	if o.uotClient != nil {
 		serverDestination.Network = net.Network_TCP
 	} else {
 		serverDestination.Network = network
@@ -149,9 +150,12 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
 			}
 		}
 
-		if o.uot {
-			serverConn := o.method.DialEarlyConn(connection, M.Socksaddr{Fqdn: uot.UOTMagicAddress})
-			return returnError(bufio.CopyPacketConn(ctx, packetConn, uot.NewClientConn(serverConn)))
+		if o.uotClient != nil {
+			uConn, err := o.uotClient.DialEarlyConn(o.method.DialEarlyConn(connection, uot.RequestDestination(o.uotClient.Version)), false, toSocksaddr(destination))
+			if err != nil {
+				return err
+			}
+			return returnError(bufio.CopyPacketConn(ctx, packetConn, uConn))
 		} else {
 			serverConn := o.method.DialPacketConn(connection)
 			return returnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))