mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-15 13:41:23 +08:00
136 lines
3.6 KiB
Go
136 lines
3.6 KiB
Go
package tls
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
CN "github.com/Dreamacro/clash/common/net"
|
|
|
|
xtls "github.com/xtls/go"
|
|
)
|
|
|
|
var tlsCertificates = make([]tls.Certificate, 0)
|
|
|
|
var mutex sync.RWMutex
|
|
var errNotMacth error = errors.New("certificate fingerprints do not match")
|
|
|
|
func AddCertificate(privateKey, certificate string) error {
|
|
mutex.Lock()
|
|
defer mutex.Unlock()
|
|
if cert, err := CN.ParseCert(certificate, privateKey); err != nil {
|
|
return err
|
|
} else {
|
|
tlsCertificates = append(tlsCertificates, cert)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetCertificates() []tls.Certificate {
|
|
mutex.RLock()
|
|
defer mutex.RUnlock()
|
|
return tlsCertificates
|
|
}
|
|
|
|
func verifyFingerprint(fingerprint *[32]byte) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
|
return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
|
// ssl pining
|
|
for i := range rawCerts {
|
|
rawCert := rawCerts[i]
|
|
cert, err := x509.ParseCertificate(rawCert)
|
|
if err == nil {
|
|
hash := sha256.Sum256(cert.Raw)
|
|
if bytes.Equal(fingerprint[:], hash[:]) {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
return errNotMacth
|
|
}
|
|
}
|
|
|
|
func convertFingerprint(fingerprint string) (*[32]byte, error) {
|
|
fingerprint = strings.TrimSpace(strings.Replace(fingerprint, ":", "", -1))
|
|
fpByte, err := hex.DecodeString(fingerprint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(fpByte) != 32 {
|
|
return nil, fmt.Errorf("fingerprint string length error,need sha25 fingerprint")
|
|
}
|
|
return (*[32]byte)(fpByte), nil
|
|
}
|
|
|
|
func GetDefaultTLSConfig() *tls.Config {
|
|
return GetGlobalTLSConfig(nil)
|
|
}
|
|
|
|
// GetSpecifiedFingerprintTLSConfig specified fingerprint
|
|
func GetSpecifiedFingerprintTLSConfig(tlsConfig *tls.Config, fingerprint string) (*tls.Config, error) {
|
|
if fingerprintBytes, err := convertFingerprint(fingerprint); err != nil {
|
|
return nil, err
|
|
} else {
|
|
tlsConfig = GetGlobalTLSConfig(tlsConfig)
|
|
tlsConfig.VerifyPeerCertificate = verifyFingerprint(fingerprintBytes)
|
|
tlsConfig.InsecureSkipVerify = true
|
|
return tlsConfig, nil
|
|
}
|
|
}
|
|
|
|
func GetGlobalTLSConfig(tlsConfig *tls.Config) *tls.Config {
|
|
if tlsConfig == nil {
|
|
return &tls.Config{
|
|
Certificates: tlsCertificates,
|
|
}
|
|
}
|
|
tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCertificates...)
|
|
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 {
|
|
tlsConfig=GetGlobalXTLSConfig(tlsConfig)
|
|
tlsConfig.VerifyPeerCertificate = verifyFingerprint(fingerprintBytes)
|
|
tlsConfig.InsecureSkipVerify = true
|
|
return tlsConfig, nil
|
|
}
|
|
}
|
|
|
|
func GetGlobalXTLSConfig(tlsConfig *xtls.Config) *xtls.Config {
|
|
xtlsCerts := make([]xtls.Certificate, len(tlsCertificates))
|
|
for _, cert := range tlsCertificates {
|
|
tlsSsaList := make([]xtls.SignatureScheme, len(cert.SupportedSignatureAlgorithms))
|
|
for _, ssa := range cert.SupportedSignatureAlgorithms {
|
|
tlsSsa := xtls.SignatureScheme(ssa)
|
|
tlsSsaList = append(tlsSsaList, tlsSsa)
|
|
}
|
|
xtlsCert := xtls.Certificate{
|
|
Certificate: cert.Certificate,
|
|
PrivateKey: cert.PrivateKey,
|
|
OCSPStaple: cert.OCSPStaple,
|
|
SignedCertificateTimestamps: cert.SignedCertificateTimestamps,
|
|
Leaf: cert.Leaf,
|
|
SupportedSignatureAlgorithms: tlsSsaList,
|
|
}
|
|
xtlsCerts = append(xtlsCerts, xtlsCert)
|
|
}
|
|
if tlsConfig == nil {
|
|
return &xtls.Config{
|
|
Certificates: xtlsCerts,
|
|
}
|
|
}
|
|
|
|
tlsConfig.Certificates = xtlsCerts
|
|
return tlsConfig
|
|
}
|