feat: add fingerprint param
This commit is contained in:
parent
ab8e9e7d7a
commit
a8ce283727
16 changed files with 193 additions and 30 deletions
|
@ -36,6 +36,7 @@ type HttpOption struct {
|
|||
TLS bool `proxy:"tls,omitempty"`
|
||||
SNI string `proxy:"sni,omitempty"`
|
||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||
Fingerprint string `proxy:"fingerprint,omitempty"`
|
||||
Headers map[string]string `proxy:"headers,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -127,16 +128,26 @@ func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
|||
return fmt.Errorf("can not connect remote err code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
func NewHttp(option HttpOption) *Http {
|
||||
func NewHttp(option HttpOption) (*Http, error) {
|
||||
var tlsConfig *tls.Config
|
||||
if option.TLS {
|
||||
sni := option.Server
|
||||
if option.SNI != "" {
|
||||
sni = option.SNI
|
||||
}
|
||||
tlsConfig = &tls.Config{
|
||||
if len(option.Fingerprint) == 0 {
|
||||
tlsConfig = tlsC.GetGlobalFingerprintTLCConfig(&tls.Config{
|
||||
InsecureSkipVerify: option.SkipCertVerify,
|
||||
ServerName: sni,
|
||||
})
|
||||
} else {
|
||||
var err error
|
||||
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(&tls.Config{
|
||||
InsecureSkipVerify: option.SkipCertVerify,
|
||||
ServerName: sni,
|
||||
}, option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +161,7 @@ func NewHttp(option HttpOption) *Http {
|
|||
},
|
||||
user: option.UserName,
|
||||
pass: option.Password,
|
||||
tlsConfig: tlsC.MixinTLSConfig(tlsConfig),
|
||||
tlsConfig: tlsConfig,
|
||||
option: &option,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ type HysteriaOption struct {
|
|||
Obfs string `proxy:"obfs,omitempty"`
|
||||
SNI string `proxy:"sni,omitempty"`
|
||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||
Fingerprint string `proxy:"fingerprint,omitempty"`
|
||||
ALPN string `proxy:"alpn,omitempty"`
|
||||
CustomCA string `proxy:"ca,omitempty"`
|
||||
CustomCAString string `proxy:"ca_str,omitempty"`
|
||||
|
@ -122,11 +123,22 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) {
|
|||
if option.SNI != "" {
|
||||
serverName = option.SNI
|
||||
}
|
||||
tlsConfig := tlsC.MixinTLSConfig(&tls.Config{
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: serverName,
|
||||
InsecureSkipVerify: option.SkipCertVerify,
|
||||
MinVersion: tls.VersionTLS13,
|
||||
})
|
||||
}
|
||||
if len(option.Fingerprint) != 0 {
|
||||
var err error
|
||||
tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, option.Fingerprint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
tlsConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
}
|
||||
|
||||
if len(option.ALPN) > 0 {
|
||||
tlsConfig.NextProtos = []string{option.ALPN}
|
||||
} else {
|
||||
|
|
|
@ -60,6 +60,7 @@ type v2rayObfsOption struct {
|
|||
Host string `obfs:"host,omitempty"`
|
||||
Path string `obfs:"path,omitempty"`
|
||||
TLS bool `obfs:"tls,omitempty"`
|
||||
Fingerprint string `obfs:"fingerprint,omitempty"`
|
||||
Headers map[string]string `obfs:"headers,omitempty"`
|
||||
SkipCertVerify bool `obfs:"skip-cert-verify,omitempty"`
|
||||
Mux bool `obfs:"mux,omitempty"`
|
||||
|
|
|
@ -34,6 +34,7 @@ type Socks5Option struct {
|
|||
TLS bool `proxy:"tls,omitempty"`
|
||||
UDP bool `proxy:"udp,omitempty"`
|
||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||
Fingerprint string `proxy:"fingerprint,omitempty"`
|
||||
}
|
||||
|
||||
// StreamConn implements C.ProxyAdapter
|
||||
|
@ -139,13 +140,22 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
|||
return newPacketConn(&socksPacketConn{PacketConn: pc, rAddr: bindUDPAddr, tcpConn: c}, ss), nil
|
||||
}
|
||||
|
||||
func NewSocks5(option Socks5Option) *Socks5 {
|
||||
func NewSocks5(option Socks5Option) (*Socks5, error) {
|
||||
var tlsConfig *tls.Config
|
||||
if option.TLS {
|
||||
tlsConfig = &tls.Config{
|
||||
InsecureSkipVerify: option.SkipCertVerify,
|
||||
ServerName: option.Server,
|
||||
}
|
||||
|
||||
if len(option.Fingerprint) == 0 {
|
||||
tlsConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &Socks5{
|
||||
|
@ -161,8 +171,8 @@ func NewSocks5(option Socks5Option) *Socks5 {
|
|||
pass: option.Password,
|
||||
tls: option.TLS,
|
||||
skipCertVerify: option.SkipCertVerify,
|
||||
tlsConfig: tlsC.MixinTLSConfig(tlsConfig),
|
||||
}
|
||||
tlsConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type socksPacketConn struct {
|
||||
|
|
|
@ -36,6 +36,7 @@ type TrojanOption struct {
|
|||
ALPN []string `proxy:"alpn,omitempty"`
|
||||
SNI string `proxy:"sni,omitempty"`
|
||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||
Fingerprint string `proxy:"fingerprint,omitempty"`
|
||||
UDP bool `proxy:"udp,omitempty"`
|
||||
Network string `proxy:"network,omitempty"`
|
||||
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
||||
|
@ -189,6 +190,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||
ServerName: option.Server,
|
||||
SkipCertVerify: option.SkipCertVerify,
|
||||
FlowShow: option.FlowShow,
|
||||
Fingerprint: option.Fingerprint,
|
||||
}
|
||||
|
||||
if option.Network != "ws" && len(option.Flow) >= 16 {
|
||||
|
@ -228,12 +230,21 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||
return c, nil
|
||||
}
|
||||
|
||||
tlsConfig := tlsC.MixinTLSConfig(&tls.Config{
|
||||
tlsConfig := &tls.Config{
|
||||
NextProtos: option.ALPN,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: tOption.SkipCertVerify,
|
||||
ServerName: tOption.ServerName,
|
||||
})
|
||||
}
|
||||
|
||||
if len(option.Fingerprint) == 0 {
|
||||
tlsConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if t.option.Flow != "" {
|
||||
t.transport = gun.NewHTTP2XTLSClient(dialFn, tlsConfig)
|
||||
|
|
|
@ -56,6 +56,7 @@ type VlessOption struct {
|
|||
WSPath string `proxy:"ws-path,omitempty"`
|
||||
WSHeaders map[string]string `proxy:"ws-headers,omitempty"`
|
||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||
Fingerprint string `proxy:"fingerprint,omitempty"`
|
||||
ServerName string `proxy:"servername,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -81,12 +82,19 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||
}
|
||||
if v.option.TLS {
|
||||
wsOpts.TLS = true
|
||||
wsOpts.TLSConfig = tlsC.MixinTLSConfig(&tls.Config{
|
||||
tlsConfig := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ServerName: host,
|
||||
InsecureSkipVerify: v.option.SkipCertVerify,
|
||||
NextProtos: []string{"http/1.1"},
|
||||
})
|
||||
}
|
||||
|
||||
if len(v.option.Fingerprint) == 0 {
|
||||
wsOpts.TLSConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
} else {
|
||||
wsOpts.TLSConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, v.option.Fingerprint)
|
||||
}
|
||||
|
||||
if v.option.ServerName != "" {
|
||||
wsOpts.TLSConfig.ServerName = v.option.ServerName
|
||||
} else if host := wsOpts.Headers.Get("Host"); host != "" {
|
||||
|
@ -153,6 +161,7 @@ func (v *Vless) streamTLSOrXTLSConn(conn net.Conn, isH2 bool) (net.Conn, error)
|
|||
xtlsOpts := vless.XTLSConfig{
|
||||
Host: host,
|
||||
SkipCertVerify: v.option.SkipCertVerify,
|
||||
FingerPrint: v.option.Fingerprint,
|
||||
}
|
||||
|
||||
if isH2 {
|
||||
|
@ -169,6 +178,7 @@ func (v *Vless) streamTLSOrXTLSConn(conn net.Conn, isH2 bool) (net.Conn, error)
|
|||
tlsOpts := vmess.TLSConfig{
|
||||
Host: host,
|
||||
SkipCertVerify: v.option.SkipCertVerify,
|
||||
FingerPrint: v.option.Fingerprint,
|
||||
}
|
||||
|
||||
if isH2 {
|
||||
|
@ -437,7 +447,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||
ServiceName: v.option.GrpcOpts.GrpcServiceName,
|
||||
Host: v.option.ServerName,
|
||||
}
|
||||
tlsConfig := tlsC.MixinTLSConfig(&tls.Config{
|
||||
tlsConfig := tlsC.GetGlobalFingerprintTLCConfig(&tls.Config{
|
||||
InsecureSkipVerify: v.option.SkipCertVerify,
|
||||
ServerName: v.option.ServerName,
|
||||
})
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
vmess "github.com/sagernet/sing-vmess"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -17,7 +18,6 @@ import (
|
|||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/transport/gun"
|
||||
clashVMess "github.com/Dreamacro/clash/transport/vmess"
|
||||
"github.com/sagernet/sing-vmess"
|
||||
"github.com/sagernet/sing-vmess/packetaddr"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
)
|
||||
|
@ -45,6 +45,7 @@ type VmessOption struct {
|
|||
Network string `proxy:"network,omitempty"`
|
||||
TLS bool `proxy:"tls,omitempty"`
|
||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||
Fingerprint string `proxy:"fingerprint,omitempty"`
|
||||
ServerName string `proxy:"servername,omitempty"`
|
||||
HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"`
|
||||
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
|
||||
|
@ -100,11 +101,21 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||
|
||||
if v.option.TLS {
|
||||
wsOpts.TLS = true
|
||||
wsOpts.TLSConfig = tlsC.MixinTLSConfig(&tls.Config{
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: host,
|
||||
InsecureSkipVerify: v.option.SkipCertVerify,
|
||||
NextProtos: []string{"http/1.1"},
|
||||
})
|
||||
}
|
||||
|
||||
if len(v.option.Fingerprint) == 0 {
|
||||
wsOpts.TLSConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if wsOpts.TLSConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, v.option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if v.option.ServerName != "" {
|
||||
wsOpts.TLSConfig.ServerName = v.option.ServerName
|
||||
} else if host := wsOpts.Headers.Get("Host"); host != "" {
|
||||
|
|
|
@ -40,14 +40,14 @@ func ParseProxy(mapping map[string]any) (C.Proxy, error) {
|
|||
if err != nil {
|
||||
break
|
||||
}
|
||||
proxy = outbound.NewSocks5(*socksOption)
|
||||
proxy, err = outbound.NewSocks5(*socksOption)
|
||||
case "http":
|
||||
httpOption := &outbound.HttpOption{}
|
||||
err = decoder.Decode(mapping, httpOption)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
proxy = outbound.NewHttp(*httpOption)
|
||||
proxy, err = outbound.NewHttp(*httpOption)
|
||||
case "vmess":
|
||||
vmessOption := &outbound.VmessOption{
|
||||
HTTPOpts: outbound.HTTPOptions{
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
xtls "github.com/xtls/go"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -75,11 +76,11 @@ func convertFingerprint(fingerprint string) (*[32]byte, error) {
|
|||
}
|
||||
|
||||
func GetDefaultTLSConfig() *tls.Config {
|
||||
return MixinTLSConfig(nil)
|
||||
return GetGlobalFingerprintTLCConfig(nil)
|
||||
}
|
||||
|
||||
// GetTLSConfigWithSpecifiedFingerprint specified fingerprint
|
||||
func GetTLSConfigWithSpecifiedFingerprint(tlsConfig *tls.Config, fingerprint string) (*tls.Config, error) {
|
||||
// GetSpecifiedFingerprintTLSConfig specified fingerprint
|
||||
func GetSpecifiedFingerprintTLSConfig(tlsConfig *tls.Config, fingerprint string) (*tls.Config, error) {
|
||||
if fingerprintBytes, err := convertFingerprint(fingerprint); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
|
@ -96,7 +97,7 @@ func GetTLSConfigWithSpecifiedFingerprint(tlsConfig *tls.Config, fingerprint str
|
|||
}
|
||||
}
|
||||
|
||||
func MixinTLSConfig(tlsConfig *tls.Config) *tls.Config {
|
||||
func GetGlobalFingerprintTLCConfig(tlsConfig *tls.Config) *tls.Config {
|
||||
if tlsConfig == nil {
|
||||
return &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
|
@ -108,3 +109,34 @@ func MixinTLSConfig(tlsConfig *tls.Config) *tls.Config {
|
|||
tlsConfig.InsecureSkipVerify = true
|
||||
return tlsConfig
|
||||
}
|
||||
|
||||
// GetSpecifiedFingerprintXTLSConfig specified fingerprint
|
||||
func GetSpecifiedFingerprintXTLSConfig(tlsConfig *xtls.Config, fingerprint string) (*xtls.Config, error) {
|
||||
if fingerprintBytes, err := convertFingerprint(fingerprint); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if tlsConfig == nil {
|
||||
return &xtls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
VerifyPeerCertificate: verifyPeerCertificateAndFingerprints([][32]byte{*fingerprintBytes}, false),
|
||||
}, nil
|
||||
} else {
|
||||
tlsConfig.VerifyPeerCertificate = verifyPeerCertificateAndFingerprints([][32]byte{*fingerprintBytes}, tlsConfig.InsecureSkipVerify)
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
return tlsConfig, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetGlobalFingerprintXTLCConfig(tlsConfig *xtls.Config) *xtls.Config {
|
||||
if tlsConfig == nil {
|
||||
return &xtls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
VerifyPeerCertificate: verifyPeerCertificateAndFingerprints(globalFingerprints, false),
|
||||
}
|
||||
}
|
||||
|
||||
tlsConfig.VerifyPeerCertificate = verifyPeerCertificateAndFingerprints(globalFingerprints, tlsConfig.InsecureSkipVerify)
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
return tlsConfig
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error)
|
|||
ch := make(chan result, 1)
|
||||
go func() {
|
||||
if strings.HasSuffix(c.Client.Net, "tls") {
|
||||
conn = tls.Client(conn, tlsC.MixinTLSConfig(c.Client.TLSConfig))
|
||||
conn = tls.Client(conn, tlsC.GetGlobalFingerprintTLCConfig(c.Client.TLSConfig))
|
||||
}
|
||||
|
||||
msg, _, err := c.Client.ExchangeWithConn(m, &D.Conn{
|
||||
|
|
|
@ -129,7 +129,7 @@ func (dc *quicClient) getSession(ctx context.Context) (quic.Connection, error) {
|
|||
}
|
||||
|
||||
func (dc *quicClient) openSession(ctx context.Context) (quic.Connection, error) {
|
||||
tlsConfig := tlsC.MixinTLSConfig(
|
||||
tlsConfig := tlsC.GetGlobalFingerprintTLCConfig(
|
||||
&tls.Config{
|
||||
InsecureSkipVerify: false,
|
||||
NextProtos: []string{
|
||||
|
|
|
@ -178,6 +178,7 @@ proxies:
|
|||
plugin-opts:
|
||||
mode: websocket # no QUIC now
|
||||
# tls: true # wss
|
||||
# fingerprint: xxxx
|
||||
# skip-cert-verify: true
|
||||
# host: bing.com
|
||||
# path: "/"
|
||||
|
@ -196,6 +197,7 @@ proxies:
|
|||
cipher: auto
|
||||
# udp: true
|
||||
# tls: true
|
||||
# fingerprint: xxxx
|
||||
# skip-cert-verify: true
|
||||
# servername: example.com # priority over wss host
|
||||
# network: ws
|
||||
|
@ -215,6 +217,7 @@ proxies:
|
|||
cipher: auto
|
||||
network: h2
|
||||
tls: true
|
||||
# fingerprint: xxxx
|
||||
h2-opts:
|
||||
host:
|
||||
- http.example.com
|
||||
|
@ -248,6 +251,7 @@ proxies:
|
|||
cipher: auto
|
||||
network: grpc
|
||||
tls: true
|
||||
# fingerprint: xxxx
|
||||
servername: example.com
|
||||
# skip-cert-verify: true
|
||||
grpc-opts:
|
||||
|
@ -261,6 +265,7 @@ proxies:
|
|||
# username: username
|
||||
# password: password
|
||||
# tls: true
|
||||
# fingerprint: xxxx
|
||||
# skip-cert-verify: true
|
||||
# udp: true
|
||||
|
||||
|
@ -274,6 +279,7 @@ proxies:
|
|||
# tls: true # https
|
||||
# skip-cert-verify: true
|
||||
# sni: custom.com
|
||||
# fingerprint: xxxx
|
||||
|
||||
# Snell
|
||||
# Beware that there's currently no UDP support yet
|
||||
|
@ -293,6 +299,7 @@ proxies:
|
|||
server: server
|
||||
port: 443
|
||||
password: yourpsk
|
||||
# fingerprint: xxxx
|
||||
# udp: true
|
||||
# sni: example.com # aka server name
|
||||
# alpn:
|
||||
|
@ -308,6 +315,7 @@ proxies:
|
|||
network: grpc
|
||||
sni: example.com
|
||||
# skip-cert-verify: true
|
||||
# fingerprint: xxxx
|
||||
udp: true
|
||||
grpc-opts:
|
||||
grpc-service-name: "example"
|
||||
|
@ -320,6 +328,7 @@ proxies:
|
|||
network: ws
|
||||
sni: example.com
|
||||
# skip-cert-verify: true
|
||||
# fingerprint: xxxx
|
||||
udp: true
|
||||
# ws-opts:
|
||||
# path: /path
|
||||
|
@ -336,6 +345,7 @@ proxies:
|
|||
# udp: true
|
||||
# sni: example.com # aka server name
|
||||
# skip-cert-verify: true
|
||||
# fingerprint: xxxx
|
||||
|
||||
# vless
|
||||
- name: "vless-tcp"
|
||||
|
@ -347,6 +357,7 @@ proxies:
|
|||
servername: example.com # AKA SNI
|
||||
# flow: xtls-rprx-direct # xtls-rprx-origin # enable XTLS
|
||||
# skip-cert-verify: true
|
||||
# fingerprint: xxxx
|
||||
|
||||
- name: "vless-ws"
|
||||
type: vless
|
||||
|
@ -358,6 +369,7 @@ proxies:
|
|||
network: ws
|
||||
servername: example.com # priority over wss host
|
||||
# skip-cert-verify: true
|
||||
# fingerprint: xxxx
|
||||
ws-opts:
|
||||
path: "/"
|
||||
headers:
|
||||
|
@ -379,6 +391,7 @@ proxies:
|
|||
#ca: "./my.ca"
|
||||
#ca_str: "xyz"
|
||||
#disable_mtu_discovery: false
|
||||
# fingerprint: xxxx
|
||||
|
||||
# ShadowsocksR
|
||||
# The supported ciphers (encryption methods): all stream ciphers in ss
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -50,6 +51,7 @@ type Option struct {
|
|||
ALPN []string
|
||||
ServerName string
|
||||
SkipCertVerify bool
|
||||
Fingerprint string
|
||||
Flow string
|
||||
FlowShow bool
|
||||
}
|
||||
|
@ -80,6 +82,15 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) {
|
|||
ServerName: t.option.ServerName,
|
||||
}
|
||||
|
||||
if len(t.option.Fingerprint) == 0 {
|
||||
xtlsConfig = tlsC.GetGlobalFingerprintXTLCConfig(xtlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if xtlsConfig, err = tlsC.GetSpecifiedFingerprintXTLSConfig(xtlsConfig, t.option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
xtlsConn := xtls.Client(conn, xtlsConfig)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||
|
@ -95,6 +106,16 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) {
|
|||
InsecureSkipVerify: t.option.SkipCertVerify,
|
||||
ServerName: t.option.ServerName,
|
||||
}
|
||||
|
||||
if len(t.option.Fingerprint) == 0 {
|
||||
tlsConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, t.option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
tlsConn := tls.Client(conn, tlsConfig)
|
||||
if err := tlsConn.Handshake(); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -2,6 +2,7 @@ package obfs
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
|
@ -16,6 +17,7 @@ type Option struct {
|
|||
Headers map[string]string
|
||||
TLS bool
|
||||
SkipCertVerify bool
|
||||
Fingerprint string
|
||||
Mux bool
|
||||
}
|
||||
|
||||
|
@ -35,11 +37,20 @@ func NewV2rayObfs(conn net.Conn, option *Option) (net.Conn, error) {
|
|||
|
||||
if option.TLS {
|
||||
config.TLS = true
|
||||
config.TLSConfig = &tls.Config{
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: option.Host,
|
||||
InsecureSkipVerify: option.SkipCertVerify,
|
||||
NextProtos: []string{"http/1.1"},
|
||||
}
|
||||
if len(option.Fingerprint) == 0 {
|
||||
config.TLSConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if config.TLSConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, option.Fingerprint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if host := config.Headers.Get("Host"); host != "" {
|
||||
config.TLSConfig.ServerName = host
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package vless
|
|||
|
||||
import (
|
||||
"context"
|
||||
tlsC "github.com/Dreamacro/clash/component/tls"
|
||||
"net"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -11,6 +12,7 @@ import (
|
|||
type XTLSConfig struct {
|
||||
Host string
|
||||
SkipCertVerify bool
|
||||
FingerPrint string
|
||||
NextProtos []string
|
||||
}
|
||||
|
||||
|
@ -20,6 +22,14 @@ func StreamXTLSConn(conn net.Conn, cfg *XTLSConfig) (net.Conn, error) {
|
|||
InsecureSkipVerify: cfg.SkipCertVerify,
|
||||
NextProtos: cfg.NextProtos,
|
||||
}
|
||||
if len(cfg.FingerPrint) == 0 {
|
||||
xtlsConfig = tlsC.GetGlobalFingerprintXTLCConfig(xtlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if xtlsConfig, err = tlsC.GetSpecifiedFingerprintXTLSConfig(xtlsConfig, cfg.FingerPrint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
xtlsConn := xtls.Client(conn, xtlsConfig)
|
||||
|
||||
|
|
|
@ -12,15 +12,25 @@ import (
|
|||
type TLSConfig struct {
|
||||
Host string
|
||||
SkipCertVerify bool
|
||||
FingerPrint string
|
||||
NextProtos []string
|
||||
}
|
||||
|
||||
func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) {
|
||||
tlsConfig := tlsC.MixinTLSConfig(&tls.Config{
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: cfg.Host,
|
||||
InsecureSkipVerify: cfg.SkipCertVerify,
|
||||
NextProtos: cfg.NextProtos,
|
||||
})
|
||||
}
|
||||
|
||||
if len(cfg.FingerPrint) == 0 {
|
||||
tlsConfig = tlsC.GetGlobalFingerprintTLCConfig(tlsConfig)
|
||||
} else {
|
||||
var err error
|
||||
if tlsConfig, err = tlsC.GetSpecifiedFingerprintTLSConfig(tlsConfig, cfg.FingerPrint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
tlsConn := tls.Client(conn, tlsConfig)
|
||||
|
||||
|
|
Loading…
Reference in a new issue