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:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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服务器,请勿混淆
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -19,6 +19,7 @@ type ClientConfig struct {
|
||||
|
||||
ServerName string
|
||||
SkipCertVerify bool
|
||||
NameCertVerify string
|
||||
ALPN []string
|
||||
Fingerprint string
|
||||
Certificate string
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user