lolly/internal/proxy/proxy_ssl.go
xfy 0c71a80b5a docs(proxy): 为反向代理模块添加标准化 godoc 注释
为 proxy 包所有文件添加完整文档注释:
- proxy: 反向代理核心(负载均衡、缓存、WebSocket、SSL/TLS)
- headers: X-Forwarded 系列请求头设置
- health: 后端健康检查
- proxy_ssl: 上游 SSL/TLS 配置
- redirect_rewrite: 重定向响应改写
- tempfile_cleaner: 临时文件清理

包级注释详细说明支持的负载均衡算法、故障转移机制、
代理缓存策略、重定向改写模式等核心功能。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 10:59:35 +08:00

121 lines
3.4 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 版本控制。
//
// 主要功能:
// - 自定义 CA 证书验证:支持指定受信任的 CA 证书文件
// - 客户端证书认证mTLS支持双向 TLS 认证
// - SNI 支持:自动从目标 URL 提取或使用配置的主机名
// - TLS 版本控制:支持 TLSv1.0 到 TLSv1.3 的最小/最大版本限制
// - 跳过证书验证:仅测试环境使用
//
// 主要用途:
// 用于代理与上游服务器之间的 TLS 连接配置,支持自签名证书、
// 内部 CA 签发证书以及双向认证场景。
//
// 注意事项:
// - InsecureSkipVerify 仅建议在测试环境使用
// - 证书文件路径为绝对路径或相对于工作目录
//
// 作者xfy
package proxy
import (
"crypto/tls"
"crypto/x509"
"errors"
"os"
"strings"
"rua.plus/lolly/internal/config"
)
// tlsVersionMap TLS 版本字符串到 tls 常量的映射表。
//
// 支持 TLSv1.0、TLSv1.1、TLSv1.2、TLSv1.3 格式(大小写不敏感)。
// 空字符串表示使用 Go 标准库默认值。
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
}