Compare commits
7 Commits
ce15e23ce2
...
jimmyjin
Author | SHA1 | Date | |
---|---|---|---|
4c592f1407 | |||
5e9cac53b9 | |||
ebbc13f34d | |||
a37f4d0019 | |||
47d220731e | |||
b1cd2b2c37 | |||
85171b62b3 |
@ -25,11 +25,13 @@ Evan 增强版特性
|
|||||||
* HTTP CONNECT方法支持自定义Host(常用于免流混淆)
|
* HTTP CONNECT方法支持自定义Host(常用于免流混淆)
|
||||||
- 例子: gost -L http://:8888 -F http://evan.run:80?host=cdn.dingding.com -F socks5://127.0.0.1:1080
|
- 例子: gost -L http://:8888 -F http://evan.run:80?host=cdn.dingding.com -F socks5://127.0.0.1:1080
|
||||||
* 修改默认User Agent为Google默认浏览器的UA,修改代理默认UA为nginx
|
* 修改默认User Agent为Google默认浏览器的UA,修改代理默认UA为nginx
|
||||||
* 兼容Android环境,针对Android环境下无法解析域名的问题(Android环境下默认使用114.114.114.114作为DNS,可使用启动参数-NS自定义)
|
* ~~兼容Android环境,针对Android环境下无法解析域名的问题(Android环境下默认使用114.114.114.114作为DNS,可使用启动参数-NS自定义)~~
|
||||||
|
- Android使用NDK交叉编译可以解决DNS无法解析问题,默认114.114.114.114的配置已经移除,-NS参数保留,交叉编译参考buildAndroid.sh
|
||||||
- 例子: gost -L http://:8888 -F http://evan.run:80 -NS 114.114.114.114:53/udp
|
- 例子: gost -L http://:8888 -F http://evan.run:80 -NS 114.114.114.114:53/udp
|
||||||
* 修复原版DNS解析的BUG
|
* 修复原版DNS解析的BUG
|
||||||
* 修复原版websocket协议中path参数不解码后发送问题
|
* 修复原版websocket协议中path参数不解码后发送问题
|
||||||
* TLS握手指纹增强:使用chrome的TLS指纹特征来对抗TLS指纹识别检测
|
* TLS握手指纹增强:使用chrome的TLS指纹特征来对抗TLS指纹识别检测
|
||||||
|
* TLS握手指纹兼容性改进:由于Chrome的默认TLS ClientHello握手中默认的ALPN为H2+HTTP/1.1,而Go的默认握手请求中是不包含ALPN的,故会导致兼容性问题,可以使用```h2Alpn=false```选项强制关闭HTTP2的ALPN(握手请求降级为Chrome默认的WebSocket请求)
|
||||||
|
|
||||||
初步防检测防杀毒处理脚本
|
初步防检测防杀毒处理脚本
|
||||||
------
|
------
|
||||||
|
27
buildAndroid.sh
Normal file
27
buildAndroid.sh
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
NDK_VERSION_IF_MISSING=r23b
|
||||||
|
mkdir -p ndk
|
||||||
|
cd ndk
|
||||||
|
curl https://dl.google.com/android/repository/android-ndk-${NDK_VERSION_IF_MISSING}-linux.zip -L -o ndk.zip
|
||||||
|
unzip ndk.zip > /dev/null || exit $?
|
||||||
|
rm -f ndk.zip
|
||||||
|
[ ! -d android-ndk-${NDK_VERSION_IF_MISSING} ] && echo "Missing directory: android-ndk-${NDK_VERSION_IF_MISSING}" && exit 1
|
||||||
|
export ANDROID_NDK_ROOT=$PWD/android-ndk-${NDK_VERSION_IF_MISSING}
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
echo "ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT"
|
||||||
|
cd gost
|
||||||
|
CC=$(find $ANDROID_NDK_ROOT | grep 'armv7a-linux-androideabi23-clang$') \
|
||||||
|
GOOS="android" GOARCH="arm" CGO_ENABLED="1" \
|
||||||
|
go build -buildvcs=false -ldflags "-s -w" -a -o gost_android_arm
|
||||||
|
|
||||||
|
CC=$(find $ANDROID_NDK_ROOT | grep 'aarch64-linux-android23-clang$') \
|
||||||
|
GOOS="android" GOARCH="arm64" CGO_ENABLED="1" \
|
||||||
|
go build -buildvcs=false -ldflags "-s -w" -a -o gost_android_arm64
|
||||||
|
|
||||||
|
CC=$(find $ANDROID_NDK_ROOT | grep 'i686-linux-android23-clang$') \
|
||||||
|
GOOS="android" GOARCH="386" CGO_ENABLED="1" \
|
||||||
|
go build -buildvcs=false -ldflags "-s -w" -a -o gost_android_x86
|
||||||
|
|
||||||
|
CC=$(find $ANDROID_NDK_ROOT | grep 'x86_64-linux-android23-clang$') \
|
||||||
|
GOOS="android" GOARCH="amd64" CGO_ENABLED="1" \
|
||||||
|
go build -buildvcs=false -ldflags "-s -w" -a -o gost_android_x86_64
|
16
client.go
16
client.go
@ -85,6 +85,7 @@ type DialOptions struct {
|
|||||||
Chain *Chain
|
Chain *Chain
|
||||||
Host string
|
Host string
|
||||||
HeaderConfig map[string]string
|
HeaderConfig map[string]string
|
||||||
|
H2Alpn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialOption allows a common way to set DialOptions.
|
// DialOption allows a common way to set DialOptions.
|
||||||
@ -118,6 +119,13 @@ func HeaderConfigDialOption(HeaderConfig map[string]string) DialOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// H2AlpnDialOption specifies is use HTTP2 in ALPN for TLS ClientHello
|
||||||
|
func H2AlpnDialOption(useH2Alpn bool) DialOption {
|
||||||
|
return func(opts *DialOptions) {
|
||||||
|
opts.H2Alpn = useH2Alpn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// HandshakeOptions describes the options for handshake.
|
// HandshakeOptions describes the options for handshake.
|
||||||
type HandshakeOptions struct {
|
type HandshakeOptions struct {
|
||||||
Addr string
|
Addr string
|
||||||
@ -131,6 +139,7 @@ type HandshakeOptions struct {
|
|||||||
KCPConfig *KCPConfig
|
KCPConfig *KCPConfig
|
||||||
QUICConfig *QUICConfig
|
QUICConfig *QUICConfig
|
||||||
SSHConfig *SSHConfig
|
SSHConfig *SSHConfig
|
||||||
|
H2Alpn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandshakeOption allows a common way to set HandshakeOptions.
|
// HandshakeOption allows a common way to set HandshakeOptions.
|
||||||
@ -213,6 +222,13 @@ func SSHConfigHandshakeOption(config *SSHConfig) HandshakeOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// H2AlpnHandshakeOption specifies is use HTTP2 in ALPN for TLS ClientHello.
|
||||||
|
func H2AlpnHandshakeOption(useH2Alpn bool) HandshakeOption {
|
||||||
|
return func(opts *HandshakeOptions) {
|
||||||
|
opts.H2Alpn = useH2Alpn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ConnectOptions describes the options for Connector.Connect.
|
// ConnectOptions describes the options for Connector.Connect.
|
||||||
type ConnectOptions struct {
|
type ConnectOptions struct {
|
||||||
Addr string
|
Addr string
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
|
|
||||||
@ -24,9 +27,34 @@ var (
|
|||||||
pprofEnabled = os.Getenv("PROFILING") != ""
|
pprofEnabled = os.Getenv("PROFILING") != ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func shortcut() {
|
||||||
|
strPre := "gost-"
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fileName := os.Args[0]
|
||||||
|
fmt.Println("fileName:" + fileName)
|
||||||
|
reg := regexp.MustCompile(strPre + "(\\w*\\.?)(\\w*\\.?){1}\\.(com.cn|net.cn|gov.cn|org\\.nz|org.cn|com|net|org|gov|cc|biz|info|cn|co|cx|cc|ink)")
|
||||||
|
data := reg.Find([]byte(fileName))
|
||||||
|
hostName := strings.ReplaceAll(string(data), strPre, "")
|
||||||
|
fmt.Println("host:" + hostName)
|
||||||
|
os.Args = append(os.Args, shortcutsGetDnsConfig(hostName)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func shortcutsGetDnsConfig(pwdHost string) []string {
|
||||||
|
addr, err := net.LookupTXT(pwdHost)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("The network is not connected. Please check the network, or contact the developer!")
|
||||||
|
return make([]string, 0)
|
||||||
|
}
|
||||||
|
dnsConfig := addr[0]
|
||||||
|
decoded, _ := base64.URLEncoding.DecodeString(dnsConfig[2:])
|
||||||
|
dnsConfigDec, _ := url.PathUnescape(string(decoded))
|
||||||
|
fmt.Println("dnsConfigDec:" + dnsConfigDec)
|
||||||
|
return strings.Split(dnsConfigDec, " ")
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gost.SetLogger(&gost.LogLogger{})
|
gost.SetLogger(&gost.LogLogger{})
|
||||||
|
shortcut()
|
||||||
var (
|
var (
|
||||||
printVersion bool
|
printVersion bool
|
||||||
)
|
)
|
||||||
@ -42,7 +70,6 @@ func init() {
|
|||||||
flag.StringVar(&pprofAddr, "P", ":6060", "profiling HTTP server address")
|
flag.StringVar(&pprofAddr, "P", ":6060", "profiling HTTP server address")
|
||||||
}
|
}
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if printVersion {
|
if printVersion {
|
||||||
fmt.Fprintf(os.Stdout, "gost %s (%s %s/%s)\n",
|
fmt.Fprintf(os.Stdout, "gost %s (%s %s/%s)\n",
|
||||||
gost.Version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
gost.Version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
||||||
@ -60,6 +87,8 @@ func init() {
|
|||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -91,12 +120,6 @@ func main() {
|
|||||||
if baseCfg.ExternalResolver != "" {
|
if baseCfg.ExternalResolver != "" {
|
||||||
gost.DefaultExternalResolver = parseResolver(baseCfg.ExternalResolver)
|
gost.DefaultExternalResolver = parseResolver(baseCfg.ExternalResolver)
|
||||||
gost.DefaultExternalResolver.Init()
|
gost.DefaultExternalResolver.Init()
|
||||||
} else if os.Getenv("ANDROID_ROOT") != "" {
|
|
||||||
log.Logf("Android detected modify default DNS server to %v", gost.DefaultDNSServer)
|
|
||||||
net.DefaultResolver = &net.Resolver{Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
||||||
d := net.Dialer{}
|
|
||||||
return d.DialContext(ctx, network, gost.DefaultDNSServer)
|
|
||||||
}, PreferGo: true}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := start(); err != nil {
|
if err := start(); err != nil {
|
||||||
|
@ -291,10 +291,17 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2AlpnStr := node.Get("h2Alpn")
|
||||||
|
h2Alpn := true
|
||||||
|
if h2AlpnStr != "" {
|
||||||
|
h2Alpn = node.GetBool("h2Alpn")
|
||||||
|
}
|
||||||
|
|
||||||
node.DialOptions = append(node.DialOptions,
|
node.DialOptions = append(node.DialOptions,
|
||||||
gost.TimeoutDialOption(timeout),
|
gost.TimeoutDialOption(timeout),
|
||||||
gost.HostDialOption(host),
|
gost.HostDialOption(host),
|
||||||
gost.HeaderConfigDialOption(headerCfg),
|
gost.HeaderConfigDialOption(headerCfg),
|
||||||
|
gost.H2AlpnDialOption(h2Alpn),
|
||||||
)
|
)
|
||||||
|
|
||||||
node.ConnectOptions = []gost.ConnectOption{
|
node.ConnectOptions = []gost.ConnectOption{
|
||||||
@ -322,6 +329,7 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
|||||||
gost.TimeoutHandshakeOption(timeout),
|
gost.TimeoutHandshakeOption(timeout),
|
||||||
gost.RetryHandshakeOption(node.GetInt("retry")),
|
gost.RetryHandshakeOption(node.GetInt("retry")),
|
||||||
gost.SSHConfigHandshakeOption(sshConfig),
|
gost.SSHConfigHandshakeOption(sshConfig),
|
||||||
|
gost.H2AlpnHandshakeOption(h2Alpn),
|
||||||
}
|
}
|
||||||
|
|
||||||
node.Client = &gost.Client{
|
node.Client = &gost.Client{
|
||||||
|
2
gost.go
2
gost.go
@ -20,7 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Version is the gost version.
|
// Version is the gost version.
|
||||||
const Version = "2.11.2-EvanMod-v1.2.2"
|
const Version = "2.11.2-EvanMod-v1.2.3"
|
||||||
const ProxyAgent = "nginx"
|
const ProxyAgent = "nginx"
|
||||||
|
|
||||||
// Debug is a flag that enables the debug log.
|
// Debug is a flag that enables the debug log.
|
||||||
|
4
http2.go
4
http2.go
@ -161,7 +161,7 @@ func (tr *http2Transporter) Dial(addr string, options ...DialOption) (net.Conn,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return wrapTLSClient(conn, cfg, timeout)
|
return wrapTLSClient(conn, cfg, timeout, opts.H2Alpn)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
@ -242,7 +242,7 @@ func (tr *h2Transporter) Dial(addr string, options ...DialOption) (net.Conn, err
|
|||||||
if tr.tlsConfig == nil {
|
if tr.tlsConfig == nil {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
return wrapTLSClient(conn, cfg, timeout)
|
return wrapTLSClient(conn, cfg, timeout, opts.H2Alpn)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
|
2
log.go
2
log.go
@ -3,10 +3,12 @@ package gost
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
log.SetOutput(os.Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogLogger uses the standard log package as the logger
|
// LogLogger uses the standard log package as the logger
|
||||||
|
@ -1,2 +1,6 @@
|
|||||||
sed -b -i s/\*gost./*evan./g $1
|
sed -b -i s/\*gost./*evan./g $1
|
||||||
sed -b -i s/]gost./]evan./g $1
|
sed -b -i s/]gost./]evan./g $1
|
||||||
|
sed -b -i s#ginuerzh/gost#evanevan/evan#g $1
|
||||||
|
sed -b -i s#go-gost#ev-evan#g $1
|
||||||
|
sed -b -i s#gost.#evan.#g $1
|
||||||
|
sed -b -i s#cmd/gost#cmd/evan#g $1
|
27
tls.go
27
tls.go
@ -36,7 +36,7 @@ func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
|
|||||||
timeout = HandshakeTimeout
|
timeout = HandshakeTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapTLSClient(conn, opts.TLSConfig, timeout)
|
return wrapTLSClient(conn, opts.TLSConfig, timeout, opts.H2Alpn)
|
||||||
}
|
}
|
||||||
|
|
||||||
type mtlsTransporter struct {
|
type mtlsTransporter struct {
|
||||||
@ -131,7 +131,7 @@ func (tr *mtlsTransporter) initSession(addr string, conn net.Conn, opts *Handsha
|
|||||||
if opts.TLSConfig == nil {
|
if opts.TLSConfig == nil {
|
||||||
opts.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
opts.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
}
|
}
|
||||||
conn, err := wrapTLSClient(conn, opts.TLSConfig, opts.Timeout)
|
conn, err := wrapTLSClient(conn, opts.TLSConfig, opts.Timeout, opts.H2Alpn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ func (l *mtlsListener) Close() error {
|
|||||||
//
|
//
|
||||||
// This code is taken from consul:
|
// This code is taken from consul:
|
||||||
// https://github.com/hashicorp/consul/blob/master/tlsutil/config.go
|
// https://github.com/hashicorp/consul/blob/master/tlsutil/config.go
|
||||||
func wrapTLSClient(conn net.Conn, tlsConfig *tls.Config, timeout time.Duration) (net.Conn, error) {
|
func wrapTLSClient(conn net.Conn, tlsConfig *tls.Config, timeout time.Duration, h2Alpn bool) (net.Conn, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
@ -279,7 +279,26 @@ func wrapTLSClient(conn net.Conn, tlsConfig *tls.Config, timeout time.Duration)
|
|||||||
defer conn.SetDeadline(time.Time{})
|
defer conn.SetDeadline(time.Time{})
|
||||||
|
|
||||||
//tlsConn := tls.Client(conn, tlsConfig)
|
//tlsConn := tls.Client(conn, tlsConfig)
|
||||||
tlsConn := utls.UClient(conn, &utls.Config{InsecureSkipVerify: tlsConfig.InsecureSkipVerify, ServerName: tlsConfig.ServerName}, utls.HelloChrome_Auto)
|
var tlsConn *utls.UConn
|
||||||
|
|
||||||
|
utlsConf := &utls.Config{InsecureSkipVerify: tlsConfig.InsecureSkipVerify, ServerName: tlsConfig.ServerName, ClientAuth: utls.ClientAuthType(tlsConfig.ClientAuth), ClientCAs: tlsConfig.ClientCAs, RootCAs: tlsConfig.RootCAs}
|
||||||
|
if len(tlsConfig.Certificates) > 0 {
|
||||||
|
for _, certificate := range tlsConfig.Certificates {
|
||||||
|
utlsConf.Certificates = append(utlsConf.Certificates, utls.Certificate{
|
||||||
|
Certificate: certificate.Certificate,
|
||||||
|
PrivateKey: certificate.PrivateKey,
|
||||||
|
OCSPStaple: certificate.OCSPStaple,
|
||||||
|
SignedCertificateTimestamps: certificate.SignedCertificateTimestamps,
|
||||||
|
Leaf: certificate.Leaf,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if h2Alpn {
|
||||||
|
tlsConn = utls.UClient(conn, utlsConf, utls.HelloChrome_Auto)
|
||||||
|
} else {
|
||||||
|
tlsConn = utls.UClient(conn, utlsConf, utls.HelloCustom)
|
||||||
|
tlsConn.ApplyPreset(newWsSpec())
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise perform handshake, but don't verify the domain
|
// Otherwise perform handshake, but don't verify the domain
|
||||||
//
|
//
|
||||||
|
60
ws.go
60
ws.go
@ -744,28 +744,8 @@ type websocketConn struct {
|
|||||||
rb []byte
|
rb []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func websocketClientConn(url string, conn net.Conn, tlsConfig *tls.Config, options *WSOptions) (net.Conn, error) {
|
func newWsSpec() *utls.ClientHelloSpec {
|
||||||
if options == nil {
|
return &utls.ClientHelloSpec{
|
||||||
options = &WSOptions{}
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout := options.HandshakeTimeout
|
|
||||||
if timeout <= 0 {
|
|
||||||
timeout = HandshakeTimeout
|
|
||||||
}
|
|
||||||
|
|
||||||
dialer := websocket.Dialer{
|
|
||||||
ReadBufferSize: options.ReadBufferSize,
|
|
||||||
WriteBufferSize: options.WriteBufferSize,
|
|
||||||
TLSClientConfig: tlsConfig,
|
|
||||||
HandshakeTimeout: timeout,
|
|
||||||
EnableCompression: options.EnableCompression,
|
|
||||||
NetDial: func(net, addr string) (net.Conn, error) {
|
|
||||||
return conn, nil
|
|
||||||
},
|
|
||||||
NetDialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
||||||
client := utls.UClient(conn, &utls.Config{InsecureSkipVerify: tlsConfig.InsecureSkipVerify, ServerName: tlsConfig.ServerName}, utls.HelloCustom)
|
|
||||||
client.ApplyPreset(&utls.ClientHelloSpec{
|
|
||||||
CipherSuites: []uint16{
|
CipherSuites: []uint16{
|
||||||
utls.GREASE_PLACEHOLDER,
|
utls.GREASE_PLACEHOLDER,
|
||||||
utls.TLS_AES_128_GCM_SHA256,
|
utls.TLS_AES_128_GCM_SHA256,
|
||||||
@ -834,7 +814,43 @@ func websocketClientConn(url string, conn net.Conn, tlsConfig *tls.Config, optio
|
|||||||
&utls.UtlsGREASEExtension{},
|
&utls.UtlsGREASEExtension{},
|
||||||
&utls.UtlsPaddingExtension{GetPaddingLen: utls.BoringPaddingStyle},
|
&utls.UtlsPaddingExtension{GetPaddingLen: utls.BoringPaddingStyle},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func websocketClientConn(url string, conn net.Conn, tlsConfig *tls.Config, options *WSOptions) (net.Conn, error) {
|
||||||
|
if options == nil {
|
||||||
|
options = &WSOptions{}
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout := options.HandshakeTimeout
|
||||||
|
if timeout <= 0 {
|
||||||
|
timeout = HandshakeTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer := websocket.Dialer{
|
||||||
|
ReadBufferSize: options.ReadBufferSize,
|
||||||
|
WriteBufferSize: options.WriteBufferSize,
|
||||||
|
TLSClientConfig: tlsConfig,
|
||||||
|
HandshakeTimeout: timeout,
|
||||||
|
EnableCompression: options.EnableCompression,
|
||||||
|
NetDial: func(net, addr string) (net.Conn, error) {
|
||||||
|
return conn, nil
|
||||||
|
},
|
||||||
|
NetDialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
utlsConf := &utls.Config{InsecureSkipVerify: tlsConfig.InsecureSkipVerify, ServerName: tlsConfig.ServerName, ClientAuth: utls.ClientAuthType(tlsConfig.ClientAuth), ClientCAs: tlsConfig.ClientCAs, RootCAs: tlsConfig.RootCAs}
|
||||||
|
if len(tlsConfig.Certificates) > 0 {
|
||||||
|
for _, certificate := range tlsConfig.Certificates {
|
||||||
|
utlsConf.Certificates = append(utlsConf.Certificates, utls.Certificate{
|
||||||
|
Certificate: certificate.Certificate,
|
||||||
|
PrivateKey: certificate.PrivateKey,
|
||||||
|
OCSPStaple: certificate.OCSPStaple,
|
||||||
|
SignedCertificateTimestamps: certificate.SignedCertificateTimestamps,
|
||||||
|
Leaf: certificate.Leaf,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client := utls.UClient(conn, utlsConf, utls.HelloCustom)
|
||||||
|
client.ApplyPreset(newWsSpec())
|
||||||
err := client.Handshake()
|
err := client.Handshake()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Reference in New Issue
Block a user