chore: Remove legacy XTLS support (#645)
* chore: Remove legacy XTLS support * chore: Rename function
This commit is contained in:
parent
cbb8ef5dfe
commit
a82745f544
10 changed files with 55 additions and 264 deletions
|
@ -14,7 +14,6 @@ import (
|
|||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/transport/gun"
|
||||
"github.com/Dreamacro/clash/transport/trojan"
|
||||
"github.com/Dreamacro/clash/transport/vless"
|
||||
)
|
||||
|
||||
type Trojan struct {
|
||||
|
@ -45,8 +44,6 @@ type TrojanOption struct {
|
|||
RealityOpts RealityOptions `proxy:"reality-opts,omitempty"`
|
||||
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
||||
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
|
||||
Flow string `proxy:"flow,omitempty"`
|
||||
FlowShow bool `proxy:"flow-show,omitempty"`
|
||||
ClientFingerprint string `proxy:"client-fingerprint,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -95,11 +92,6 @@ func (t *Trojan) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.
|
|||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
}
|
||||
|
||||
c, err = t.instance.PresetXTLSConn(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if metadata.NetWork == C.UDP {
|
||||
err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
|
||||
return c, err
|
||||
|
@ -117,12 +109,6 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
|||
return nil, err
|
||||
}
|
||||
|
||||
c, err = t.instance.PresetXTLSConn(c)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = t.instance.WriteHeader(c, trojan.CommandTCP, serializesSocksAddr(metadata)); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
|
@ -237,24 +223,10 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||
ALPN: option.ALPN,
|
||||
ServerName: option.Server,
|
||||
SkipCertVerify: option.SkipCertVerify,
|
||||
FlowShow: option.FlowShow,
|
||||
Fingerprint: option.Fingerprint,
|
||||
ClientFingerprint: option.ClientFingerprint,
|
||||
}
|
||||
|
||||
switch option.Network {
|
||||
case "", "tcp":
|
||||
if len(option.Flow) >= 16 {
|
||||
option.Flow = option.Flow[:16]
|
||||
switch option.Flow {
|
||||
case vless.XRO, vless.XRD, vless.XRS:
|
||||
tOption.Flow = option.Flow
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported xtls flow type: %s", option.Flow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if option.SNI != "" {
|
||||
tOption.ServerName = option.SNI
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
xtls "github.com/xtls/go"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
|
@ -17,9 +16,8 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
globalClientSessionCache tls.ClientSessionCache
|
||||
globalClientXSessionCache xtls.ClientSessionCache
|
||||
once sync.Once
|
||||
globalClientSessionCache tls.ClientSessionCache
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func tcpKeepAlive(c net.Conn) {
|
||||
|
@ -36,13 +34,6 @@ func getClientSessionCache() tls.ClientSessionCache {
|
|||
return globalClientSessionCache
|
||||
}
|
||||
|
||||
func getClientXSessionCache() xtls.ClientSessionCache {
|
||||
once.Do(func() {
|
||||
globalClientXSessionCache = xtls.NewLRUClientSessionCache(128)
|
||||
})
|
||||
return globalClientXSessionCache
|
||||
}
|
||||
|
||||
func serializesSocksAddr(metadata *C.Metadata) []byte {
|
||||
var buf [][]byte
|
||||
addrType := metadata.AddrType()
|
||||
|
|
|
@ -56,7 +56,6 @@ type VlessOption struct {
|
|||
Port int `proxy:"port"`
|
||||
UUID string `proxy:"uuid"`
|
||||
Flow string `proxy:"flow,omitempty"`
|
||||
FlowShow bool `proxy:"flow-show,omitempty"`
|
||||
TLS bool `proxy:"tls,omitempty"`
|
||||
UDP bool `proxy:"udp,omitempty"`
|
||||
PacketAddr bool `proxy:"packet-addr,omitempty"`
|
||||
|
@ -133,7 +132,7 @@ func (v *Vless) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.M
|
|||
c, err = vmess.StreamWebsocketConn(ctx, c, wsOpts)
|
||||
case "http":
|
||||
// readability first, so just copy default TLS logic
|
||||
c, err = v.streamTLSOrXTLSConn(ctx, c, false)
|
||||
c, err = v.streamTLSConn(ctx, c, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -148,7 +147,7 @@ func (v *Vless) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.M
|
|||
|
||||
c = vmess.StreamHTTPConn(c, httpOpts)
|
||||
case "h2":
|
||||
c, err = v.streamTLSOrXTLSConn(ctx, c, true)
|
||||
c, err = v.streamTLSConn(ctx, c, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -163,8 +162,8 @@ func (v *Vless) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.M
|
|||
c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig, v.realityConfig)
|
||||
default:
|
||||
// default tcp network
|
||||
// handle TLS And XTLS
|
||||
c, err = v.streamTLSOrXTLSConn(ctx, c, false)
|
||||
// handle TLS
|
||||
c, err = v.streamTLSConn(ctx, c, false)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -202,23 +201,10 @@ func (v *Vless) streamConn(c net.Conn, metadata *C.Metadata) (conn net.Conn, err
|
|||
return
|
||||
}
|
||||
|
||||
func (v *Vless) streamTLSOrXTLSConn(ctx context.Context, conn net.Conn, isH2 bool) (net.Conn, error) {
|
||||
host, _, _ := net.SplitHostPort(v.addr)
|
||||
func (v *Vless) streamTLSConn(ctx context.Context, conn net.Conn, isH2 bool) (net.Conn, error) {
|
||||
if v.option.TLS {
|
||||
host, _, _ := net.SplitHostPort(v.addr)
|
||||
|
||||
if v.isLegacyXTLSEnabled() && !isH2 {
|
||||
xtlsOpts := vless.XTLSConfig{
|
||||
Host: host,
|
||||
SkipCertVerify: v.option.SkipCertVerify,
|
||||
Fingerprint: v.option.Fingerprint,
|
||||
}
|
||||
|
||||
if v.option.ServerName != "" {
|
||||
xtlsOpts.Host = v.option.ServerName
|
||||
}
|
||||
|
||||
return vless.StreamXTLSConn(ctx, conn, &xtlsOpts)
|
||||
|
||||
} else if v.option.TLS {
|
||||
tlsOpts := vmess.TLSConfig{
|
||||
Host: host,
|
||||
SkipCertVerify: v.option.SkipCertVerify,
|
||||
|
@ -241,10 +227,6 @@ func (v *Vless) streamTLSOrXTLSConn(ctx context.Context, conn net.Conn, isH2 boo
|
|||
return conn, nil
|
||||
}
|
||||
|
||||
func (v *Vless) isLegacyXTLSEnabled() bool {
|
||||
return v.client.Addons != nil && v.client.Addons.Flow != vless.XRV
|
||||
}
|
||||
|
||||
// DialContext implements C.ProxyAdapter
|
||||
func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||
// gun transport
|
||||
|
@ -526,11 +508,11 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||
switch option.Flow {
|
||||
case vless.XRV:
|
||||
log.Warnln("To use %s, ensure your server is upgrade to Xray-core v1.8.0+", vless.XRV)
|
||||
fallthrough
|
||||
case vless.XRO, vless.XRD, vless.XRS:
|
||||
addons = &vless.Addons{
|
||||
Flow: option.Flow,
|
||||
}
|
||||
case vless.XRO, vless.XRD, vless.XRS:
|
||||
log.Fatalln("Legacy XTLS protocol %s is deprecated and no longer supported", option.Flow)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported xtls flow type: %s", option.Flow)
|
||||
}
|
||||
|
@ -549,7 +531,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||
option.PacketAddr = false
|
||||
}
|
||||
|
||||
client, err := vless.NewClient(option.UUID, addons, option.FlowShow)
|
||||
client, err := vless.NewClient(option.UUID, addons)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
xtls "github.com/xtls/go"
|
||||
)
|
||||
|
||||
var trustCerts []*x509.Certificate
|
||||
|
@ -122,27 +120,3 @@ func GetGlobalTLSConfig(tlsConfig *tls.Config) *tls.Config {
|
|||
tlsConfig.RootCAs = certPool
|
||||
return tlsConfig
|
||||
}
|
||||
|
||||
// GetSpecifiedFingerprintXTLSConfig specified fingerprint
|
||||
func GetSpecifiedFingerprintXTLSConfig(tlsConfig *xtls.Config, fingerprint string) (*xtls.Config, error) {
|
||||
if fingerprintBytes, err := convertFingerprint(fingerprint); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
tlsConfig = GetGlobalXTLSConfig(tlsConfig)
|
||||
tlsConfig.VerifyPeerCertificate = verifyFingerprint(fingerprintBytes)
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
return tlsConfig, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetGlobalXTLSConfig(tlsConfig *xtls.Config) *xtls.Config {
|
||||
certPool := getCertPool()
|
||||
if tlsConfig == nil {
|
||||
return &xtls.Config{
|
||||
RootCAs: certPool,
|
||||
}
|
||||
}
|
||||
|
||||
tlsConfig.RootCAs = certPool
|
||||
return tlsConfig
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -42,7 +42,6 @@ require (
|
|||
github.com/shirou/gopsutil/v3 v3.23.6
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3
|
||||
github.com/zhangyunhao116/fastrand v0.3.0
|
||||
go.etcd.io/bbolt v1.3.7
|
||||
go.uber.org/automaxprocs v1.5.2
|
||||
|
|
2
go.sum
2
go.sum
|
@ -194,8 +194,6 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
|
|||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3 h1:a3Y4WVjCxwoyO4E2xdNvq577tW8lkSBgyrA8E9+2NtM=
|
||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -18,10 +17,7 @@ import (
|
|||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/transport/socks5"
|
||||
"github.com/Dreamacro/clash/transport/vless"
|
||||
"github.com/Dreamacro/clash/transport/vmess"
|
||||
|
||||
xtls "github.com/xtls/go"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -42,7 +38,7 @@ const (
|
|||
CommandTCP byte = 1
|
||||
CommandUDP byte = 3
|
||||
|
||||
// for XTLS
|
||||
// deprecated XTLS commands, as souvenirs
|
||||
commandXRD byte = 0xf0 // XTLS direct mode
|
||||
commandXRO byte = 0xf1 // XTLS origin mode
|
||||
)
|
||||
|
@ -53,8 +49,6 @@ type Option struct {
|
|||
ServerName string
|
||||
SkipCertVerify bool
|
||||
Fingerprint string
|
||||
Flow string
|
||||
FlowShow bool
|
||||
ClientFingerprint string
|
||||
Reality *tlsC.RealityConfig
|
||||
}
|
||||
|
@ -76,78 +70,50 @@ func (t *Trojan) StreamConn(ctx context.Context, conn net.Conn) (net.Conn, error
|
|||
if len(t.option.ALPN) != 0 {
|
||||
alpn = t.option.ALPN
|
||||
}
|
||||
switch t.option.Flow {
|
||||
case vless.XRO, vless.XRD, vless.XRS:
|
||||
xtlsConfig := &xtls.Config{
|
||||
NextProtos: alpn,
|
||||
MinVersion: xtls.VersionTLS12,
|
||||
InsecureSkipVerify: t.option.SkipCertVerify,
|
||||
ServerName: t.option.ServerName,
|
||||
}
|
||||
tlsConfig := &tls.Config{
|
||||
NextProtos: alpn,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: t.option.SkipCertVerify,
|
||||
ServerName: t.option.ServerName,
|
||||
}
|
||||
|
||||
if len(t.option.Fingerprint) == 0 {
|
||||
xtlsConfig = tlsC.GetGlobalXTLSConfig(xtlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if xtlsConfig, err = tlsC.GetSpecifiedFingerprintXTLSConfig(xtlsConfig, t.option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
xtlsConn := xtls.Client(conn, xtlsConfig)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
if err := xtlsConn.HandshakeContext(ctx); err != nil {
|
||||
if len(t.option.Fingerprint) == 0 {
|
||||
tlsConfig = tlsC.GetGlobalTLSConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, t.option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return xtlsConn, nil
|
||||
default:
|
||||
tlsConfig := &tls.Config{
|
||||
NextProtos: alpn,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: t.option.SkipCertVerify,
|
||||
ServerName: t.option.ServerName,
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.option.Fingerprint) == 0 {
|
||||
tlsConfig = tlsC.GetGlobalTLSConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, t.option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.option.ClientFingerprint) != 0 {
|
||||
if t.option.Reality == nil {
|
||||
utlsConn, valid := vmess.GetUTLSConn(conn, t.option.ClientFingerprint, tlsConfig)
|
||||
if valid {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
|
||||
err := utlsConn.(*tlsC.UConn).HandshakeContext(ctx)
|
||||
return utlsConn, err
|
||||
}
|
||||
} else {
|
||||
if len(t.option.ClientFingerprint) != 0 {
|
||||
if t.option.Reality == nil {
|
||||
utlsConn, valid := vmess.GetUTLSConn(conn, t.option.ClientFingerprint, tlsConfig)
|
||||
if valid {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
return tlsC.GetRealityConn(ctx, conn, t.option.ClientFingerprint, tlsConfig, t.option.Reality)
|
||||
|
||||
err := utlsConn.(*tlsC.UConn).HandshakeContext(ctx)
|
||||
return utlsConn, err
|
||||
}
|
||||
} else {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
return tlsC.GetRealityConn(ctx, conn, t.option.ClientFingerprint, tlsConfig, t.option.Reality)
|
||||
}
|
||||
if t.option.Reality != nil {
|
||||
return nil, errors.New("REALITY is based on uTLS, please set a client-fingerprint")
|
||||
}
|
||||
|
||||
tlsConn := tls.Client(conn, tlsConfig)
|
||||
|
||||
// fix tls handshake not timeout
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
|
||||
err := tlsConn.HandshakeContext(ctx)
|
||||
return tlsConn, err
|
||||
}
|
||||
if t.option.Reality != nil {
|
||||
return nil, errors.New("REALITY is based on uTLS, please set a client-fingerprint")
|
||||
}
|
||||
|
||||
tlsConn := tls.Client(conn, tlsConfig)
|
||||
|
||||
// fix tls handshake not timeout
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
|
||||
err := tlsConn.HandshakeContext(ctx)
|
||||
return tlsConn, err
|
||||
}
|
||||
|
||||
func (t *Trojan) StreamWebsocketConn(ctx context.Context, conn net.Conn, wsOptions *WebsocketOption) (net.Conn, error) {
|
||||
|
@ -174,37 +140,7 @@ func (t *Trojan) StreamWebsocketConn(ctx context.Context, conn net.Conn, wsOptio
|
|||
})
|
||||
}
|
||||
|
||||
func (t *Trojan) PresetXTLSConn(conn net.Conn) (net.Conn, error) {
|
||||
switch t.option.Flow {
|
||||
case vless.XRO, vless.XRD, vless.XRS:
|
||||
if xtlsConn, ok := conn.(*xtls.Conn); ok {
|
||||
xtlsConn.RPRX = true
|
||||
xtlsConn.SHOW = t.option.FlowShow
|
||||
xtlsConn.MARK = "XTLS"
|
||||
if t.option.Flow == vless.XRS {
|
||||
t.option.Flow = vless.XRD
|
||||
}
|
||||
|
||||
if t.option.Flow == vless.XRD {
|
||||
xtlsConn.DirectMode = true
|
||||
}
|
||||
} else {
|
||||
return conn, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", t.option.Flow)
|
||||
}
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (t *Trojan) WriteHeader(w io.Writer, command Command, socks5Addr []byte) error {
|
||||
if command == CommandTCP {
|
||||
if t.option.Flow == vless.XRD {
|
||||
command = commandXRD
|
||||
} else if t.option.Flow == vless.XRO {
|
||||
command = commandXRO
|
||||
}
|
||||
}
|
||||
|
||||
buf := pool.GetBuffer()
|
||||
defer pool.PutBuffer(buf)
|
||||
|
||||
|
@ -398,8 +334,7 @@ func (pc *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, er
|
|||
|
||||
func hexSha224(data []byte) []byte {
|
||||
buf := make([]byte, 56)
|
||||
hash := sha256.New224()
|
||||
hash.Write(data)
|
||||
hex.Encode(buf, hash.Sum(nil))
|
||||
hash := sha256.Sum224(data)
|
||||
hex.Encode(buf, hash[:])
|
||||
return buf
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package vless
|
|||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
|
@ -13,7 +12,6 @@ import (
|
|||
"github.com/Dreamacro/clash/transport/vless/vision"
|
||||
|
||||
"github.com/gofrs/uuid/v5"
|
||||
xtls "github.com/xtls/go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
|
@ -201,25 +199,6 @@ func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
|
|||
|
||||
if client.Addons != nil {
|
||||
switch client.Addons.Flow {
|
||||
case XRO, XRD, XRS:
|
||||
if !dst.UDP {
|
||||
if xtlsConn, ok := conn.(*xtls.Conn); ok {
|
||||
xtlsConn.RPRX = true
|
||||
xtlsConn.SHOW = client.XTLSShow
|
||||
xtlsConn.MARK = "XTLS"
|
||||
if client.Addons.Flow == XRS {
|
||||
client.Addons.Flow = XRD
|
||||
}
|
||||
|
||||
if client.Addons.Flow == XRD {
|
||||
xtlsConn.DirectMode = true
|
||||
}
|
||||
c.addons = client.Addons
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow)
|
||||
}
|
||||
}
|
||||
|
||||
case XRV:
|
||||
visionConn, err := vision.NewConn(c, c.id)
|
||||
if err != nil {
|
||||
|
|
|
@ -42,9 +42,8 @@ type DstAddr struct {
|
|||
|
||||
// Client is vless connection generator
|
||||
type Client struct {
|
||||
uuid *uuid.UUID
|
||||
Addons *Addons
|
||||
XTLSShow bool
|
||||
uuid *uuid.UUID
|
||||
Addons *Addons
|
||||
}
|
||||
|
||||
// StreamConn return a Conn with net.Conn and DstAddr
|
||||
|
@ -53,15 +52,14 @@ func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
|
|||
}
|
||||
|
||||
// NewClient return Client instance
|
||||
func NewClient(uuidStr string, addons *Addons, xtlsShow bool) (*Client, error) {
|
||||
func NewClient(uuidStr string, addons *Addons) (*Client, error) {
|
||||
uid, err := utils.UUIDMap(uuidStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
uuid: &uid,
|
||||
Addons: addons,
|
||||
XTLSShow: xtlsShow,
|
||||
uuid: &uid,
|
||||
Addons: addons,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package vless
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
xtls "github.com/xtls/go"
|
||||
)
|
||||
|
||||
type XTLSConfig struct {
|
||||
Host string
|
||||
SkipCertVerify bool
|
||||
Fingerprint string
|
||||
NextProtos []string
|
||||
}
|
||||
|
||||
func StreamXTLSConn(ctx context.Context, conn net.Conn, cfg *XTLSConfig) (net.Conn, error) {
|
||||
xtlsConfig := &xtls.Config{
|
||||
ServerName: cfg.Host,
|
||||
InsecureSkipVerify: cfg.SkipCertVerify,
|
||||
NextProtos: cfg.NextProtos,
|
||||
}
|
||||
if len(cfg.Fingerprint) == 0 {
|
||||
xtlsConfig = tlsC.GetGlobalXTLSConfig(xtlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if xtlsConfig, err = tlsC.GetSpecifiedFingerprintXTLSConfig(xtlsConfig, cfg.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
xtlsConn := xtls.Client(conn, xtlsConfig)
|
||||
|
||||
err := xtlsConn.HandshakeContext(ctx)
|
||||
return xtlsConn, err
|
||||
}
|
Loading…
Reference in a new issue