lolly/internal/config/performance_config.go
xfy 179090fa34 fix(security): 修复 2 个 CRITICAL + 6 个 HIGH 安全与代码质量问题
安全修复:
- ConnLimiter Acquire() TOCTOU 竞态: atomic.AddInt64 替代 loadInt64+addInt64
- Cache Purge token 时序侧信道: 改用 subtle.ConstantTimeCompare
- Lua Cosocket SSRF: 新增 ip_guard 两层 IP 检查(字面量+解析后),拒绝私有/回环地址
- X-Accel-Redirect 路径遍历: urlpath.Clean + 前缀拒绝(/internal/ /admin/)
- CRLF 注入: containsCRLF 校验变量展开后的 header 值,logging.Warn 可观测
- Proxy URI 注入: bytes.ContainsAny 检查 path 中的 @\r\n 危险字符

代码质量:
- disk_cache.go Set() 7 处静默 return 改为 logging.Error 日志记录
- config.go 从 2392 行拆分为 9 个按域文件(config/server/proxy/security/ssl/cache/performance/monitoring/variable)

验证: go build + vet + golangci-lint(0 issues) + test(83.2% 无回归) + race detector 全部通过

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 10:13:47 +08:00

259 lines
7.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 config
import (
"errors"
"fmt"
"net"
"time"
)
// HTTP2Config HTTP/2 配置。
//
// HTTP/2 提供多路复用、头部压缩和服务器推送等功能,
// 需要服务器配置 SSL/TLS 证书才能正常工作。
//
// 注意事项:
// - 必须配置有效的 SSL 证书TLS 1.2 或更高版本)
// - http2.enabled 仅在配置了 SSL/TLS 时生效
// - 客户端可以通过 ALPN 协商使用 HTTP/2 或 HTTP/1.1
//
// 使用示例:
//
// server:
// ssl:
// cert: "/etc/ssl/server.crt"
// key: "/etc/ssl/server.key"
// http2:
// enabled: true
// max_concurrent_streams: 128
// max_header_list_size: "16KB"
type HTTP2Config struct {
MaxConcurrentStreams int `yaml:"max_concurrent_streams"`
MaxHeaderListSize int `yaml:"max_header_list_size"`
IdleTimeout time.Duration `yaml:"idle_timeout"`
Enabled bool `yaml:"enabled"`
PushEnabled bool `yaml:"push_enabled"`
H2CEnabled bool `yaml:"h2c_enabled"`
GracefulShutdownTimeout time.Duration `yaml:"graceful_shutdown_timeout"`
}
// HTTP3Config HTTP/3 (QUIC) 配置。
//
// HTTP/3 基于 QUIC 协议,提供更快的连接建立和更低的延迟。
// 需要服务器配置 SSL/TLS 证书才能正常工作。
//
// 注意事项:
// - 必须配置有效的 SSL 证书
// - UDP 监听地址不能与 HTTP/1.1 或 HTTP/2 冲突
// - 0-RTT 特性可能带来重放攻击风险,需评估安全性
// - 部分网络环境可能限制 UDP 流量
//
// 使用示例:
//
// http3:
// enabled: true
// listen: ":443"
// max_streams: 1000
// idle_timeout: 30s
// enable_0rtt: true
type HTTP3Config struct {
Listen string `yaml:"listen"`
MaxStreams int `yaml:"max_streams"`
IdleTimeout time.Duration `yaml:"idle_timeout"`
Enabled bool `yaml:"enabled"`
Enable0RTT bool `yaml:"enable_0rtt"`
}
// PerformanceConfig 性能配置。
//
// 配置服务器性能优化相关参数。
//
// 注意事项:
// - GoroutinePool 复用 goroutine 减少创建开销
// - FileCache 缓存静态文件内容提升响应速度
// - Transport 配置代理连接的连接池参数
//
// 使用示例:
//
// performance:
// goroutine_pool:
// enabled: true
// max_workers: 1000
// file_cache:
// max_entries: 10000
// max_size: 1073741824
// transport:
// max_idle_conns: 100
type PerformanceConfig struct {
// GoroutinePool Goroutine 池配置
// 控制 worker goroutine 的复用行为
GoroutinePool GoroutinePoolConfig `yaml:"goroutine_pool"`
// FileCache 文件缓存配置
// 缓存静态文件内容避免重复磁盘 IO
FileCache FileCacheConfig `yaml:"file_cache"`
// Transport HTTP Transport 配置
// 代理连接池的参数设置
Transport TransportConfig `yaml:"transport"`
}
// GoroutinePoolConfig Goroutine 池配置。
//
// 复用 goroutine 减少创建和销毁开销。
//
// 注意事项:
// - Enabled 为 true 时启用 goroutine 池
// - MaxWorkers 限制最大并发 worker 数
// - MinWorkers 预热 worker 数量
// - IdleTimeout 空闲 worker 回收时间
//
// 使用示例:
//
// goroutine_pool:
// enabled: true
// max_workers: 1000
// min_workers: 100
// idle_timeout: 60s
type GoroutinePoolConfig struct {
// Enabled 是否启用
Enabled bool `yaml:"enabled"`
// MaxWorkers 最大 worker 数
// 限制同时运行的最大 goroutine 数量
MaxWorkers int `yaml:"max_workers"`
// MinWorkers 最小 worker 数(预热)
// 启动时预创建的 goroutine 数量
MinWorkers int `yaml:"min_workers"`
// IdleTimeout 空闲超时
// 空闲 worker 超过此时间将被回收
IdleTimeout time.Duration `yaml:"idle_timeout"`
}
// TransportConfig HTTP Transport 配置。
//
// 配置代理后端连接的连接池参数。
//
// 注意事项:
// - IdleConnTimeout 控制空闲连接的保持时间
// - MaxConnsPerHost 限制每个后端主机的总连接数(含活跃和空闲)
//
// 使用示例:
//
// transport:
// idle_conn_timeout: 90s
// max_conns_per_host: 100
type TransportConfig struct {
// IdleConnTimeout 空闲连接超时
// 空闲连接的最大存活时间
IdleConnTimeout time.Duration `yaml:"idle_conn_timeout"`
// MaxConnsPerHost 每主机最大连接数
// 单个后端主机的总连接数上限(包括活跃连接和空闲连接)
MaxConnsPerHost int `yaml:"max_conns_per_host"`
}
// ShutdownConfig 服务器关闭配置。
//
// 用于配置服务器在接收到不同信号时的关闭超时行为。
// 优雅停止会等待正在处理的请求完成,快速停止会立即中断连接。
//
// 注意事项:
// - graceful_timeout = 0 表示使用默认值30s
// - fast_timeout = 0 表示使用默认值5s
// - graceful_timeout 应显著大于 fast_timeout
// - 两个值都必须 >= 0负数在验证时会报错
//
// 使用示例:
//
// shutdown:
// graceful_timeout: 30s # SIGQUIT 优雅停止超时
// fast_timeout: 5s # SIGINT/SIGTERM 快速停止超时
type ShutdownConfig struct {
// GracefulTimeout 优雅停止超时SIGQUIT
// 接收到 SIGQUIT 信号后,等待活跃请求完成的最大时间
// 默认: 30s当值为 0 时使用默认值)
GracefulTimeout time.Duration `yaml:"graceful_timeout"`
// FastTimeout 快速停止超时SIGINT/SIGTERM
// 接收到 SIGINT 或 SIGTERM 信号后,等待服务器关闭的最大时间
// 默认: 5s当值为 0 时使用默认值)
FastTimeout time.Duration `yaml:"fast_timeout"`
}
// ResolverConfig DNS 解析器配置。
//
// 配置 DNS 解析器的行为,包括服务器地址、缓存 TTL、超时等。
// 启用后可实现动态 DNS 解析和缓存,支持后端域名的动态解析。
//
// 注意事项:
// - Enabled 为 true 时启用 DNS 解析器
// - Addresses 配置 DNS 服务器地址,如 "8.8.8.8:53"
// - Valid 为缓存有效期TTL建议 30s-300s
// - Timeout 为单次查询超时时间
//
// 使用示例:
//
// resolver:
// enabled: true
// addresses:
// - "8.8.8.8:53"
// - "8.8.4.4:53"
// valid: 30s
// timeout: 5s
// ipv4: true
// ipv6: false
// cache_size: 1024
type ResolverConfig struct {
Addresses []string `yaml:"addresses"`
Valid time.Duration `yaml:"valid"`
Timeout time.Duration `yaml:"timeout"`
CacheSize int `yaml:"cache_size"`
Enabled bool `yaml:"enabled"`
IPv4 bool `yaml:"ipv4"`
IPv6 bool `yaml:"ipv6"`
}
// TTL 返回缓存有效期Valid 的别名,便于代码理解)。
func (c *ResolverConfig) TTL() time.Duration {
return c.Valid
}
// Validate 验证 Resolver 配置。
//
// 检查 DNS 服务器地址格式、TTL 和超时设置的有效性。
//
// 返回值:
// - error: 验证失败时的错误信息
func (c *ResolverConfig) Validate() error {
if !c.Enabled {
return nil
}
if len(c.Addresses) == 0 {
return errors.New("resolver.addresses is required when enabled")
}
for _, addr := range c.Addresses {
if _, err := net.ResolveUDPAddr("udp", addr); err != nil {
return fmt.Errorf("invalid DNS address %s: %w", addr, err)
}
}
if c.Valid > 0 && c.Valid < time.Second {
return errors.New("resolver.valid must be at least 1s")
}
if c.Timeout > 0 && c.Timeout < time.Second {
return errors.New("resolver.timeout must be at least 1s")
}
if !c.IPv4 && !c.IPv6 {
return errors.New("at least one of ipv4 or ipv6 must be enabled")
}
return nil
}