mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-21 20:56:06 +03:00
Add udp over tcp support for shadowsocks-2022
This commit is contained in:
parent
6f93ef7736
commit
c3505632fd
@ -211,6 +211,10 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
}
|
||||
}
|
||||
|
||||
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
||||
return conn, err
|
||||
}
|
||||
|
||||
conn, err := internet.Dial(ctx, dest, h.streamSettings)
|
||||
return h.getStatCouterConnection(conn), err
|
||||
}
|
||||
|
25
app/proxyman/outbound/uot.go
Normal file
25
app/proxyman/outbound/uot.go
Normal file
@ -0,0 +1,25 @@
|
||||
//go:build go1.18
|
||||
|
||||
package outbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing/common/uot"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
)
|
||||
|
||||
func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
||||
if !dest.Address.Family().IsDomain() || dest.Address.Domain() != uot.UOTMagicAddress {
|
||||
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)
|
||||
return h.getStatCouterConnection(conn), nil
|
||||
}
|
15
app/proxyman/outbound/uot_stub.go
Normal file
15
app/proxyman/outbound/uot_stub.go
Normal file
@ -0,0 +1,15 @@
|
||||
//go:build !go1.18
|
||||
|
||||
package outbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
)
|
||||
|
||||
func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
4
go.mod
4
go.mod
@ -16,8 +16,8 @@ require (
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pires/go-proxyproto v0.6.2
|
||||
github.com/refraction-networking/utls v1.1.0
|
||||
github.com/sagernet/sing v0.0.0-20220530041323-c82c144a8e00
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220531032427-182b7837c827
|
||||
github.com/sagernet/sing v0.0.0-20220601033944-4e04bbd3d84d
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220601034426-ee9be8af94e4
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
|
||||
github.com/stretchr/testify v1.7.1
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||
|
8
go.sum
8
go.sum
@ -172,10 +172,10 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sagernet/sing v0.0.0-20220530041323-c82c144a8e00 h1:kQCITv1yBrSSL6RIBPWTe1+goyWLbS4DELWTeRKmoh8=
|
||||
github.com/sagernet/sing v0.0.0-20220530041323-c82c144a8e00/go.mod h1:w2HnJzXKHpD6F5Z/9XlSD4qbcpHY2RSZuQnFzqgELMg=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220531032427-182b7837c827 h1:dy8/Ltn4TW8op9esqdXBCuOVuaUSEZW2gCVE609z2UY=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220531032427-182b7837c827/go.mod h1:24Hwpi7iyZ8KSUqV5GpG29xSc8jUfU//RlClJcOqph4=
|
||||
github.com/sagernet/sing v0.0.0-20220601033944-4e04bbd3d84d h1:BNhKTknI2tBPUOPDV3lcgwOX6iZimL7K3TPdTdp5hiA=
|
||||
github.com/sagernet/sing v0.0.0-20220601033944-4e04bbd3d84d/go.mod h1:w2HnJzXKHpD6F5Z/9XlSD4qbcpHY2RSZuQnFzqgELMg=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220601034426-ee9be8af94e4 h1:POJZphM4VaovhB/7GjJTG+pUTcI/Q9jaOHBqTL6jq1E=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220601034426-ee9be8af94e4/go.mod h1:8NNH8ACh+C0oZb4ielvRJHYA4kFmhDdSQxmwAa+N8PM=
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
|
@ -136,6 +136,7 @@ type ShadowsocksServerTarget struct {
|
||||
Email string `json:"email"`
|
||||
Level byte `json:"level"`
|
||||
IVCheck bool `json:"ivCheck"`
|
||||
UoT bool `json:"uot"`
|
||||
}
|
||||
|
||||
type ShadowsocksClientConfig struct {
|
||||
@ -165,6 +166,7 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
|
||||
config.Port = uint32(server.Port)
|
||||
config.Method = server.Cipher
|
||||
config.Key = server.Password
|
||||
config.UdpOverTcp = server.UoT
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
//go:build !go1.18
|
||||
|
||||
package conf
|
||||
|
||||
import (
|
||||
@ -98,6 +99,7 @@ type ShadowsocksServerTarget struct {
|
||||
Email string `json:"email"`
|
||||
Level byte `json:"level"`
|
||||
IVCheck bool `json:"ivCheck"`
|
||||
UoT bool `json:"uot"`
|
||||
}
|
||||
|
||||
type ShadowsocksClientConfig struct {
|
||||
|
@ -239,10 +239,11 @@ 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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
func (x *ClientConfig) Reset() {
|
||||
@ -305,6 +306,13 @@ func (x *ClientConfig) GetKey() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ClientConfig) GetUdpOverTcp() bool {
|
||||
if x != nil {
|
||||
return x.UdpOverTcp
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_proxy_shadowsocks_2022_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{
|
||||
@ -340,7 +348,7 @@ var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{
|
||||
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, 0x83, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x69,
|
||||
0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xa5, 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, 0x74, 0x2e, 0x49, 0x50, 0x4f,
|
||||
@ -348,15 +356,17 @@ var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{
|
||||
0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 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,
|
||||
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,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -35,4 +35,5 @@ message ClientConfig {
|
||||
uint32 port = 2;
|
||||
string method = 3;
|
||||
string key = 4;
|
||||
bool udp_over_tcp = 5;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
C "github.com/sagernet/sing/common"
|
||||
B "github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/xtls/xray-core/common"
|
||||
@ -74,20 +75,23 @@ func (i *Inbound) Process(ctx context.Context, network net.Network, connection s
|
||||
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||||
|
||||
if network == net.Network_TCP {
|
||||
return i.service.NewConnection(ctx, connection, metadata)
|
||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
} else {
|
||||
reader := buf.NewReader(connection)
|
||||
pc := &natPacketConn{connection}
|
||||
for {
|
||||
mb, err := reader.ReadMultiBuffer()
|
||||
if err != nil {
|
||||
return err
|
||||
buf.ReleaseMulti(mb)
|
||||
return returnError(err)
|
||||
}
|
||||
for _, buffer := range mb {
|
||||
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()), metadata)
|
||||
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()).ToOwned(), metadata)
|
||||
if err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
buffer.Release()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,6 +151,9 @@ func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, me
|
||||
}
|
||||
|
||||
func (i *Inbound) HandleError(err error) {
|
||||
if E.IsClosed(err) {
|
||||
return
|
||||
}
|
||||
newError(err).AtWarning().WriteToLog()
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||
B "github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/xtls/xray-core/common"
|
||||
@ -93,20 +94,23 @@ func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, con
|
||||
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||||
|
||||
if network == net.Network_TCP {
|
||||
return i.service.NewConnection(ctx, connection, metadata)
|
||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
} else {
|
||||
reader := buf.NewReader(connection)
|
||||
pc := &natPacketConn{connection}
|
||||
for {
|
||||
mb, err := reader.ReadMultiBuffer()
|
||||
if err != nil {
|
||||
return err
|
||||
buf.ReleaseMulti(mb)
|
||||
return returnError(err)
|
||||
}
|
||||
for _, buffer := range mb {
|
||||
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()), metadata)
|
||||
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()).ToOwned(), metadata)
|
||||
if err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
buffer.Release()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,5 +174,8 @@ func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.Packe
|
||||
}
|
||||
|
||||
func (i *MultiUserInbound) HandleError(err error) {
|
||||
if E.IsClosed(err) {
|
||||
return
|
||||
}
|
||||
newError(err).AtWarning().WriteToLog()
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ 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"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@ -32,6 +34,7 @@ type Outbound struct {
|
||||
ctx context.Context
|
||||
server net.Destination
|
||||
method shadowsocks.Method
|
||||
uot bool
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
|
||||
@ -42,6 +45,7 @@ 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 == "" {
|
||||
@ -75,7 +79,11 @@ 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
|
||||
serverDestination.Network = network
|
||||
if o.uot {
|
||||
serverDestination.Network = net.Network_TCP
|
||||
} else {
|
||||
serverDestination.Network = network
|
||||
}
|
||||
connection, err := dialer.Dial(ctx, serverDestination)
|
||||
if err != nil {
|
||||
return newError("failed to connect to server").Base(err)
|
||||
@ -143,7 +151,12 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
|
||||
}
|
||||
}
|
||||
|
||||
serverConn := o.method.DialPacketConn(connection)
|
||||
return returnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
|
||||
if o.uot {
|
||||
serverConn := o.method.DialEarlyConn(connection, M.Socksaddr{Fqdn: uot.UOTMagicAddress})
|
||||
return returnError(bufio.CopyPacketConn(ctx, packetConn, uot.NewClientConn(serverConn)))
|
||||
} else {
|
||||
serverConn := o.method.DialPacketConn(connection)
|
||||
return returnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
package shadowsocks_2022
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
B "github.com/sagernet/sing/common/buf"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@ -140,7 +140,7 @@ func (w *packetConnWrapper) Close() error {
|
||||
}
|
||||
|
||||
func returnError(err error) error {
|
||||
if errors.Is(err, io.EOF) {
|
||||
if E.IsClosed(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
@ -3,11 +3,10 @@ package scenarios
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||
"github.com/xtls/xray-core/app/log"
|
||||
"github.com/xtls/xray-core/app/proxyman"
|
||||
"github.com/xtls/xray-core/common"
|
||||
@ -17,6 +16,7 @@ import (
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/proxy/dokodemo"
|
||||
"github.com/xtls/xray-core/proxy/freedom"
|
||||
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
|
||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||
"github.com/xtls/xray-core/testing/servers/udp"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
Loading…
Reference in New Issue
Block a user