lolly/internal/proxy/proxy_ssl.go
xfy a644e551af feat(proxy): 添加上游 SSL 配置和缓存有效期分段配置
- ProxySSLConfig: 支持自定义 CA、客户端证书(mTLS)、SNI、TLS 版本控制
- ProxyCacheValidConfig: 按 HTTP 状态码分段配置缓存有效期
- proxy_ssl.go: 实现 CreateTLSConfig 和 TLS 版本解析
- proxy.go: 集成 SSL 配置到 HostClient,实现 getCacheDuration 分段缓存
- 测试文件适配新配置

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 18:27:50 +08:00

101 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package proxy 反向代理包,为 Lolly HTTP 服务器提供反向代理功能。
//
// 该文件提供上游 SSL/TLS 配置支持,包括自定义 CA 证书、
// 客户端证书mTLS、SNI 和 TLS 版本控制。
package proxy
import (
"crypto/tls"
"crypto/x509"
"errors"
"os"
"strings"
"rua.plus/lolly/internal/config"
)
// TLS 版本字符串到 tls 常量的映射。
// 支持 TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3 格式(大小写不敏感)
var tlsVersionMap = map[string]uint16{
"TLSV1.0": tls.VersionTLS10,
"TLSV1.1": tls.VersionTLS11,
"TLSV1.2": tls.VersionTLS12,
"TLSV1.3": tls.VersionTLS13,
"": 0, // 空字符串表示使用默认
}
// CreateTLSConfig 从 ProxySSLConfig 创建 tls.Config。
//
// 参数:
// - cfg: 上游 SSL 配置
// - defaultServerName: 默认 SNI 名称(从目标 URL 提取)
//
// 返回值:
// - *tls.Config: TLS 配置对象
// - error: 配置错误(证书加载失败等)
//
// 注意事项:
// - cfg 为 nil 或 Enabled=false 时返回 nil
// - TrustedCA 加载失败时返回错误
// - ClientCert/ClientKey 加载失败时返回错误
func CreateTLSConfig(cfg *config.ProxySSLConfig, defaultServerName string) (*tls.Config, error) {
if cfg == nil || !cfg.Enabled {
return nil, nil
}
tlsCfg := &tls.Config{}
// SNI 配置
if cfg.ServerName != "" {
tlsCfg.ServerName = cfg.ServerName
} else if defaultServerName != "" {
tlsCfg.ServerName = defaultServerName
}
// 跳过证书验证(仅测试环境)
if cfg.InsecureSkipVerify {
tlsCfg.InsecureSkipVerify = true
}
// CA 证书验证
if cfg.TrustedCA != "" {
caData, err := os.ReadFile(cfg.TrustedCA)
if err != nil {
return nil, errors.New("failed to read CA certificate: " + err.Error())
}
caPool := x509.NewCertPool()
if !caPool.AppendCertsFromPEM(caData) {
return nil, errors.New("failed to parse CA certificate")
}
tlsCfg.RootCAs = caPool
}
// 客户端证书mTLS
if cfg.ClientCert != "" && cfg.ClientKey != "" {
cert, err := tls.LoadX509KeyPair(cfg.ClientCert, cfg.ClientKey)
if err != nil {
return nil, errors.New("failed to load client certificate: " + err.Error())
}
tlsCfg.Certificates = []tls.Certificate{cert}
}
// TLS 版本配置
if cfg.MinVersion != "" {
version, ok := tlsVersionMap[strings.ToUpper(cfg.MinVersion)]
if !ok {
return nil, errors.New("invalid TLS min version: " + cfg.MinVersion)
}
tlsCfg.MinVersion = version
}
if cfg.MaxVersion != "" {
version, ok := tlsVersionMap[strings.ToUpper(cfg.MaxVersion)]
if !ok {
return nil, errors.New("invalid TLS max version: " + cfg.MaxVersion)
}
tlsCfg.MaxVersion = version
}
return tlsCfg, nil
}