// 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" "rua.plus/lolly/internal/logging" ) // 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 版本配置:默认 MinVersion = TLS 1.2 tlsCfg.MinVersion = tls.VersionTLS12 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 } // 警告:TLS 1.0/1.1 已不安全,不应在生产环境使用 if tlsCfg.MinVersion < tls.VersionTLS12 { logging.Warn().Msgf("上游 TLS MinVersion 设置为 %s(低于 TLS 1.2),存在安全风险", cfg.MinVersion) } 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 }