2022-07-10 20:44:24 +08:00
|
|
|
package tls
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/sha256"
|
|
|
|
"crypto/tls"
|
|
|
|
"crypto/x509"
|
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
"time"
|
2023-01-13 09:55:01 +08:00
|
|
|
|
|
|
|
xtls "github.com/xtls/go"
|
2022-07-10 20:44:24 +08:00
|
|
|
)
|
|
|
|
|
2023-01-13 09:55:01 +08:00
|
|
|
var globalFingerprints = make([][32]byte, 0)
|
2022-07-10 21:56:33 +08:00
|
|
|
var mutex sync.Mutex
|
2022-07-10 20:44:24 +08:00
|
|
|
|
2022-10-03 22:41:24 +08:00
|
|
|
func verifyPeerCertificateAndFingerprints(fingerprints *[][32]byte, insecureSkipVerify bool) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
2022-07-10 21:56:33 +08:00
|
|
|
return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
2022-07-11 12:37:27 +08:00
|
|
|
if insecureSkipVerify {
|
|
|
|
return nil
|
|
|
|
}
|
2022-07-10 20:44:24 +08:00
|
|
|
|
2022-07-10 21:56:33 +08:00
|
|
|
var preErr error
|
|
|
|
for i := range rawCerts {
|
|
|
|
rawCert := rawCerts[i]
|
|
|
|
cert, err := x509.ParseCertificate(rawCert)
|
|
|
|
if err == nil {
|
|
|
|
opts := x509.VerifyOptions{
|
|
|
|
CurrentTime: time.Now(),
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
2022-07-10 21:56:33 +08:00
|
|
|
if _, err := cert.Verify(opts); err == nil {
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
fingerprint := sha256.Sum256(cert.Raw)
|
2022-10-03 22:41:24 +08:00
|
|
|
for _, fp := range *fingerprints {
|
2022-07-10 21:56:33 +08:00
|
|
|
if bytes.Equal(fingerprint[:], fp[:]) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
preErr = err
|
|
|
|
}
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-10 21:56:33 +08:00
|
|
|
return preErr
|
|
|
|
}
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func AddCertFingerprint(fingerprint string) error {
|
2022-07-10 21:56:33 +08:00
|
|
|
fpByte, err2 := convertFingerprint(fingerprint)
|
|
|
|
if err2 != nil {
|
|
|
|
return err2
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex.Lock()
|
|
|
|
globalFingerprints = append(globalFingerprints, *fpByte)
|
|
|
|
mutex.Unlock()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func convertFingerprint(fingerprint string) (*[32]byte, error) {
|
2022-07-11 13:44:27 +08:00
|
|
|
fpByte, err := hex.DecodeString(fingerprint)
|
2022-07-10 20:44:24 +08:00
|
|
|
if err != nil {
|
2022-07-10 21:56:33 +08:00
|
|
|
return nil, err
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(fpByte) != 32 {
|
2022-07-10 21:56:33 +08:00
|
|
|
return nil, fmt.Errorf("fingerprint string length error,need sha25 fingerprint")
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
2022-07-10 21:56:33 +08:00
|
|
|
return (*[32]byte)(fpByte), nil
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetDefaultTLSConfig() *tls.Config {
|
2023-01-13 09:55:01 +08:00
|
|
|
return GetGlobalFingerprintTLSConfig(nil)
|
2022-07-10 21:56:33 +08:00
|
|
|
}
|
|
|
|
|
2022-07-11 13:42:28 +08:00
|
|
|
// GetSpecifiedFingerprintTLSConfig specified fingerprint
|
|
|
|
func GetSpecifiedFingerprintTLSConfig(tlsConfig *tls.Config, fingerprint string) (*tls.Config, error) {
|
2022-07-10 21:56:33 +08:00
|
|
|
if fingerprintBytes, err := convertFingerprint(fingerprint); err != nil {
|
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
if tlsConfig == nil {
|
|
|
|
return &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
2022-10-03 22:41:24 +08:00
|
|
|
VerifyPeerCertificate: verifyPeerCertificateAndFingerprints(&[][32]byte{*fingerprintBytes}, false),
|
2022-07-10 21:56:33 +08:00
|
|
|
}, nil
|
|
|
|
} else {
|
2022-10-03 22:41:24 +08:00
|
|
|
tlsConfig.VerifyPeerCertificate = verifyPeerCertificateAndFingerprints(&[][32]byte{*fingerprintBytes}, tlsConfig.InsecureSkipVerify)
|
2022-07-10 21:56:33 +08:00
|
|
|
tlsConfig.InsecureSkipVerify = true
|
|
|
|
return tlsConfig, nil
|
|
|
|
}
|
|
|
|
}
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
2023-01-13 09:55:01 +08:00
|
|
|
func GetGlobalFingerprintTLSConfig(tlsConfig *tls.Config) *tls.Config {
|
|
|
|
// If there's at least one fingerprint then we could skip the general check
|
|
|
|
// If there's no fingerprints but the config insists then we should skip.
|
|
|
|
// Otherwise we should do a general verification.
|
|
|
|
shouldSkipVerify := len(globalFingerprints) != 0 || tlsConfig != nil && tlsConfig.InsecureSkipVerify
|
2022-07-10 20:44:24 +08:00
|
|
|
if tlsConfig == nil {
|
2022-07-11 12:37:27 +08:00
|
|
|
return &tls.Config{
|
2023-01-13 09:55:01 +08:00
|
|
|
InsecureSkipVerify: shouldSkipVerify,
|
2022-10-03 22:41:24 +08:00
|
|
|
VerifyPeerCertificate: verifyPeerCertificateAndFingerprints(&globalFingerprints, false),
|
2022-07-11 12:37:27 +08:00
|
|
|
}
|
2022-07-10 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
2022-10-03 22:41:24 +08:00
|
|
|
tlsConfig.VerifyPeerCertificate = verifyPeerCertificateAndFingerprints(&globalFingerprints, tlsConfig.InsecureSkipVerify)
|
2023-01-13 09:55:01 +08:00
|
|
|
tlsConfig.InsecureSkipVerify = shouldSkipVerify
|
2022-07-10 20:44:24 +08:00
|
|
|
return tlsConfig
|
|
|
|
}
|
2022-07-11 13:42:28 +08:00
|
|
|
|
|
|
|
// 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,
|
2022-10-03 22:41:24 +08:00
|
|
|
VerifyPeerCertificate: verifyPeerCertificateAndFingerprints(&[][32]byte{*fingerprintBytes}, false),
|
2022-07-11 13:42:28 +08:00
|
|
|
}, nil
|
|
|
|
} else {
|
2022-10-03 22:41:24 +08:00
|
|
|
tlsConfig.VerifyPeerCertificate = verifyPeerCertificateAndFingerprints(&[][32]byte{*fingerprintBytes}, tlsConfig.InsecureSkipVerify)
|
2022-07-11 13:42:28 +08:00
|
|
|
tlsConfig.InsecureSkipVerify = true
|
|
|
|
return tlsConfig, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-13 09:55:01 +08:00
|
|
|
func GetGlobalFingerprintXTLSConfig(tlsConfig *xtls.Config) *xtls.Config {
|
|
|
|
shouldSkipVerify := len(globalFingerprints) != 0 || tlsConfig != nil && tlsConfig.InsecureSkipVerify
|
2022-07-11 13:42:28 +08:00
|
|
|
if tlsConfig == nil {
|
|
|
|
return &xtls.Config{
|
2023-01-13 09:55:01 +08:00
|
|
|
InsecureSkipVerify: shouldSkipVerify,
|
2022-10-03 22:41:24 +08:00
|
|
|
VerifyPeerCertificate: verifyPeerCertificateAndFingerprints(&globalFingerprints, false),
|
2022-07-11 13:42:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-03 22:41:24 +08:00
|
|
|
tlsConfig.VerifyPeerCertificate = verifyPeerCertificateAndFingerprints(&globalFingerprints, tlsConfig.InsecureSkipVerify)
|
2023-01-13 09:55:01 +08:00
|
|
|
tlsConfig.InsecureSkipVerify = shouldSkipVerify
|
2022-07-11 13:42:28 +08:00
|
|
|
return tlsConfig
|
|
|
|
}
|