mihomo/transport/trojan/trojan.go

350 lines
7.4 KiB
Go
Raw Normal View History

2020-03-19 20:26:53 +08:00
package trojan
import (
"context"
2020-03-19 20:26:53 +08:00
"crypto/sha256"
"crypto/tls"
"encoding/binary"
"encoding/hex"
"errors"
2022-03-30 00:15:39 +08:00
"fmt"
2020-03-20 00:02:05 +08:00
"io"
2020-03-19 20:26:53 +08:00
"net"
2021-10-16 20:19:59 +08:00
"net/http"
2020-03-19 20:26:53 +08:00
"sync"
2021-09-20 21:02:18 +08:00
"github.com/Dreamacro/clash/common/pool"
tlsC "github.com/Dreamacro/clash/component/tls"
C "github.com/Dreamacro/clash/constant"
2021-05-13 22:18:49 +08:00
"github.com/Dreamacro/clash/transport/socks5"
2022-03-30 00:15:39 +08:00
"github.com/Dreamacro/clash/transport/vless"
2021-10-16 20:19:59 +08:00
"github.com/Dreamacro/clash/transport/vmess"
2022-03-30 00:15:39 +08:00
xtls "github.com/xtls/go"
2020-03-19 20:26:53 +08:00
)
2020-03-20 00:02:05 +08:00
const (
// max packet length
maxLength = 8192
)
2020-03-19 20:26:53 +08:00
var (
defaultALPN = []string{"h2", "http/1.1"}
defaultWebsocketALPN = []string{"http/1.1"}
crlf = []byte{'\r', '\n'}
2020-03-19 20:26:53 +08:00
)
type Command = byte
2022-03-30 00:15:39 +08:00
const (
2020-03-19 20:26:53 +08:00
CommandTCP byte = 1
CommandUDP byte = 3
2022-03-30 00:15:39 +08:00
// for XTLS
commandXRD byte = 0xf0 // XTLS direct mode
commandXRO byte = 0xf1 // XTLS origin mode
2020-03-19 20:26:53 +08:00
)
type Option struct {
Password string
ALPN []string
ServerName string
SkipCertVerify bool
Fingerprint string
Flow string
FlowShow bool
ClientFingerprint string
2020-03-19 20:26:53 +08:00
}
2021-10-16 20:19:59 +08:00
type WebsocketOption struct {
Host string
Port string
Path string
Headers http.Header
}
2020-03-19 20:26:53 +08:00
type Trojan struct {
option *Option
hexPassword []byte
}
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 vless.XRO, vless.XRD, vless.XRS:
xtlsConfig := &xtls.Config{
NextProtos: alpn,
MinVersion: xtls.VersionTLS12,
InsecureSkipVerify: t.option.SkipCertVerify,
ServerName: t.option.ServerName,
}
2022-03-30 00:15:39 +08:00
2022-07-11 13:42:28 +08:00
if len(t.option.Fingerprint) == 0 {
xtlsConfig = tlsC.GetGlobalXTLSConfig(xtlsConfig)
2022-07-11 13:42:28 +08:00
} else {
var err error
if xtlsConfig, err = tlsC.GetSpecifiedFingerprintXTLSConfig(xtlsConfig, t.option.Fingerprint); err != nil {
return nil, err
}
}
xtlsConn := xtls.Client(conn, xtlsConfig)
2022-03-30 00:15:39 +08:00
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
defer cancel()
if err := xtlsConn.HandshakeContext(ctx); 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,
}
2022-07-11 13:42:28 +08:00
if len(t.option.Fingerprint) == 0 {
tlsConfig = tlsC.GetGlobalTLSConfig(tlsConfig)
2022-07-11 13:42:28 +08:00
} else {
var err error
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, t.option.Fingerprint); err != nil {
return nil, err
}
}
if len(t.option.ClientFingerprint) != 0 {
utlsConn, valid := vmess.GetUtlsConnWithClientFingerprint(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
}
}
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
2020-03-19 20:26:53 +08:00
}
}
2021-10-16 20:19:59 +08:00
func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption) (net.Conn, error) {
alpn := defaultWebsocketALPN
2021-10-16 20:19:59 +08:00
if len(t.option.ALPN) != 0 {
alpn = t.option.ALPN
}
tlsConfig := &tls.Config{
NextProtos: alpn,
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: t.option.SkipCertVerify,
ServerName: t.option.ServerName,
}
return vmess.StreamWebsocketConn(conn, &vmess.WebsocketConfig{
Host: wsOptions.Host,
Port: wsOptions.Port,
Path: wsOptions.Path,
Headers: wsOptions.Headers,
TLS: true,
TLSConfig: tlsConfig,
ClientFingerprint: t.option.ClientFingerprint,
2021-10-16 20:19:59 +08:00
})
}
2022-03-30 00:15:39 +08:00
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 {
2022-04-09 21:29:19 +08:00
return conn, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", t.option.Flow)
2022-03-30 00:15:39 +08:00
}
}
return conn, nil
}
2020-03-20 00:02:05 +08:00
func (t *Trojan) WriteHeader(w io.Writer, command Command, socks5Addr []byte) error {
2022-03-30 00:15:39 +08:00
if command == CommandTCP {
if t.option.Flow == vless.XRD {
command = commandXRD
} else if t.option.Flow == vless.XRO {
command = commandXRO
}
}
2021-09-20 21:02:18 +08:00
buf := pool.GetBuffer()
defer pool.PutBuffer(buf)
2020-03-19 20:26:53 +08:00
buf.Write(t.hexPassword)
buf.Write(crlf)
buf.WriteByte(command)
buf.Write(socks5Addr)
buf.Write(crlf)
2020-03-20 00:02:05 +08:00
_, err := w.Write(buf.Bytes())
2020-03-19 20:26:53 +08:00
return err
}
func (t *Trojan) PacketConn(conn net.Conn) net.PacketConn {
2020-03-20 00:02:05 +08:00
return &PacketConn{
Conn: conn,
}
2020-03-19 20:26:53 +08:00
}
2020-03-20 00:02:05 +08:00
func writePacket(w io.Writer, socks5Addr, payload []byte) (int, error) {
2021-09-20 21:02:18 +08:00
buf := pool.GetBuffer()
defer pool.PutBuffer(buf)
2020-03-19 20:26:53 +08:00
buf.Write(socks5Addr)
binary.Write(buf, binary.BigEndian, uint16(len(payload)))
buf.Write(crlf)
buf.Write(payload)
2020-03-20 00:02:05 +08:00
return w.Write(buf.Bytes())
}
func WritePacket(w io.Writer, socks5Addr, payload []byte) (int, error) {
if len(payload) <= maxLength {
return writePacket(w, socks5Addr, payload)
}
offset := 0
total := len(payload)
for {
cursor := offset + maxLength
if cursor > total {
cursor = total
}
n, err := writePacket(w, socks5Addr, payload[offset:cursor])
if err != nil {
return offset + n, err
}
offset = cursor
if offset == total {
break
}
}
return total, nil
2020-03-19 20:26:53 +08:00
}
2020-03-20 00:02:05 +08:00
func ReadPacket(r io.Reader, payload []byte) (net.Addr, int, int, error) {
addr, err := socks5.ReadAddr(r, payload)
if err != nil {
return nil, 0, 0, errors.New("read addr error")
}
uAddr := addr.UDPAddr()
if uAddr == nil {
return nil, 0, 0, errors.New("parse addr error")
}
2020-03-20 00:02:05 +08:00
if _, err = io.ReadFull(r, payload[:2]); err != nil {
return nil, 0, 0, errors.New("read length error")
}
total := int(binary.BigEndian.Uint16(payload[:2]))
if total > maxLength {
return nil, 0, 0, errors.New("packet invalid")
}
// read crlf
if _, err = io.ReadFull(r, payload[:2]); err != nil {
return nil, 0, 0, errors.New("read crlf error")
2020-03-19 20:26:53 +08:00
}
2020-03-20 00:02:05 +08:00
length := len(payload)
if total < length {
length = total
2020-03-19 20:26:53 +08:00
}
2020-03-20 00:02:05 +08:00
if _, err = io.ReadFull(r, payload[:length]); err != nil {
return nil, 0, 0, errors.New("read packet error")
2020-03-19 20:26:53 +08:00
}
2020-03-20 00:02:05 +08:00
return uAddr, length, total - length, nil
2020-03-19 20:26:53 +08:00
}
func New(option *Option) *Trojan {
return &Trojan{option, hexSha224([]byte(option.Password))}
}
type PacketConn struct {
net.Conn
2020-03-20 00:02:05 +08:00
remain int
rAddr net.Addr
mux sync.Mutex
2020-03-19 20:26:53 +08:00
}
func (pc *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
return WritePacket(pc, socks5.ParseAddr(addr.String()), b)
}
func (pc *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
2020-03-20 00:02:05 +08:00
pc.mux.Lock()
defer pc.mux.Unlock()
if pc.remain != 0 {
length := len(b)
if pc.remain < length {
length = pc.remain
}
n, err := pc.Conn.Read(b[:length])
if err != nil {
return 0, nil, err
}
pc.remain -= n
addr := pc.rAddr
if pc.remain == 0 {
pc.rAddr = nil
}
return n, addr, nil
}
addr, n, remain, err := ReadPacket(pc.Conn, b)
2020-03-19 20:26:53 +08:00
if err != nil {
2020-03-20 00:02:05 +08:00
return 0, nil, err
}
if remain != 0 {
pc.remain = remain
pc.rAddr = addr
2020-03-19 20:26:53 +08:00
}
2020-03-20 00:02:05 +08:00
return n, addr, nil
2020-03-19 20:26:53 +08:00
}
func hexSha224(data []byte) []byte {
buf := make([]byte, 56)
hash := sha256.New224()
hash.Write(data)
hex.Encode(buf, hash.Sum(nil))
return buf
}