1
0
mirror of https://github.com/MetaCubeX/mihomo.git synced 2026-10-10 04:03:11 +08:00

feat: add name-cert-verify to support separate certificate verification name

This commit is contained in:
wwqgtxx
2026-07-12 18:00:23 +08:00
parent 3766a08754
commit 5677fd3808
33 changed files with 310 additions and 57 deletions
+2
View File
@@ -33,6 +33,7 @@ type AnyTLSOption struct {
ECHOpts ECHOptions `proxy:"ech-opts,omitempty"`
ClientFingerprint string `proxy:"client-fingerprint,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -118,6 +119,7 @@ func NewAnyTLS(option AnyTLSOption) (*AnyTLS, error) {
tlsConfig := &vmess.TLSConfig{
Host: option.SNI,
SkipCertVerify: option.SkipCertVerify,
NameCertVerify: option.NameCertVerify,
NextProtos: option.ALPN,
FingerPrint: option.Fingerprint,
Certificate: option.Certificate,
+2
View File
@@ -29,6 +29,7 @@ type GostRelayOption struct {
Username string `proxy:"username,omitempty"`
Password string `proxy:"password,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -100,6 +101,7 @@ func NewGostRelay(option GostRelayOption) (*GostRelay, error) {
Username: option.Username,
Password: option.Password,
SkipCertVerify: option.SkipCertVerify,
NameCertVerify: option.NameCertVerify,
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
+5 -3
View File
@@ -35,6 +35,7 @@ type HttpOption struct {
TLS bool `proxy:"tls,omitempty"`
SNI string `proxy:"sni,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -157,9 +158,10 @@ func NewHttp(option HttpOption) (*Http, error) {
InsecureSkipVerify: option.SkipCertVerify,
ServerName: sni,
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
+5 -3
View File
@@ -116,6 +116,7 @@ type HysteriaOption struct {
SNI string `proxy:"sni,omitempty"`
ECHOpts ECHOptions `proxy:"ech-opts,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -158,9 +159,10 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) {
InsecureSkipVerify: option.SkipCertVerify,
MinVersion: tls.VersionTLS13,
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
+10 -6
View File
@@ -53,6 +53,7 @@ type Hysteria2Option struct {
SNI string `proxy:"sni,omitempty"`
ECHOpts ECHOptions `proxy:"ech-opts,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -80,6 +81,7 @@ type Hysteria2RealmOption struct {
// for ServerURL
SNI string `proxy:"sni,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -170,9 +172,10 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
InsecureSkipVerify: option.SkipCertVerify,
MinVersion: tls.VersionTLS13,
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
@@ -269,9 +272,10 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
InsecureSkipVerify: option.RealmOpts.SkipCertVerify,
NextProtos: option.RealmOpts.ALPN,
},
Fingerprint: option.RealmOpts.Fingerprint,
Certificate: option.RealmOpts.Certificate,
PrivateKey: option.RealmOpts.PrivateKey,
Fingerprint: option.RealmOpts.Fingerprint,
NameCertVerify: option.RealmOpts.NameCertVerify,
Certificate: option.RealmOpts.Certificate,
PrivateKey: option.RealmOpts.PrivateKey,
})
if err != nil {
return nil, err
+1
View File
@@ -67,6 +67,7 @@ type MasqueOption struct {
UDP bool `proxy:"udp,omitempty"`
HandshakeTimeout int `proxy:"handshake-timeout,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"` // placeholder; MASQUE does not verify certificate names
Network string `proxy:"network,omitempty"`
CongestionController string `proxy:"congestion-controller,omitempty"`
+10 -1
View File
@@ -69,6 +69,7 @@ type v2rayObfsOption struct {
PrivateKey string `obfs:"private-key,omitempty"`
Headers map[string]string `obfs:"headers,omitempty"`
SkipCertVerify bool `obfs:"skip-cert-verify,omitempty"`
NameCertVerify string `obfs:"name-cert-verify,omitempty"`
Mux bool `obfs:"mux,omitempty"`
V2rayHttpUpgrade bool `obfs:"v2ray-http-upgrade,omitempty"`
V2rayHttpUpgradeFastOpen bool `obfs:"v2ray-http-upgrade-fast-open,omitempty"`
@@ -85,6 +86,7 @@ type gostObfsOption struct {
PrivateKey string `obfs:"private-key,omitempty"`
Headers map[string]string `obfs:"headers,omitempty"`
SkipCertVerify bool `obfs:"skip-cert-verify,omitempty"`
NameCertVerify string `obfs:"name-cert-verify,omitempty"`
Mux bool `obfs:"mux,omitempty"`
}
@@ -95,6 +97,7 @@ type shadowTLSOption struct {
Certificate string `obfs:"certificate,omitempty"`
PrivateKey string `obfs:"private-key,omitempty"`
SkipCertVerify bool `obfs:"skip-cert-verify,omitempty"`
NameCertVerify string `obfs:"name-cert-verify,omitempty"`
Version int `obfs:"version,omitempty"`
ALPN []string `obfs:"alpn,omitempty"`
}
@@ -106,6 +109,7 @@ type restlsOption struct {
RestlsScript string `obfs:"restls-script,omitempty"`
Fingerprint string `obfs:"fingerprint,omitempty"`
SkipCertVerify bool `obfs:"skip-cert-verify,omitempty"`
NameCertVerify string `obfs:"name-cert-verify,omitempty"`
ForceTLS12 bool `obfs:"force-tls12,omitempty"` // for test
}
@@ -331,6 +335,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
if opts.TLS {
v2rayOption.TLS = true
v2rayOption.SkipCertVerify = opts.SkipCertVerify
v2rayOption.NameCertVerify = opts.NameCertVerify
v2rayOption.Fingerprint = opts.Fingerprint
v2rayOption.Certificate = opts.Certificate
v2rayOption.PrivateKey = opts.PrivateKey
@@ -361,6 +366,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
if opts.TLS {
gostOption.TLS = true
gostOption.SkipCertVerify = opts.SkipCertVerify
gostOption.NameCertVerify = opts.NameCertVerify
gostOption.Fingerprint = opts.Fingerprint
gostOption.Certificate = opts.Certificate
gostOption.PrivateKey = opts.PrivateKey
@@ -388,6 +394,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
PrivateKey: opt.PrivateKey,
ClientFingerprint: option.ClientFingerprint,
SkipCertVerify: opt.SkipCertVerify,
NameCertVerify: opt.NameCertVerify,
Version: opt.Version,
}
@@ -409,10 +416,12 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
}
restlsConfig.InsecureSkipVerify = restlsOpt.SkipCertVerify
if restlsOpt.Fingerprint != "" {
err = restls.SetFingerprint(restlsConfig, restlsOpt.Fingerprint)
err = restls.SetFingerprint(restlsConfig, restlsOpt.Fingerprint, restlsOpt.NameCertVerify)
if err != nil {
return nil, fmt.Errorf("ss %s initialize restls-plugin error: %w", addr, err)
}
} else if restlsOpt.NameCertVerify != "" {
restls.SetNameCertVerify(restlsConfig, restlsOpt.NameCertVerify)
}
restlsConfig.ForceTLS12 = restlsOpt.ForceTLS12
} else if option.Plugin == kcptun.Mode {
+1
View File
@@ -180,6 +180,7 @@ func NewSnell(option SnellOption) (*Snell, error) {
PrivateKey: opt.PrivateKey,
ClientFingerprint: option.ClientFingerprint,
SkipCertVerify: opt.SkipCertVerify,
NameCertVerify: opt.NameCertVerify,
Version: opt.Version,
}
+5 -3
View File
@@ -37,6 +37,7 @@ type Socks5Option struct {
TLS bool `proxy:"tls,omitempty"`
UDP bool `proxy:"udp,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -178,9 +179,10 @@ func NewSocks5(option Socks5Option) (*Socks5, error) {
InsecureSkipVerify: option.SkipCertVerify,
ServerName: option.Server,
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
+7 -3
View File
@@ -44,6 +44,7 @@ type TrojanOption struct {
ALPN []string `proxy:"alpn,omitempty"`
SNI string `proxy:"sni,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -105,9 +106,10 @@ func (t *Trojan) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.
InsecureSkipVerify: t.option.SkipCertVerify,
ServerName: t.option.SNI,
},
Fingerprint: t.option.Fingerprint,
Certificate: t.option.Certificate,
PrivateKey: t.option.PrivateKey,
Fingerprint: t.option.Fingerprint,
NameCertVerify: t.option.NameCertVerify,
Certificate: t.option.Certificate,
PrivateKey: t.option.PrivateKey,
})
if err != nil {
return nil, err
@@ -126,6 +128,7 @@ func (t *Trojan) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.
c, err = vmess.StreamTLSConn(ctx, c, &vmess.TLSConfig{
Host: t.option.SNI,
SkipCertVerify: t.option.SkipCertVerify,
NameCertVerify: t.option.NameCertVerify,
FingerPrint: t.option.Fingerprint,
Certificate: t.option.Certificate,
PrivateKey: t.option.PrivateKey,
@@ -307,6 +310,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
tlsConfig := &vmess.TLSConfig{
Host: option.SNI,
SkipCertVerify: option.SkipCertVerify,
NameCertVerify: option.NameCertVerify,
FingerPrint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
+2
View File
@@ -29,6 +29,7 @@ type TrustTunnelOption struct {
ECHOpts ECHOptions `proxy:"ech-opts,omitempty"`
ClientFingerprint string `proxy:"client-fingerprint,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -124,6 +125,7 @@ func NewTrustTunnel(option TrustTunnelOption) (*TrustTunnel, error) {
tlsConfig := &vmess.TLSConfig{
Host: option.SNI,
SkipCertVerify: option.SkipCertVerify,
NameCertVerify: option.NameCertVerify,
NextProtos: option.ALPN,
FingerPrint: option.Fingerprint,
Certificate: option.Certificate,
+5 -3
View File
@@ -54,6 +54,7 @@ type TuicOption struct {
CWND int `proxy:"cwnd,omitempty"`
BBRProfile string `proxy:"bbr-profile,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -138,9 +139,10 @@ func NewTuic(option TuicOption) (*Tuic, error) {
InsecureSkipVerify: option.SkipCertVerify,
MinVersion: tls.VersionTLS13,
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
+12 -3
View File
@@ -71,6 +71,7 @@ type VlessOption struct {
XHTTPOpts XHTTPOptions `proxy:"xhttp-opts,omitempty"`
WSHeaders map[string]string `proxy:"ws-headers,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -129,6 +130,7 @@ type XHTTPDownloadSettings struct {
ECHOpts *ECHOptions `proxy:"ech-opts,omitempty"`
RealityOpts *RealityOptions `proxy:"reality-opts,omitempty"`
SkipCertVerify *bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify *string `proxy:"name-cert-verify,omitempty"`
Fingerprint *string `proxy:"fingerprint,omitempty"`
Certificate *string `proxy:"certificate,omitempty"`
PrivateKey *string `proxy:"private-key,omitempty"`
@@ -166,9 +168,10 @@ func (v *Vless) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.M
InsecureSkipVerify: v.option.SkipCertVerify,
NextProtos: []string{"http/1.1"},
},
Fingerprint: v.option.Fingerprint,
Certificate: v.option.Certificate,
PrivateKey: v.option.PrivateKey,
Fingerprint: v.option.Fingerprint,
NameCertVerify: v.option.NameCertVerify,
Certificate: v.option.Certificate,
PrivateKey: v.option.PrivateKey,
})
if err != nil {
return nil, err
@@ -273,6 +276,7 @@ func (v *Vless) streamTLSConn(ctx context.Context, conn net.Conn, isH2 bool) (ne
tlsOpts := vmess.TLSConfig{
Host: host,
SkipCertVerify: v.option.SkipCertVerify,
NameCertVerify: v.option.NameCertVerify,
FingerPrint: v.option.Fingerprint,
Certificate: v.option.Certificate,
PrivateKey: v.option.PrivateKey,
@@ -510,6 +514,7 @@ func NewVless(option VlessOption) (*Vless, error) {
tlsConfig = &vmess.TLSConfig{
Host: option.ServerName,
SkipCertVerify: option.SkipCertVerify,
NameCertVerify: option.NameCertVerify,
FingerPrint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
@@ -596,6 +601,7 @@ func NewVless(option VlessOption) (*Vless, error) {
tlsOpts := &vmess.TLSConfig{
Host: host,
SkipCertVerify: v.option.SkipCertVerify,
NameCertVerify: v.option.NameCertVerify,
FingerPrint: v.option.Fingerprint,
Certificate: v.option.Certificate,
PrivateKey: v.option.PrivateKey,
@@ -658,6 +664,7 @@ func NewVless(option VlessOption) (*Vless, error) {
}
}
downloadSkipCertVerify := lo.FromPtrOr(ds.SkipCertVerify, v.option.SkipCertVerify)
downloadNameCertVerify := lo.FromPtrOr(ds.NameCertVerify, v.option.NameCertVerify)
downloadFingerprint := lo.FromPtrOr(ds.Fingerprint, v.option.Fingerprint)
downloadCertificate := lo.FromPtrOr(ds.Certificate, v.option.Certificate)
downloadPrivateKey := lo.FromPtrOr(ds.PrivateKey, v.option.PrivateKey)
@@ -707,6 +714,7 @@ func NewVless(option VlessOption) (*Vless, error) {
tlsOpts := vmess.TLSConfig{
Host: host,
SkipCertVerify: downloadSkipCertVerify,
NameCertVerify: downloadNameCertVerify,
FingerPrint: downloadFingerprint,
Certificate: downloadCertificate,
PrivateKey: downloadPrivateKey,
@@ -734,6 +742,7 @@ func NewVless(option VlessOption) (*Vless, error) {
tlsOpts := &vmess.TLSConfig{
Host: host,
SkipCertVerify: downloadSkipCertVerify,
NameCertVerify: downloadNameCertVerify,
FingerPrint: downloadFingerprint,
Certificate: downloadCertificate,
PrivateKey: downloadPrivateKey,
+7 -3
View File
@@ -57,6 +57,7 @@ type VmessOption struct {
TLS bool `proxy:"tls,omitempty"`
ALPN []string `proxy:"alpn,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -198,9 +199,10 @@ func (v *Vmess) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.M
InsecureSkipVerify: v.option.SkipCertVerify,
NextProtos: []string{"http/1.1"},
},
Fingerprint: v.option.Fingerprint,
Certificate: v.option.Certificate,
PrivateKey: v.option.PrivateKey,
Fingerprint: v.option.Fingerprint,
NameCertVerify: v.option.NameCertVerify,
Certificate: v.option.Certificate,
PrivateKey: v.option.PrivateKey,
})
if err != nil {
return nil, err
@@ -321,6 +323,7 @@ func (v *Vmess) streamTLSConn(ctx context.Context, conn net.Conn, isH2 bool) (ne
tlsOpts := mihomoVMess.TLSConfig{
Host: host,
SkipCertVerify: v.option.SkipCertVerify,
NameCertVerify: v.option.NameCertVerify,
FingerPrint: v.option.Fingerprint,
Certificate: v.option.Certificate,
PrivateKey: v.option.PrivateKey,
@@ -538,6 +541,7 @@ func NewVmess(option VmessOption) (*Vmess, error) {
tlsConfig = &mihomoVMess.TLSConfig{
Host: option.ServerName,
SkipCertVerify: option.SkipCertVerify,
NameCertVerify: option.NameCertVerify,
FingerPrint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
+4
View File
@@ -16,6 +16,7 @@ type overrideSchema struct {
Down *string `provider:"down,omitempty"`
DialerProxy *string `provider:"dialer-proxy,omitempty"`
SkipCertVerify *bool `provider:"skip-cert-verify,omitempty"`
NameCertVerify *string `provider:"name-cert-verify,omitempty"`
Interface *string `provider:"interface-name,omitempty"`
RoutingMark *int `provider:"routing-mark,omitempty"`
IPVersion *string `provider:"ip-version,omitempty"`
@@ -63,6 +64,9 @@ func (o *overrideSchema) Apply(mapping map[string]any) error {
if o.SkipCertVerify != nil {
mapping["skip-cert-verify"] = *o.SkipCertVerify
}
if o.NameCertVerify != nil {
mapping["name-cert-verify"] = *o.NameCertVerify
}
if o.Interface != nil {
mapping["interface-name"] = *o.Interface
}
+17 -6
View File
@@ -77,11 +77,12 @@ func GetCertPool() *x509.CertPool {
}
type Option struct {
TLSConfig *tls.Config
Fingerprint string
ZeroTrust bool
Certificate string
PrivateKey string
TLSConfig *tls.Config
Fingerprint string
NameCertVerify string
ZeroTrust bool
Certificate string
PrivateKey string
}
func GetTLSConfig(opt Option) (tlsConfig *tls.Config, err error) {
@@ -106,7 +107,17 @@ func GetTLSConfig(opt Option) (tlsConfig *tls.Config, err error) {
// [ConnectionState.ServerName] can return the actual ServerName needed for verification,
// avoiding inconsistencies caused by [tlsConfig.ServerName] being modified after the [NewFingerprintVerifier] call.
// https://github.com/golang/go/issues/36736#issuecomment-587925536
return verifier(state.PeerCertificates, state.ServerName)
serverName := state.ServerName
if opt.NameCertVerify != "" {
serverName = opt.NameCertVerify
}
return verifier(state.PeerCertificates, serverName)
}
tlsConfig.InsecureSkipVerify = true
} else if opt.NameCertVerify != "" {
verifier := NewNameCertVerifier(opt.NameCertVerify, tlsConfig.RootCAs, tlsConfig.Time)
tlsConfig.VerifyConnection = func(state tls.ConnectionState) error {
return verifier(state.PeerCertificates)
}
tlsConfig.InsecureSkipVerify = true
}
+31
View File
@@ -0,0 +1,31 @@
package ca
import (
"crypto/x509"
"errors"
"time"
)
// NewNameCertVerifier returns a verifier for a certificate chain and an explicit DNSName.
func NewNameCertVerifier(dnsName string, roots *x509.CertPool, now func() time.Time) func([]*x509.Certificate) error {
return func(certificates []*x509.Certificate) error {
if len(certificates) == 0 {
return errors.New("tls: no peer certificates")
}
intermediates := x509.NewCertPool()
for _, certificate := range certificates[1:] {
intermediates.AddCert(certificate)
}
verifyOptions := x509.VerifyOptions{
Roots: roots,
Intermediates: intermediates,
DNSName: dnsName,
}
if now != nil {
verifyOptions.CurrentTime = now()
}
_, err := certificates[0].Verify(verifyOptions)
return err
}
}
+98
View File
@@ -0,0 +1,98 @@
package ca
import (
"crypto/x509"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestNameCertVerifier(t *testing.T) {
roots := x509.NewCertPool()
roots.AddCert(rootCert)
untrustedRoots := x509.NewCertPool()
untrustedRoots.AddCert(smimeRootCert)
tests := []struct {
name string
dnsName string
roots *x509.CertPool
now func() time.Time
certificates []*x509.Certificate
wantErr bool
}{
{
name: "valid chain",
dnsName: leafServerName,
roots: roots,
now: certTime,
certificates: []*x509.Certificate{leafCert, intermediateCert},
},
{
name: "valid chain with root",
dnsName: leafServerName,
roots: roots,
now: certTime,
certificates: []*x509.Certificate{leafCert, intermediateCert, rootCert},
},
{
name: "wrong DNS name",
dnsName: wrongLeafServerName,
roots: roots,
now: certTime,
certificates: []*x509.Certificate{leafCert, intermediateCert},
wantErr: true,
},
{
name: "no certificates",
dnsName: leafServerName,
roots: roots,
now: certTime,
wantErr: true,
},
{
name: "missing intermediate",
dnsName: leafServerName,
roots: roots,
now: certTime,
certificates: []*x509.Certificate{leafCert},
wantErr: true,
},
{
name: "untrusted root",
dnsName: leafServerName,
roots: untrustedRoots,
now: certTime,
certificates: []*x509.Certificate{leafCert, intermediateCert},
wantErr: true,
},
{
name: "expired certificate",
dnsName: leafServerName,
roots: roots,
now: func() time.Time { return leafCert.NotAfter.Add(time.Second) },
certificates: []*x509.Certificate{leafCert, intermediateCert},
wantErr: true,
},
{
name: "invalid certificate signature",
dnsName: leafServerName,
roots: roots,
now: certTime,
certificates: []*x509.Certificate{leafWithInvalidHashCert, intermediateCert},
wantErr: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
err := NewNameCertVerifier(test.dnsName, test.roots, test.now)(test.certificates)
if test.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
+3
View File
@@ -69,6 +69,7 @@ type dnsOverHTTPS struct {
dialer *dnsDialer
addr string
skipCertVerify bool
nameCertVerify string
}
// type check
@@ -100,6 +101,7 @@ func newDoHClient(urlString string, r resolver.Resolver, preferH3 bool, params m
if params["skip-cert-verify"] == "true" {
doh.skipCertVerify = true
}
doh.nameCertVerify = params["name-cert-verify"]
runtime.SetFinalizer(doh, (*dnsOverHTTPS).Close)
@@ -406,6 +408,7 @@ func (doh *dnsOverHTTPS) createTransport(ctx context.Context) (t http.RoundTripp
MinVersion: tls.VersionTLS12,
SessionTicketsDisabled: false,
},
NameCertVerify: doh.nameCertVerify,
})
if err != nil {
return nil, err
+3
View File
@@ -62,6 +62,7 @@ type dnsOverQUIC struct {
addr string
dialer *dnsDialer
skipCertVerify bool
nameCertVerify string
}
// type check
@@ -81,6 +82,7 @@ func newDoQ(addr string, resolver resolver.Resolver, params map[string]string, p
if params["skip-cert-verify"] == "true" {
doq.skipCertVerify = true
}
doq.nameCertVerify = params["name-cert-verify"]
runtime.SetFinalizer(doq, (*dnsOverQUIC).Close)
return doq
@@ -349,6 +351,7 @@ func (doq *dnsOverQUIC) openConnection(ctx context.Context) (quicConn *quic.Conn
},
SessionTicketsDisabled: false,
},
NameCertVerify: doq.nameCertVerify,
})
if err != nil {
return nil, err
+3
View File
@@ -24,6 +24,7 @@ type dnsOverTLS struct {
host string
dialer *dnsDialer
skipCertVerify bool
nameCertVerify string
disableReuse bool
access sync.Mutex
@@ -128,6 +129,7 @@ func (t *dnsOverTLS) dialContext(ctx context.Context) (net.Conn, error) {
ServerName: t.host,
InsecureSkipVerify: t.skipCertVerify,
},
NameCertVerify: t.nameCertVerify,
})
if err != nil {
_ = conn.Close()
@@ -171,6 +173,7 @@ func newDoTClient(addr string, resolver resolver.Resolver, params map[string]str
if params["skip-cert-verify"] == "true" {
c.skipCertVerify = true
}
c.nameCertVerify = params["name-cert-verify"]
if params["disable-reuse"] == "true" {
c.disableReuse = true
}
+28 -3
View File
@@ -379,6 +379,7 @@ proxies: # socks5
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
# private-key: ./client.key # 证书对应的私钥 PEM 格式,或者私钥路径
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# udp: true
# ip-version: ipv6
@@ -391,6 +392,7 @@ proxies: # socks5
# password: password
# tls: true # https
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# sni: custom.com
# fingerprint: xxxx # 配置指纹将实现 SSL Pining 效果, 可使用 openssl x509 -noout -fingerprint -sha256 -inform pem -in yourcert.pem 获取
# 下面两项如果填写则开启 mTLS(需要同时填写)
@@ -489,6 +491,7 @@ proxies: # socks5
# config: AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA
# # query-server-name: xxx.com # 可选项,不为空时用于指定通过dns解析时的域名
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# host: bing.com
# path: "/"
# mux: true
@@ -526,6 +529,7 @@ proxies: # socks5
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
# private-key: ./client.key # 证书对应的私钥 PEM 格式,或者私钥路径
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# host: bing.com
# path: "/"
# mux: true
@@ -549,6 +553,7 @@ proxies: # socks5
# certificate: ./client.crt
# private-key: ./client.key
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
- name: "ss6-gost-relay"
type: ss
@@ -677,8 +682,9 @@ proxies: # socks5
# private-key: ./client.key # 证书对应的私钥 PEM 格式,或者私钥路径
# 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
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# servername: example.com # priority over wss host
# 如果填写 tlsmirror-opts 则开启 tlsmirror(当 tls: true 时)。tlsmirror 的 TLS 载体会使用同一出站中的 `servername`、`alpn`、`skip-cert-verify`、`fingerprint`、`certificate`、`private-key`、`client-fingerprint` 和 `ech-opts` 配置;`servername` 为空时使用 `server`。
# 如果填写 tlsmirror-opts 则开启 tlsmirror(当 tls: true 时)。tlsmirror 的 TLS 载体会使用同一出站中的 `servername`、`alpn`、`skip-cert-verify`、`name-cert-verify`、`fingerprint`、`certificate`、`private-key`、`client-fingerprint` 和 `ech-opts` 配置;`servername` 为空时使用 `server`。
# tlsmirror-opts:
# primary-key: MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY= # 必填,32 字节主密钥的 base64 编码
# explicit-nonce-ciphersuites: [156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 49195, 49196, 49197, 49198, 49199, 49200, 49201, 49202, 49290, 49291, 49293, 49316, 49317, 49318, 49319, 49320, 49321, 49322, 49323, 49324, 49325, 49326, 49327, 52392, 52393, 52394, 52395, 52396, 52397, 52398] # TLS 1.2 载体使用显式 nonce 的加密套件
@@ -816,6 +822,7 @@ proxies: # socks5
# private-key: ./client.key # 证书对应的私钥 PEM 格式,或者私钥路径
servername: example.com
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
grpc-opts:
grpc-service-name: "example"
# grpc-user-agent: "grpc-go/1.36.0"
@@ -834,6 +841,7 @@ proxies: # socks5
network: tcp
servername: example.com # AKA SNI
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# 下面两项如果填写则开启 mTLS(需要同时填写)
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
# private-key: ./client.key # 证书对应的私钥 PEM 格式,或者私钥路径
@@ -860,6 +868,7 @@ proxies: # socks5
# private-key: ./client.key # 证书对应的私钥 PEM 格式,或者私钥路径
# fingerprint: xxxx # 配置指纹将实现 SSL Pining 效果, 可使用 openssl x509 -noout -fingerprint -sha256 -inform pem -in yourcert.pem 获取
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
- name: "vless-encryption"
type: vless
@@ -908,6 +917,7 @@ proxies: # socks5
udp: true
flow:
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
client-fingerprint: chrome
servername: testingcf.jsdelivr.net
grpc-opts:
@@ -934,6 +944,7 @@ proxies: # socks5
# client-fingerprint: random # Available: "chrome","firefox","safari","random","none"
servername: example.com # priority over wss host
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# fingerprint: xxxx # 配置指纹将实现 SSL Pining 效果, 可使用 openssl x509 -noout -fingerprint -sha256 -inform pem -in yourcert.pem 获取
# 下面两项如果填写则开启 mTLS(需要同时填写)
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
@@ -957,6 +968,7 @@ proxies: # socks5
# ech-opts: ...
# reality-opts: ...
# skip-cert-verify: false
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# fingerprint: ...
# certificate: ...
# private-key: ...
@@ -1014,6 +1026,7 @@ proxies: # socks5
# ech-opts: ...
# reality-opts: ...
# skip-cert-verify: false
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# fingerprint: ...
# certificate: ...
# private-key: ...
@@ -1038,6 +1051,7 @@ proxies: # socks5
# - h2
# - http/1.1
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# ss-opts: # like trojan-go's `shadowsocks` config
# enabled: false
# method: aes-128-gcm # aes-128-gcm/aes-256-gcm/chacha20-ietf-poly1305
@@ -1056,6 +1070,7 @@ proxies: # socks5
network: grpc
sni: example.com
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# fingerprint: xxxx # 配置指纹将实现 SSL Pining 效果, 可使用 openssl x509 -noout -fingerprint -sha256 -inform pem -in yourcert.pem 获取
# 下面两项如果填写则开启 mTLS(需要同时填写)
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
@@ -1077,6 +1092,7 @@ proxies: # socks5
network: ws
sni: example.com
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# fingerprint: xxxx # 配置指纹将实现 SSL Pining 效果, 可使用 openssl x509 -noout -fingerprint -sha256 -inform pem -in yourcert.pem 获取
# 下面两项如果填写则开启 mTLS(需要同时填写)
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
@@ -1099,6 +1115,7 @@ proxies: # socks5
# udp: true
# sni: example.com # aka server name
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# fingerprint: xxxx # 配置指纹将实现 SSL Pining 效果, 可使用 openssl x509 -noout -fingerprint -sha256 -inform pem -in yourcert.pem 获取
# 下面两项如果填写则开启 mTLS(需要同时填写)
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
@@ -1124,6 +1141,7 @@ proxies: # socks5
# config: AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA
# # query-server-name: xxx.com # 可选项,不为空时用于指定通过dns解析时的域名
# skip-cert-verify: false
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# recv-window-conn: 12582912
# recv-window: 52428800
# disable-mtu-discovery: false
@@ -1156,6 +1174,7 @@ proxies: # socks5
# config: AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA
# # query-server-name: xxx.com # 可选项,不为空时用于指定通过dns解析时的域名
# skip-cert-verify: false
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# fingerprint: xxxx # 配置指纹将实现 SSL Pining 效果, 可使用 openssl x509 -noout -fingerprint -sha256 -inform pem -in yourcert.pem 获取
# 下面两项如果填写则开启 mTLS(需要同时填写)
# certificate: ./client.crt # 证书 PEM 格式,或者 证书的路径
@@ -1171,8 +1190,9 @@ proxies: # socks5
# - stun.nextcloud.com:3478
# - stun.sip.us:3478
# - global.stun.twilio.com:3478
# # 下面支持填写针对server-url的TLS配置(sni, skip-cert-verify, fingerprint, certificate, private-key, alpn)
# # 下面支持填写针对server-url的TLS配置(sni, skip-cert-verify, name-cert-verify, fingerprint, certificate, private-key, alpn)
# # skip-cert-verify: false
# # name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# # ......
###quic-go特殊配置项,不要随意修改除非你知道你在干什么###
# initial-stream-receive-window: 8388608
@@ -1384,6 +1404,7 @@ proxies: # socks5
# max-udp-relay-packet-size: 1500
# fast-open: true
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# max-open-streams: 20 # default 100, too many open streams may hurt performance
# sni: example.com
# ech-opts:
@@ -1482,6 +1503,7 @@ proxies: # socks5
# - h2
# - http/1.1
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# trusttunnel
- name: trusttunnel
@@ -1497,6 +1519,7 @@ proxies: # socks5
# alpn:
# - h2
# skip-cert-verify: true
# name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
### quic options
# quic: true # 默认为false
# congestion-controller: bbr
@@ -1619,6 +1642,7 @@ proxy-providers:
# expected-status: 204 # 当健康检查返回状态码与期望值不符时,认为节点不可用
override: # 覆写节点加载时的一些配置项
skip-cert-verify: true
name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
udp: true
# down: "50 Mbps"
# up: "10 Mbps"
@@ -2323,8 +2347,9 @@ listeners:
# - stun.sip.us:3478
# - global.stun.twilio.com:3478
# # proxy: DIRECT # 设置server-url通过哪个代理进行连接
# # 下面支持填写针对server-url的TLS配置(sni, skip-cert-verify, fingerprint, certificate, private-key, alpn)
# # 下面支持填写针对server-url的TLS配置(sni, skip-cert-verify, name-cert-verify, fingerprint, certificate, private-key, alpn)
# # skip-cert-verify: false
# # name-cert-verify: example.com # 仅修改证书 DNSName 校验目标,不修改 SNI
# # ......
# 注意,这是用于自建hysteria2入站和出站中realm-opts中server-url的HTTP/HTTPS服务器,请勿混淆
+1
View File
@@ -49,6 +49,7 @@ type Hysteria2RealmOption struct {
// for ServerURL
SNI string `yaml:"sni" json:"sni,omitempty"`
SkipCertVerify bool `yaml:"skip-cert-verify" json:"skip-cert-verify,omitempty"`
NameCertVerify string `yaml:"name-cert-verify" json:"name-cert-verify,omitempty"`
Fingerprint string `yaml:"fingerprint" json:"fingerprint,omitempty"`
Certificate string `yaml:"certificate" json:"certificate,omitempty"`
PrivateKey string `yaml:"private-key" json:"private-key,omitempty"`
+2
View File
@@ -51,6 +51,7 @@ type Hysteria2RealmOption struct {
// for ServerURL
SNI string `inbound:"sni,omitempty"`
SkipCertVerify bool `inbound:"skip-cert-verify,omitempty"`
NameCertVerify string `inbound:"name-cert-verify,omitempty"`
Fingerprint string `inbound:"fingerprint,omitempty"`
Certificate string `inbound:"certificate,omitempty"`
PrivateKey string `inbound:"private-key,omitempty"`
@@ -67,6 +68,7 @@ func (o Hysteria2RealmOption) Build() LC.Hysteria2RealmOption {
STUNServers: o.STUNServers,
SNI: o.SNI,
SkipCertVerify: o.SkipCertVerify,
NameCertVerify: o.NameCertVerify,
Fingerprint: o.Fingerprint,
Certificate: o.Certificate,
PrivateKey: o.PrivateKey,
+4 -3
View File
@@ -163,9 +163,10 @@ func New(config LC.Hysteria2Server, lc C.InboundListenConfig, tunnel C.Tunnel, a
InsecureSkipVerify: config.RealmOpts.SkipCertVerify,
NextProtos: config.RealmOpts.ALPN,
},
Fingerprint: config.RealmOpts.Fingerprint,
Certificate: config.RealmOpts.Certificate,
PrivateKey: config.RealmOpts.PrivateKey,
Fingerprint: config.RealmOpts.Fingerprint,
NameCertVerify: config.RealmOpts.NameCertVerify,
Certificate: config.RealmOpts.Certificate,
PrivateKey: config.RealmOpts.PrivateKey,
})
if err != nil {
return nil, err
+2
View File
@@ -58,6 +58,7 @@ type RelayOption struct {
Username string `proxy:"username,omitempty"`
Password string `proxy:"password,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
NameCertVerify string `proxy:"name-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
Certificate string `proxy:"certificate,omitempty"`
PrivateKey string `proxy:"private-key,omitempty"`
@@ -175,6 +176,7 @@ func (d *relayDialer) dialRelayServer(ctx context.Context, fallbackAddress strin
tlsConn, err := mihomoVMess.StreamTLSConn(ctx, conn, &mihomoVMess.TLSConfig{
Host: d.serverName(relayAddress),
SkipCertVerify: d.option.SkipCertVerify,
NameCertVerify: d.option.NameCertVerify,
FingerPrint: d.option.Fingerprint,
Certificate: d.option.Certificate,
PrivateKey: d.option.PrivateKey,
+5 -3
View File
@@ -22,6 +22,7 @@ type Option struct {
TLS bool
ECHConfig *ech.Config
SkipCertVerify bool
NameCertVerify string
Fingerprint string
Certificate string
PrivateKey string
@@ -69,9 +70,10 @@ func NewGostWebsocket(ctx context.Context, conn net.Conn, option *Option) (net.C
InsecureSkipVerify: option.SkipCertVerify,
NextProtos: []string{"http/1.1"},
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
+14 -2
View File
@@ -38,18 +38,30 @@ type ServerConfig = tls.RestlsServerConfig
var Server = tls.RestlsServer
func SetFingerprint(config *Config, fingerprint string) (err error) {
func SetFingerprint(config *Config, fingerprint string, nameCertVerify string) (err error) {
verifier, err := ca.NewFingerprintVerifier(fingerprint, ntp.Now)
if err != nil {
return err
}
config.InsecureSkipVerify = true
config.VerifyConnection = func(state tls.ConnectionState) error {
return verifier(state.PeerCertificates, state.ServerName)
serverName := state.ServerName
if nameCertVerify != "" {
serverName = nameCertVerify
}
return verifier(state.PeerCertificates, serverName)
}
return nil
}
func SetNameCertVerify(config *Config, dnsName string) {
verifier := ca.NewNameCertVerifier(dnsName, config.RootCAs, config.Time)
config.InsecureSkipVerify = true
config.VerifyConnection = func(state tls.ConnectionState) error {
return verifier(state.PeerCertificates)
}
}
// NewRestls return a Restls Connection
func NewRestls(ctx context.Context, conn net.Conn, config *Config) (net.Conn, error) {
clientHellowID := tls.HelloChrome_Auto
+5 -3
View File
@@ -30,6 +30,7 @@ type ShadowTLSOption struct {
PrivateKey string
ClientFingerprint string
SkipCertVerify bool
NameCertVerify string
Version int
ALPN []string
}
@@ -42,9 +43,10 @@ func NewShadowTLS(ctx context.Context, conn net.Conn, option *ShadowTLSOption) (
InsecureSkipVerify: option.SkipCertVerify,
ServerName: option.Host,
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
+4 -3
View File
@@ -62,9 +62,10 @@ func Dial(ctx context.Context, rawConn net.Conn, cfg ClientConfig) (*Conn, error
InsecureSkipVerify: cfg.SkipCertVerify,
NextProtos: cfg.ALPN,
},
Fingerprint: cfg.Fingerprint,
Certificate: cfg.Certificate,
PrivateKey: cfg.PrivateKey,
Fingerprint: cfg.Fingerprint,
NameCertVerify: cfg.NameCertVerify,
Certificate: cfg.Certificate,
PrivateKey: cfg.PrivateKey,
})
if err != nil {
_ = hidden.Close()
+1
View File
@@ -19,6 +19,7 @@ type ClientConfig struct {
ServerName string
SkipCertVerify bool
NameCertVerify string
ALPN []string
Fingerprint string
Certificate string
+5 -3
View File
@@ -21,6 +21,7 @@ type Option struct {
TLS bool
ECHConfig *ech.Config
SkipCertVerify bool
NameCertVerify string
Fingerprint string
Certificate string
PrivateKey string
@@ -55,9 +56,10 @@ func NewV2rayObfs(ctx context.Context, conn net.Conn, option *Option) (net.Conn,
InsecureSkipVerify: option.SkipCertVerify,
NextProtos: []string{"http/1.1"},
},
Fingerprint: option.Fingerprint,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
Fingerprint: option.Fingerprint,
NameCertVerify: option.NameCertVerify,
Certificate: option.Certificate,
PrivateKey: option.PrivateKey,
})
if err != nil {
return nil, err
+6 -3
View File
@@ -16,6 +16,7 @@ import (
type TLSConfig struct {
Host string
SkipCertVerify bool
NameCertVerify string
FingerPrint string
Certificate string
PrivateKey string
@@ -34,9 +35,10 @@ func (cfg *TLSConfig) ToStdConfig() (*tls.Config, error) {
InsecureSkipVerify: cfg.SkipCertVerify,
NextProtos: cfg.NextProtos,
},
Fingerprint: cfg.FingerPrint,
Certificate: cfg.Certificate,
PrivateKey: cfg.PrivateKey,
Fingerprint: cfg.FingerPrint,
NameCertVerify: cfg.NameCertVerify,
Certificate: cfg.Certificate,
PrivateKey: cfg.PrivateKey,
})
}
@@ -46,6 +48,7 @@ func StreamTLSConn(ctx context.Context, conn net.Conn, cfg *TLSConfig) (net.Conn
Config: *cfg.TLSMirror,
ServerName: cfg.Host,
SkipCertVerify: cfg.SkipCertVerify,
NameCertVerify: cfg.NameCertVerify,
ALPN: cfg.NextProtos,
Fingerprint: cfg.FingerPrint,
Certificate: cfg.Certificate,