fix(ssl): implement OCSP refreshAll to actually refresh stale responses
refreshAll() was a no-op — it checked which entries needed refreshing but never called fetchOCSP. Now it: - Stores cert/issuer pairs when registering certificates - Actually fetches fresh OCSP responses for stale/expired entries - Updates error counts and marks entries as failed after max retries
This commit is contained in:
parent
3b84d62971
commit
eb404f98a2
@ -42,6 +42,7 @@ import (
|
|||||||
// 当 OCSP 查询失败时,TLS 握手仍可继续进行。
|
// 当 OCSP 查询失败时,TLS 握手仍可继续进行。
|
||||||
type OCSPManager struct {
|
type OCSPManager struct {
|
||||||
responses map[string]*ocspResponse
|
responses map[string]*ocspResponse
|
||||||
|
certs map[string]certPair
|
||||||
client *http.Client
|
client *http.Client
|
||||||
stopChan chan struct{}
|
stopChan chan struct{}
|
||||||
refreshInterval time.Duration
|
refreshInterval time.Duration
|
||||||
@ -51,6 +52,11 @@ type OCSPManager struct {
|
|||||||
running bool
|
running bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type certPair struct {
|
||||||
|
cert *x509.Certificate
|
||||||
|
issuer *x509.Certificate
|
||||||
|
}
|
||||||
|
|
||||||
// ocspResponse OCSP 响应缓存条目。
|
// ocspResponse OCSP 响应缓存条目。
|
||||||
//
|
//
|
||||||
// 保存 OCSP 响应数据及其元数据,用于证书状态验证。
|
// 保存 OCSP 响应数据及其元数据,用于证书状态验证。
|
||||||
@ -129,6 +135,7 @@ func NewOCSPManager(cfg *OCSPConfig) *OCSPManager {
|
|||||||
|
|
||||||
return &OCSPManager{
|
return &OCSPManager{
|
||||||
responses: make(map[string]*ocspResponse),
|
responses: make(map[string]*ocspResponse),
|
||||||
|
certs: make(map[string]certPair),
|
||||||
client: &http.Client{
|
client: &http.Client{
|
||||||
Timeout: timeout,
|
Timeout: timeout,
|
||||||
},
|
},
|
||||||
@ -182,25 +189,37 @@ func (m *OCSPManager) refreshLoop() {
|
|||||||
|
|
||||||
// refreshAll 刷新所有缓存的 OCSP 响应。
|
// refreshAll 刷新所有缓存的 OCSP 响应。
|
||||||
func (m *OCSPManager) refreshAll() {
|
func (m *OCSPManager) refreshAll() {
|
||||||
|
var toRefresh []string
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
certs := make([]string, 0, len(m.responses))
|
for serial, resp := range m.responses {
|
||||||
for serial := range m.responses {
|
if resp == nil || time.Now().After(resp.nextUpdate) || resp.status != statusValid {
|
||||||
certs = append(certs, serial)
|
toRefresh = append(toRefresh, serial)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m.mu.RUnlock()
|
m.mu.RUnlock()
|
||||||
|
|
||||||
for _, serial := range certs {
|
for _, serial := range toRefresh {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
resp, ok := m.responses[serial]
|
pair, ok := m.certs[serial]
|
||||||
m.mu.RUnlock()
|
m.mu.RUnlock()
|
||||||
|
if !ok {
|
||||||
if ok && resp != nil {
|
|
||||||
// 检查是否需要刷新
|
|
||||||
if time.Now().Before(resp.nextUpdate) && resp.status == statusValid {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response, err := m.fetchOCSP(pair.cert, pair.issuer)
|
||||||
|
m.mu.Lock()
|
||||||
|
if err != nil {
|
||||||
|
if existing, exists := m.responses[serial]; exists {
|
||||||
|
existing.errors++
|
||||||
|
if existing.errors >= m.maxRetries {
|
||||||
|
existing.status = statusFailed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
m.responses[serial] = response
|
||||||
|
}
|
||||||
|
m.mu.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterCertificate 注册证书以进行 OCSP Stapling。
|
// RegisterCertificate 注册证书以进行 OCSP Stapling。
|
||||||
@ -226,6 +245,10 @@ func (m *OCSPManager) RegisterCertificate(cert *x509.Certificate, issuer *x509.C
|
|||||||
|
|
||||||
serial := cert.SerialNumber.String()
|
serial := cert.SerialNumber.String()
|
||||||
|
|
||||||
|
m.mu.Lock()
|
||||||
|
m.certs[serial] = certPair{cert: cert, issuer: issuer}
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
// 获取初始 OCSP 响应
|
// 获取初始 OCSP 响应
|
||||||
response, err := m.fetchOCSP(cert, issuer)
|
response, err := m.fetchOCSP(cert, issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user