feat: Update utls support.
* client-fingerprint is used to apply Utls for modifying ClientHello, it accepts "chrome","firefox","safari","ios","random" options. * Utls is currently support TLS transport in TCP/grpc/WS/HTTP for VLESS/Vmess and trojan.
This commit is contained in:
parent
d9d2ea41c0
commit
4d33fb9848
4 changed files with 47 additions and 22 deletions
|
@ -109,7 +109,7 @@ sniffer:
|
||||||
HTTP:
|
HTTP:
|
||||||
# 需要嗅探的端口
|
# 需要嗅探的端口
|
||||||
|
|
||||||
ports: [ 80, 8080-8880 ]
|
ports: [80, 8080-8880]
|
||||||
# 可覆盖 sniffer.override-destination
|
# 可覆盖 sniffer.override-destination
|
||||||
override-destination: true
|
override-destination: true
|
||||||
force-domain:
|
force-domain:
|
||||||
|
@ -155,7 +155,7 @@ tunnels:
|
||||||
- tcp/udp,127.0.0.1:6553,114.114.114.114:53,proxy
|
- tcp/udp,127.0.0.1:6553,114.114.114.114:53,proxy
|
||||||
- tcp,127.0.0.1:6666,rds.mysql.com:3306,vpn
|
- tcp,127.0.0.1:6666,rds.mysql.com:3306,vpn
|
||||||
# full yaml config
|
# full yaml config
|
||||||
- network: [ tcp, udp ]
|
- network: [tcp, udp]
|
||||||
address: 127.0.0.1:7777
|
address: 127.0.0.1:7777
|
||||||
target: target.com
|
target: target.com
|
||||||
proxy: proxy
|
proxy: proxy
|
||||||
|
@ -317,7 +317,7 @@ proxies:
|
||||||
# udp: true
|
# udp: true
|
||||||
# tls: true
|
# tls: true
|
||||||
# fingerprint: xxxx
|
# fingerprint: xxxx
|
||||||
# client-fingerprint: random # Available: "chrome","firefox","safari","random"
|
# client-fingerprint: chrome # Available: "chrome","firefox","safari","ios","random", currently only support TLS transport in TCP/GRPC/WS/HTTP for VLESS/Vmess and trojan.
|
||||||
# skip-cert-verify: true
|
# skip-cert-verify: true
|
||||||
# servername: example.com # priority over wss host
|
# servername: example.com # priority over wss host
|
||||||
# network: ws
|
# network: ws
|
||||||
|
@ -423,6 +423,7 @@ proxies:
|
||||||
server: server
|
server: server
|
||||||
port: 443
|
port: 443
|
||||||
password: yourpsk
|
password: yourpsk
|
||||||
|
# client-fingerprint: random # Available: "chrome","firefox","safari","random"
|
||||||
# fingerprint: xxxx
|
# fingerprint: xxxx
|
||||||
# udp: true
|
# udp: true
|
||||||
# sni: example.com # aka server name
|
# sni: example.com # aka server name
|
||||||
|
@ -802,7 +803,7 @@ listeners:
|
||||||
listen: 0.0.0.0
|
listen: 0.0.0.0
|
||||||
# rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules
|
# rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules
|
||||||
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时,这里的proxy名称必须合法,否则会出错)
|
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时,这里的proxy名称必须合法,否则会出错)
|
||||||
network: [ tcp, udp ]
|
network: [tcp, udp]
|
||||||
target: target.com
|
target: target.com
|
||||||
|
|
||||||
- name: tun-in-1
|
- name: tun-in-1
|
||||||
|
|
|
@ -116,15 +116,26 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.(*vmess.UConn).HandshakeContext(ctx)
|
||||||
|
return utlsConn, err
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tlsConn := tls.Client(conn, tlsConfig)
|
tlsConn := tls.Client(conn, tlsConfig)
|
||||||
|
|
||||||
// fix tls handshake not timeout
|
// fix tls handshake not timeout
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tlsConn, nil
|
err := tlsConn.HandshakeContext(ctx)
|
||||||
|
return tlsConn, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,12 +153,13 @@ func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
return vmess.StreamWebsocketConn(conn, &vmess.WebsocketConfig{
|
return vmess.StreamWebsocketConn(conn, &vmess.WebsocketConfig{
|
||||||
Host: wsOptions.Host,
|
Host: wsOptions.Host,
|
||||||
Port: wsOptions.Port,
|
Port: wsOptions.Port,
|
||||||
Path: wsOptions.Path,
|
Path: wsOptions.Path,
|
||||||
Headers: wsOptions.Headers,
|
Headers: wsOptions.Headers,
|
||||||
TLS: true,
|
TLS: true,
|
||||||
TLSConfig: tlsConfig,
|
TLSConfig: tlsConfig,
|
||||||
|
ClientFingerprint: t.option.ClientFingerprint,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,13 +36,8 @@ func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(cfg.ClientFingerprint) != 0 {
|
if len(cfg.ClientFingerprint) != 0 {
|
||||||
if fingerprint, exists := GetFingerprint(cfg.ClientFingerprint); exists {
|
utlsConn, valid := GetUtlsConnWithClientFingerprint(conn, cfg.ClientFingerprint, tlsConfig)
|
||||||
utlsConn := UClient(conn, tlsConfig, &utls.ClientHelloID{
|
if valid {
|
||||||
Client: fingerprint.Client,
|
|
||||||
Version: fingerprint.Version,
|
|
||||||
Seed: nil,
|
|
||||||
})
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -50,7 +45,6 @@ func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) {
|
||||||
return utlsConn, err
|
return utlsConn, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConn := tls.Client(conn, tlsConfig)
|
tlsConn := tls.Client(conn, tlsConfig)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
|
@ -59,3 +53,18 @@ func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) {
|
||||||
err := tlsConn.HandshakeContext(ctx)
|
err := tlsConn.HandshakeContext(ctx)
|
||||||
return tlsConn, err
|
return tlsConn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetUtlsConnWithClientFingerprint(conn net.Conn, ClientFingerprint string, tlsConfig *tls.Config) (net.Conn, bool) {
|
||||||
|
|
||||||
|
if fingerprint, exists := GetFingerprint(ClientFingerprint); exists {
|
||||||
|
utlsConn := UClient(conn, tlsConfig, &utls.ClientHelloID{
|
||||||
|
Client: fingerprint.Client,
|
||||||
|
Version: fingerprint.Version,
|
||||||
|
Seed: nil,
|
||||||
|
})
|
||||||
|
|
||||||
|
return utlsConn, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ func RollFingerprint() (*utls.ClientHelloID, bool) {
|
||||||
chooser, _ := weightedrand.NewChooser(
|
chooser, _ := weightedrand.NewChooser(
|
||||||
weightedrand.NewChoice("chrome", 6),
|
weightedrand.NewChoice("chrome", 6),
|
||||||
weightedrand.NewChoice("safari", 3),
|
weightedrand.NewChoice("safari", 3),
|
||||||
|
weightedrand.NewChoice("ios", 2),
|
||||||
weightedrand.NewChoice("firefox", 1),
|
weightedrand.NewChoice("firefox", 1),
|
||||||
)
|
)
|
||||||
initClient := chooser.Pick()
|
initClient := chooser.Pick()
|
||||||
|
@ -50,6 +51,7 @@ var Fingerprints = map[string]*utls.ClientHelloID{
|
||||||
"chrome": &utls.HelloChrome_Auto,
|
"chrome": &utls.HelloChrome_Auto,
|
||||||
"firefox": &utls.HelloFirefox_Auto,
|
"firefox": &utls.HelloFirefox_Auto,
|
||||||
"safari": &utls.HelloSafari_Auto,
|
"safari": &utls.HelloSafari_Auto,
|
||||||
|
"ios": &utls.HelloIOS_Auto,
|
||||||
"randomized": &utls.HelloRandomized,
|
"randomized": &utls.HelloRandomized,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +66,7 @@ func CopyConfig(c *tls.Config) *utls.Config {
|
||||||
|
|
||||||
// WebsocketHandshake basically calls UConn.Handshake inside it but it will only send
|
// WebsocketHandshake basically calls UConn.Handshake inside it but it will only send
|
||||||
// http/1.1 in its ALPN.
|
// http/1.1 in its ALPN.
|
||||||
|
// Copy from https://github.com/XTLS/Xray-core/blob/main/transport/internet/tls/tls.go
|
||||||
func (c *UConn) WebsocketHandshake() error {
|
func (c *UConn) WebsocketHandshake() error {
|
||||||
// Build the handshake state. This will apply every variable of the TLS of the
|
// Build the handshake state. This will apply every variable of the TLS of the
|
||||||
// fingerprint in the UConn
|
// fingerprint in the UConn
|
||||||
|
|
Loading…
Reference in a new issue