mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-30 22:59:00 +07:00
feat: add uTLS support (#94)
* feat: add uTLS * feat: change `Utls.Imitate` to `UtlsImitate` * feat: add desc and example config * chore: refine code and docs * docs(example.dae): adjust order --------- Co-authored-by: mzz2017 <2017@duck.com>
This commit is contained in:
@ -39,6 +39,8 @@ type GlobalOption struct {
|
||||
CheckTolerance time.Duration
|
||||
CheckDnsTcp bool
|
||||
AllowInsecure bool
|
||||
TlsImplementation string
|
||||
UtlsImitate string
|
||||
}
|
||||
|
||||
type InstanceOption struct {
|
||||
|
@ -48,11 +48,12 @@ func NewTrojan(option *dialer.GlobalOption, iOption dialer.InstanceOption, link
|
||||
func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
d := direct.FullconeDirect // Trojan Proxy supports full-cone.
|
||||
u := url.URL{
|
||||
Scheme: "tls",
|
||||
Scheme: option.TlsImplementation,
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{s.Sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
"utlsImitate": []string{option.UtlsImitate},
|
||||
}.Encode(),
|
||||
}
|
||||
var err error
|
||||
|
@ -110,11 +110,12 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
|
||||
sni = s.Host
|
||||
}
|
||||
u := url.URL{
|
||||
Scheme: "tls",
|
||||
Scheme: option.TlsImplementation,
|
||||
Host: net.JoinHostPort(s.Add, s.Port),
|
||||
RawQuery: url.Values{
|
||||
"sni": []string{sni},
|
||||
"allowInsecure": []string{common.BoolToString(s.AllowInsecure)},
|
||||
"utlsImitate": []string{option.UtlsImitate},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err = tls.NewTls(u.String(), d)
|
||||
|
@ -3,17 +3,22 @@ package tls
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
"net/url"
|
||||
|
||||
"github.com/mzz2017/softwind/netproxy"
|
||||
utls "github.com/refraction-networking/utls"
|
||||
)
|
||||
|
||||
// Tls is a base Tls struct
|
||||
type Tls struct {
|
||||
dialer netproxy.Dialer
|
||||
addr string
|
||||
serverName string
|
||||
skipVerify bool
|
||||
tlsConfig *tls.Config
|
||||
dialer netproxy.Dialer
|
||||
addr string
|
||||
serverName string
|
||||
skipVerify bool
|
||||
tlsImplentation string
|
||||
utlsImitate string
|
||||
|
||||
tlsConfig *tls.Config
|
||||
}
|
||||
|
||||
// NewTls returns a Tls infra.
|
||||
@ -24,12 +29,14 @@ func NewTls(s string, d netproxy.Dialer) (*Tls, error) {
|
||||
}
|
||||
|
||||
t := &Tls{
|
||||
dialer: d,
|
||||
addr: u.Host,
|
||||
dialer: d,
|
||||
addr: u.Host,
|
||||
tlsImplentation: u.Scheme,
|
||||
}
|
||||
|
||||
query := u.Query()
|
||||
t.serverName = query.Get("sni")
|
||||
t.utlsImitate = query.Get("utlsImitate")
|
||||
|
||||
// skipVerify
|
||||
if query.Get("allowInsecure") == "true" || query.Get("allowInsecure") == "1" ||
|
||||
@ -72,11 +79,35 @@ func (s *Tls) DialTcp(addr string) (conn netproxy.Conn, err error) {
|
||||
return nil, fmt.Errorf("[Tls]: dial to %s: %w", s.addr, err)
|
||||
}
|
||||
|
||||
tlsConn := tls.Client(&netproxy.FakeNetConn{
|
||||
Conn: rc,
|
||||
LAddr: nil,
|
||||
RAddr: nil,
|
||||
}, s.tlsConfig)
|
||||
var tlsConn interface {
|
||||
netproxy.Conn
|
||||
Handshake() error
|
||||
}
|
||||
|
||||
switch s.tlsImplentation {
|
||||
case "tls":
|
||||
tlsConn = tls.Client(&netproxy.FakeNetConn{
|
||||
Conn: rc,
|
||||
LAddr: nil,
|
||||
RAddr: nil,
|
||||
}, s.tlsConfig)
|
||||
|
||||
case "utls":
|
||||
clientHelloID, err := nameToUtlsClientHelloID(s.utlsImitate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tlsConn = utls.UClient(&netproxy.FakeNetConn{
|
||||
Conn: rc,
|
||||
LAddr: nil,
|
||||
RAddr: nil,
|
||||
}, uTLSConfigFromTLSConfig(s.tlsConfig), *clientHelloID)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown tls implementation: %v", s.tlsImplentation)
|
||||
}
|
||||
|
||||
if err := tlsConn.Handshake(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
63
component/outbound/transport/tls/utls.go
Normal file
63
component/outbound/transport/tls/utls.go
Normal file
@ -0,0 +1,63 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
|
||||
utls "github.com/refraction-networking/utls"
|
||||
)
|
||||
|
||||
func uTLSConfigFromTLSConfig(config *tls.Config) *utls.Config {
|
||||
return &utls.Config{
|
||||
ServerName: config.ServerName,
|
||||
InsecureSkipVerify: config.InsecureSkipVerify,
|
||||
}
|
||||
}
|
||||
|
||||
var clientHelloIDMap = map[string]*utls.ClientHelloID{
|
||||
"randomized": &utls.HelloRandomized,
|
||||
"randomizedalpn": &utls.HelloRandomizedALPN,
|
||||
"randomizednoalpn": &utls.HelloRandomizedNoALPN,
|
||||
"firefox_auto": &utls.HelloFirefox_Auto,
|
||||
"firefox_55": &utls.HelloFirefox_55,
|
||||
"firefox_56": &utls.HelloFirefox_56,
|
||||
"firefox_63": &utls.HelloFirefox_63,
|
||||
"firefox_65": &utls.HelloFirefox_65,
|
||||
"firefox_99": &utls.HelloFirefox_99,
|
||||
"firefox_102": &utls.HelloFirefox_102,
|
||||
"firefox_105": &utls.HelloFirefox_105,
|
||||
"chrome_auto": &utls.HelloChrome_Auto,
|
||||
"chrome_58": &utls.HelloChrome_58,
|
||||
"chrome_62": &utls.HelloChrome_62,
|
||||
"chrome_70": &utls.HelloChrome_70,
|
||||
"chrome_72": &utls.HelloChrome_72,
|
||||
"chrome_83": &utls.HelloChrome_83,
|
||||
"chrome_87": &utls.HelloChrome_87,
|
||||
"chrome_96": &utls.HelloChrome_96,
|
||||
"chrome_100": &utls.HelloChrome_100,
|
||||
"chrome_102": &utls.HelloChrome_102,
|
||||
"ios_auto": &utls.HelloIOS_Auto,
|
||||
"ios_11_1": &utls.HelloIOS_11_1,
|
||||
"ios_12_1": &utls.HelloIOS_12_1,
|
||||
"ios_13": &utls.HelloIOS_13,
|
||||
"ios_14": &utls.HelloIOS_14,
|
||||
"android_11_okhttp": &utls.HelloAndroid_11_OkHttp,
|
||||
"edge_auto": &utls.HelloEdge_Auto,
|
||||
"edge_85": &utls.HelloEdge_85,
|
||||
"edge_106": &utls.HelloEdge_106,
|
||||
"safari_auto": &utls.HelloSafari_Auto,
|
||||
"safari_16_0": &utls.HelloSafari_16_0,
|
||||
"360_auto": &utls.Hello360_Auto,
|
||||
"360_7_5": &utls.Hello360_7_5,
|
||||
"360_11_0": &utls.Hello360_11_0,
|
||||
"qq_auto": &utls.HelloQQ_Auto,
|
||||
"qq_11_1": &utls.HelloQQ_11_1,
|
||||
}
|
||||
|
||||
func nameToUtlsClientHelloID(name string) (*utls.ClientHelloID, error) {
|
||||
clientHelloID, ok := clientHelloIDMap[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown uTLS Client Hello ID: %s", name)
|
||||
}
|
||||
return clientHelloID, nil
|
||||
}
|
Reference in New Issue
Block a user