Merge remote-tracking branch 'Pro-Plus/with-tun' into Alpha
# Conflicts: # README.md # adapter/outbound/trojan.go # adapter/outbound/vless.go # transport/trojan/trojan.go
This commit is contained in:
@ -7,7 +7,7 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
xtls "github.com/xtls/go"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -16,15 +16,15 @@ import (
|
||||
"github.com/Dreamacro/clash/common/pool"
|
||||
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 (
|
||||
// max packet length
|
||||
maxLength = 8192
|
||||
|
||||
XRD = "xtls-rprx-direct"
|
||||
XRO = "xtls-rprx-origin"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -36,21 +36,22 @@ var (
|
||||
|
||||
type Command = byte
|
||||
|
||||
var (
|
||||
const (
|
||||
CommandTCP byte = 1
|
||||
CommandUDP byte = 3
|
||||
CommandXRD byte = 0xf0
|
||||
CommandXRO byte = 0xf1
|
||||
|
||||
// for XTLS
|
||||
commandXRD byte = 0xf0 // XTLS direct mode
|
||||
commandXRO byte = 0xf1 // XTLS origin mode
|
||||
)
|
||||
|
||||
type Option struct {
|
||||
Password string
|
||||
Flow string
|
||||
ALPN []string
|
||||
ServerName string
|
||||
SkipCertVerify bool
|
||||
ClientSessionCache tls.ClientSessionCache
|
||||
ClientXSessionCache xtls.ClientSessionCache
|
||||
Password string
|
||||
ALPN []string
|
||||
ServerName string
|
||||
SkipCertVerify bool
|
||||
Flow string
|
||||
FlowShow bool
|
||||
}
|
||||
|
||||
type WebsocketOption struct {
|
||||
@ -65,28 +66,22 @@ type Trojan struct {
|
||||
hexPassword []byte
|
||||
}
|
||||
|
||||
func (t *Trojan) GetFlow() string {
|
||||
return t.option.Flow
|
||||
}
|
||||
|
||||
func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) {
|
||||
alpn := defaultALPN
|
||||
if len(t.option.ALPN) != 0 {
|
||||
alpn = t.option.ALPN
|
||||
}
|
||||
switch t.option.Flow {
|
||||
case XRD, XRO:
|
||||
case vless.XRO, vless.XRD, vless.XRS:
|
||||
xtlsConfig := &xtls.Config{
|
||||
NextProtos: alpn,
|
||||
MinVersion: xtls.VersionTLS12,
|
||||
InsecureSkipVerify: t.option.SkipCertVerify,
|
||||
ServerName: t.option.ServerName,
|
||||
ClientSessionCache: t.option.ClientXSessionCache,
|
||||
}
|
||||
|
||||
xtlsConn := xtls.Client(conn, xtlsConfig)
|
||||
if err := xtlsConn.Handshake(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
if err := xtlsConn.HandshakeContext(ctx); err != nil {
|
||||
@ -99,7 +94,6 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) {
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: t.option.SkipCertVerify,
|
||||
ServerName: t.option.ServerName,
|
||||
ClientSessionCache: t.option.ClientSessionCache,
|
||||
}
|
||||
tlsConn := tls.Client(conn, tlsConfig)
|
||||
if err := tlsConn.Handshake(); err != nil {
|
||||
@ -139,7 +133,37 @@ func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption)
|
||||
})
|
||||
}
|
||||
|
||||
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 nil, 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)
|
||||
|
||||
|
@ -35,15 +35,6 @@ type DstAddr struct {
|
||||
Port uint
|
||||
}
|
||||
|
||||
// Config of vless
|
||||
type Config struct {
|
||||
UUID string
|
||||
AlterID uint16
|
||||
Security string
|
||||
Port string
|
||||
HostName string
|
||||
}
|
||||
|
||||
// Client is vless connection generator
|
||||
type Client struct {
|
||||
uuid *uuid.UUID
|
||||
|
Reference in New Issue
Block a user