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:
xfy 2026-06-03 01:14:09 +08:00
parent 3b84d62971
commit eb404f98a2

View File

@ -42,6 +42,7 @@ import (
// 当 OCSP 查询失败时TLS 握手仍可继续进行。
type OCSPManager struct {
responses map[string]*ocspResponse
certs map[string]certPair
client *http.Client
stopChan chan struct{}
refreshInterval time.Duration
@ -51,6 +52,11 @@ type OCSPManager struct {
running bool
}
type certPair struct {
cert *x509.Certificate
issuer *x509.Certificate
}
// ocspResponse OCSP 响应缓存条目。
//
// 保存 OCSP 响应数据及其元数据,用于证书状态验证。
@ -129,6 +135,7 @@ func NewOCSPManager(cfg *OCSPConfig) *OCSPManager {
return &OCSPManager{
responses: make(map[string]*ocspResponse),
certs: make(map[string]certPair),
client: &http.Client{
Timeout: timeout,
},
@ -182,24 +189,36 @@ func (m *OCSPManager) refreshLoop() {
// refreshAll 刷新所有缓存的 OCSP 响应。
func (m *OCSPManager) refreshAll() {
var toRefresh []string
m.mu.RLock()
certs := make([]string, 0, len(m.responses))
for serial := range m.responses {
certs = append(certs, serial)
for serial, resp := range m.responses {
if resp == nil || time.Now().After(resp.nextUpdate) || resp.status != statusValid {
toRefresh = append(toRefresh, serial)
}
}
m.mu.RUnlock()
for _, serial := range certs {
for _, serial := range toRefresh {
m.mu.RLock()
resp, ok := m.responses[serial]
pair, ok := m.certs[serial]
m.mu.RUnlock()
if ok && resp != nil {
// 检查是否需要刷新
if time.Now().Before(resp.nextUpdate) && resp.status == statusValid {
continue
}
if !ok {
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()
}
}
@ -226,6 +245,10 @@ func (m *OCSPManager) RegisterCertificate(cert *x509.Certificate, issuer *x509.C
serial := cert.SerialNumber.String()
m.mu.Lock()
m.certs[serial] = certPair{cert: cert, issuer: issuer}
m.mu.Unlock()
// 获取初始 OCSP 响应
response, err := m.fetchOCSP(cert, issuer)
if err != nil {