2020-09-30 17:46:33 +08:00
|
|
|
|
package sslconfigs
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2022-03-18 17:04:53 +08:00
|
|
|
|
"bytes"
|
2023-03-18 22:15:13 +08:00
|
|
|
|
"context"
|
2020-09-30 17:46:33 +08:00
|
|
|
|
"crypto/tls"
|
|
|
|
|
|
"crypto/x509"
|
2021-12-13 14:58:45 +08:00
|
|
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
|
|
|
|
|
"golang.org/x/net/http2"
|
2022-03-18 20:20:28 +08:00
|
|
|
|
"time"
|
2020-09-30 17:46:33 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// TLSVersion TLS Version
|
2020-09-30 17:46:33 +08:00
|
|
|
|
type TLSVersion = string
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// TLSCipherSuite Cipher Suites
|
2020-09-30 17:46:33 +08:00
|
|
|
|
type TLSCipherSuite = string
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// SSLPolicy SSL配置
|
2020-09-30 17:46:33 +08:00
|
|
|
|
type SSLPolicy struct {
|
|
|
|
|
|
Id int64 `yaml:"id" json:"id"` // ID
|
|
|
|
|
|
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
|
|
|
|
|
|
|
|
|
|
|
|
CertRefs []*SSLCertRef `yaml:"certRefs" json:"certRefs"`
|
|
|
|
|
|
Certs []*SSLCertConfig `yaml:"certs" json:"certs"`
|
|
|
|
|
|
ClientAuthType SSLClientAuthType `yaml:"clientAuthType" json:"clientAuthType"` // 客户端认证类型
|
2020-10-01 16:01:28 +08:00
|
|
|
|
ClientCARefs []*SSLCertRef `yaml:"clientCARefs" json:"clientCARefs"` // 客户端认证CA证书引用
|
|
|
|
|
|
ClientCACerts []*SSLCertConfig `yaml:"clientCACerts" json:"clientCACerts"` // 客户端认证CA
|
2020-09-30 17:46:33 +08:00
|
|
|
|
|
2020-10-01 16:01:28 +08:00
|
|
|
|
MinVersion TLSVersion `yaml:"minVersion" json:"minVersion"` // 支持的最小版本
|
|
|
|
|
|
CipherSuitesIsOn bool `yaml:"cipherSuitesIsOn" json:"cipherSuitesIsOn"` // 是否自定义加密算法套件
|
|
|
|
|
|
CipherSuites []TLSCipherSuite `yaml:"cipherSuites" json:"cipherSuites"` // 加密算法套件
|
2020-09-30 17:46:33 +08:00
|
|
|
|
|
2020-10-01 16:01:28 +08:00
|
|
|
|
HSTS *HSTSConfig `yaml:"hsts" json:"hsts"` // HSTS配置
|
2023-06-01 17:48:01 +08:00
|
|
|
|
HTTP2Enabled bool `yaml:"http2Enabled" json:"http2Enabled"` // 是否启用HTTP/2
|
|
|
|
|
|
HTTP3Enabled bool `yaml:"http3Enabled" json:"http3Enabled"` // 是否启用HTTP/3
|
2020-09-30 17:46:33 +08:00
|
|
|
|
|
2022-03-10 11:54:58 +08:00
|
|
|
|
OCSPIsOn bool `yaml:"ocspIsOn" json:"ocspIsOn"` // 是否启用OCSP
|
|
|
|
|
|
|
2020-09-30 17:46:33 +08:00
|
|
|
|
nameMapping map[string]*tls.Certificate // dnsName => cert
|
|
|
|
|
|
|
|
|
|
|
|
minVersion uint16
|
|
|
|
|
|
cipherSuites []uint16
|
|
|
|
|
|
|
|
|
|
|
|
clientCAPool *x509.CertPool
|
2021-12-13 14:58:45 +08:00
|
|
|
|
|
|
|
|
|
|
tlsConfig *tls.Config
|
2022-03-18 20:20:28 +08:00
|
|
|
|
|
|
|
|
|
|
ocspExpiresAt int64 // OCSP最早过期时间
|
2020-09-30 17:46:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// Init 校验配置
|
2023-03-18 22:15:13 +08:00
|
|
|
|
func (this *SSLPolicy) Init(ctx context.Context) error {
|
2021-12-13 14:58:45 +08:00
|
|
|
|
this.nameMapping = map[string]*tls.Certificate{}
|
|
|
|
|
|
|
2020-10-01 16:01:28 +08:00
|
|
|
|
// certs
|
2021-12-13 14:58:45 +08:00
|
|
|
|
var certs = []tls.Certificate{}
|
2020-10-01 16:01:28 +08:00
|
|
|
|
for _, cert := range this.Certs {
|
2023-03-18 22:15:13 +08:00
|
|
|
|
err := cert.Init(ctx)
|
2020-10-01 16:01:28 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
2022-03-18 20:20:28 +08:00
|
|
|
|
if this.OCSPIsOn && len(cert.OCSP) > 0 && cert.OCSPExpiresAt > time.Now().Unix() {
|
|
|
|
|
|
if this.ocspExpiresAt == 0 || cert.OCSPExpiresAt < this.ocspExpiresAt {
|
|
|
|
|
|
this.ocspExpiresAt = cert.OCSPExpiresAt
|
|
|
|
|
|
}
|
2022-03-10 11:54:58 +08:00
|
|
|
|
cert.CertObject().OCSPStaple = cert.OCSP
|
|
|
|
|
|
}
|
2021-12-13 14:58:45 +08:00
|
|
|
|
certs = append(certs, *cert.CertObject())
|
|
|
|
|
|
for _, dnsName := range cert.DNSNames {
|
|
|
|
|
|
this.nameMapping[dnsName] = cert.CertObject()
|
|
|
|
|
|
}
|
2020-09-30 17:46:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-10-01 16:01:28 +08:00
|
|
|
|
// CA certs
|
2023-02-09 11:31:33 +08:00
|
|
|
|
this.clientCAPool = x509.NewCertPool()
|
|
|
|
|
|
|
2020-10-01 16:01:28 +08:00
|
|
|
|
for _, cert := range this.ClientCACerts {
|
2023-03-18 22:15:13 +08:00
|
|
|
|
err := cert.Init(ctx)
|
2020-09-30 17:46:33 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
2021-12-13 14:58:45 +08:00
|
|
|
|
certs = append(certs, *cert.CertObject())
|
|
|
|
|
|
for _, dnsName := range cert.DNSNames {
|
|
|
|
|
|
this.nameMapping[dnsName] = cert.CertObject()
|
|
|
|
|
|
}
|
2023-02-09 11:31:33 +08:00
|
|
|
|
|
|
|
|
|
|
for _, caCert := range cert.CACerts() {
|
|
|
|
|
|
this.clientCAPool.AddCert(caCert)
|
|
|
|
|
|
}
|
2020-09-30 17:46:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// min version
|
|
|
|
|
|
this.convertMinVersion()
|
|
|
|
|
|
|
|
|
|
|
|
// cipher suite categories
|
|
|
|
|
|
this.initCipherSuites()
|
|
|
|
|
|
|
|
|
|
|
|
// hsts
|
|
|
|
|
|
if this.HSTS != nil {
|
|
|
|
|
|
err := this.HSTS.Init()
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// tls config
|
|
|
|
|
|
this.tlsConfig = &tls.Config{}
|
|
|
|
|
|
cipherSuites := this.TLSCipherSuites()
|
|
|
|
|
|
if !this.CipherSuitesIsOn || len(cipherSuites) == 0 {
|
|
|
|
|
|
cipherSuites = nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-06-01 17:48:01 +08:00
|
|
|
|
var nextProto = []string{}
|
2021-12-13 14:58:45 +08:00
|
|
|
|
if this.HTTP2Enabled {
|
|
|
|
|
|
nextProto = []string{http2.NextProtoTLS}
|
|
|
|
|
|
}
|
|
|
|
|
|
this.tlsConfig = &tls.Config{
|
|
|
|
|
|
Certificates: certs,
|
|
|
|
|
|
MinVersion: this.TLSMinVersion(),
|
|
|
|
|
|
CipherSuites: cipherSuites,
|
|
|
|
|
|
GetCertificate: nil,
|
|
|
|
|
|
ClientAuth: GoSSLClientAuthType(this.ClientAuthType),
|
|
|
|
|
|
ClientCAs: this.CAPool(),
|
|
|
|
|
|
NextProtos: nextProto,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-09-30 17:46:33 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// TLSMinVersion 取得最小版本
|
2020-09-30 17:46:33 +08:00
|
|
|
|
func (this *SSLPolicy) TLSMinVersion() uint16 {
|
|
|
|
|
|
return this.minVersion
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// TLSCipherSuites 套件
|
2020-09-30 17:46:33 +08:00
|
|
|
|
func (this *SSLPolicy) TLSCipherSuites() []uint16 {
|
|
|
|
|
|
return this.cipherSuites
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// MatchDomain 校验是否匹配某个域名
|
2020-09-30 17:46:33 +08:00
|
|
|
|
func (this *SSLPolicy) MatchDomain(domain string) (cert *tls.Certificate, ok bool) {
|
2021-12-13 14:58:45 +08:00
|
|
|
|
cert, ok = this.nameMapping[domain]
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for name, cert := range this.nameMapping {
|
|
|
|
|
|
if configutils.MatchDomain(name, domain) {
|
|
|
|
|
|
return cert, true
|
2020-09-30 17:46:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil, false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// FirstCert 取得第一个证书
|
2020-09-30 17:46:33 +08:00
|
|
|
|
func (this *SSLPolicy) FirstCert() *tls.Certificate {
|
|
|
|
|
|
for _, cert := range this.Certs {
|
|
|
|
|
|
return cert.CertObject()
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-12-13 14:58:45 +08:00
|
|
|
|
// CAPool CA证书Pool,用于TLS对客户端进行认证
|
2020-09-30 17:46:33 +08:00
|
|
|
|
func (this *SSLPolicy) CAPool() *x509.CertPool {
|
|
|
|
|
|
return this.clientCAPool
|
|
|
|
|
|
}
|
2021-12-13 14:58:45 +08:00
|
|
|
|
|
|
|
|
|
|
func (this *SSLPolicy) TLSConfig() *tls.Config {
|
|
|
|
|
|
return this.tlsConfig
|
|
|
|
|
|
}
|
2022-03-18 17:04:53 +08:00
|
|
|
|
|
|
|
|
|
|
// ContainsCert 检查是否包括某个证书
|
|
|
|
|
|
func (this *SSLPolicy) ContainsCert(certId int64) bool {
|
|
|
|
|
|
for _, cert := range this.Certs {
|
|
|
|
|
|
if cert.Id == certId {
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// UpdateCertOCSP 修改某个证书的OCSP
|
2022-03-18 20:20:28 +08:00
|
|
|
|
func (this *SSLPolicy) UpdateCertOCSP(certId int64, ocsp []byte, expiresAt int64) {
|
|
|
|
|
|
var nowTime = time.Now().Unix()
|
|
|
|
|
|
|
2022-03-18 17:04:53 +08:00
|
|
|
|
for _, cert := range this.Certs {
|
|
|
|
|
|
if cert.Id == certId {
|
|
|
|
|
|
cert.OCSP = ocsp
|
2022-03-18 20:20:28 +08:00
|
|
|
|
cert.OCSPExpiresAt = expiresAt
|
2022-03-18 17:04:53 +08:00
|
|
|
|
cert.CertObject().OCSPStaple = cert.OCSP
|
|
|
|
|
|
|
|
|
|
|
|
// 修改tlsConfig中的cert
|
2022-03-18 20:20:28 +08:00
|
|
|
|
for index, certObj := range this.tlsConfig.Certificates {
|
|
|
|
|
|
if this.certIsEqual(*cert.CertObject(), certObj) {
|
|
|
|
|
|
if len(cert.OCSP) > 0 && cert.OCSPExpiresAt > nowTime {
|
|
|
|
|
|
this.tlsConfig.Certificates[index].OCSPStaple = ocsp
|
|
|
|
|
|
|
|
|
|
|
|
// 重置过期时间
|
|
|
|
|
|
if this.ocspExpiresAt == 0 || cert.OCSPExpiresAt < this.ocspExpiresAt {
|
|
|
|
|
|
this.ocspExpiresAt = cert.OCSPExpiresAt
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.tlsConfig.Certificates[index].OCSPStaple = nil
|
|
|
|
|
|
}
|
2022-03-18 17:04:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-18 20:20:28 +08:00
|
|
|
|
// CheckOCSP 检查OCSP过期时间
|
|
|
|
|
|
func (this *SSLPolicy) CheckOCSP() {
|
|
|
|
|
|
if !this.OCSPIsOn || this.ocspExpiresAt == 0 {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var nowTime = time.Now().Unix()
|
|
|
|
|
|
if this.ocspExpiresAt > nowTime {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
this.ocspExpiresAt = 0
|
|
|
|
|
|
|
|
|
|
|
|
for _, cert := range this.Certs {
|
|
|
|
|
|
if cert.OCSPExpiresAt > 0 && cert.OCSPExpiresAt < nowTime+1 {
|
|
|
|
|
|
// 重置OCSP
|
|
|
|
|
|
cert.OCSP = nil
|
|
|
|
|
|
cert.OCSPExpiresAt = 0
|
|
|
|
|
|
for index, certObj := range this.tlsConfig.Certificates {
|
|
|
|
|
|
if this.certIsEqual(*cert.CertObject(), certObj) {
|
|
|
|
|
|
this.tlsConfig.Certificates[index].OCSPStaple = nil
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if len(cert.OCSP) > 0 && cert.OCSPExpiresAt > nowTime && (this.ocspExpiresAt == 0 || cert.OCSPExpiresAt < this.ocspExpiresAt) {
|
|
|
|
|
|
// 重置过期时间
|
|
|
|
|
|
this.ocspExpiresAt = cert.OCSPExpiresAt
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// OcspExpiresAt OCSP最近过期时间
|
|
|
|
|
|
func (this *SSLPolicy) OcspExpiresAt() int64 {
|
|
|
|
|
|
return this.ocspExpiresAt
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-18 17:04:53 +08:00
|
|
|
|
func (this *SSLPolicy) certIsEqual(cert1 tls.Certificate, cert2 tls.Certificate) bool {
|
|
|
|
|
|
var b1 = cert1.Certificate
|
|
|
|
|
|
var b2 = cert2.Certificate
|
|
|
|
|
|
if len(b1) != len(b2) {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for index, b := range b1 {
|
2023-08-08 15:12:28 +08:00
|
|
|
|
if !bytes.Equal(b, b2[index]) {
|
2022-03-18 17:04:53 +08:00
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|