GoProxy
GoProxy是一个功能强大的Go语言HTTP代理库,支持HTTP、HTTPS和WebSocket代理,并提供了丰富的功能和扩展点。
功能特性
- 支持HTTP、HTTPS和WebSocket代理
- 支持正向代理和反向代理
- 支持HTTPS解密(中间人模式)
- 自定义CA证书和私钥
- 动态证书生成与缓存
- 通配符域名证书支持
- 支持RSA和ECDSA证书算法选择
- 支持上游代理链
- 支持多后端DNS解析和负载均衡
- 支持一个域名对应多个后端服务器
- 支持多种负载均衡策略(轮询、随机、第一个可用)
- 支持通配符域名解析
- 支持自定义DNS解析规则
- 支持动态添加/删除后端服务器
- 支持健康检查
- 支持请求重试
- 支持HTTP缓存
- 支持请求限流
- 支持请求/响应压缩
- 支持gzip压缩
- 智能压缩决策
- 可配置压缩级别
- 支持最小压缩大小
- 支持多种内容类型
- 支持监控指标收集(Prometheus格式)
- 请求总数和延迟统计
- 请求和响应大小统计
- 错误计数
- 活跃连接数
- 连接池大小
- 缓存命中率
- 内存使用量
- 后端健康状态
- 后端响应时间
- 支持自定义处理逻辑(委托模式)
- 支持DNS缓存
- 支持认证授权
- JWT认证
- 基于角色的访问控制
- 用户管理
- 权限管理
安装
go get github.com/darkit/goproxy
快速开始
正向代理
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy"
)
func main() {
// 创建代理
p := goproxy.New(nil)
// 启动HTTP服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
启用HTTPS解密
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy/pkg/config"
"github.com/darkit/goproxy"
)
func main() {
// 创建配置
cfg := config.DefaultConfig()
cfg.DecryptHTTPS = true
cfg.CACert = "ca.crt" // CA证书路径
cfg.CAKey = "ca.key" // CA私钥路径
cfg.UseECDSA = true // 使用ECDSA生成证书(默认为false,使用RSA)
// 可选:使用自定义TLS证书
// cfg.TLSCert = "server.crt"
// cfg.TLSKey = "server.key"
// 创建证书缓存
certCache := &goproxy.MemCertCache{}
// 创建代理
p := goproxy.New(&goproxy.Options{
Config: cfg,
CertCache: certCache,
})
// 启动HTTP服务器
log.Println("HTTPS解密代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
注意: 使用HTTPS解密功能时,需要在客户端安装CA证书,否则会出现证书警告。
反向代理
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy/pkg/config"
"github.com/darkit/goproxy"
)
func main() {
// 创建配置
cfg := config.DefaultConfig()
cfg.ReverseProxy = true
cfg.EnableURLRewrite = true
cfg.AddXForwardedFor = true
cfg.AddXRealIP = true
// 创建自定义委托
delegate := &ReverseProxyDelegate{
backend: "localhost:8081",
}
// 创建代理
p := goproxy.New(&goproxy.Options{
Config: cfg,
Delegate: delegate,
})
// 启动HTTP服务器
log.Println("反向代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
// ReverseProxyDelegate 反向代理委托
type ReverseProxyDelegate struct {
goproxy.DefaultDelegate
backend string
}
// ResolveBackend 解析后端服务器
func (d *ReverseProxyDelegate) ResolveBackend(req *http.Request) (string, error) {
return d.backend, nil
}
自定义委托
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy"
)
func main() {
// 创建自定义委托
delegate := &CustomDelegate{}
// 创建代理
p := goproxy.New(&goproxy.Options{
Delegate: delegate,
})
// 启动HTTP服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
// CustomDelegate 自定义委托
type CustomDelegate struct {
goproxy.DefaultDelegate
}
// BeforeRequest 请求前事件
func (d *CustomDelegate) BeforeRequest(ctx *goproxy.Context) {
log.Printf("请求: %s %s\n", ctx.Req.Method, ctx.Req.URL.String())
}
// BeforeResponse 响应前事件
func (d *CustomDelegate) BeforeResponse(ctx *goproxy.Context, resp *http.Response, err error) {
if err != nil {
log.Printf("响应错误: %v\n", err)
return
}
log.Printf("响应: %d %s\n", resp.StatusCode, resp.Status)
}
完整示例
- 正向代理示例: cmd/example/main.go
- 反向代理示例: cmd/reverse_proxy_example/main.go
使用函数式选项模式
package main
import (
"log"
"net/http"
"time"
"github.com/darkit/goproxy/pkg/metrics"
"github.com/darkit/goproxy"
)
func main() {
// 创建监控指标
metricsCollector := metrics.NewSimpleMetrics()
// 创建证书缓存
certCache := &goproxy.MemCertCache{}
// 使用函数式选项模式创建代理
p := goproxy.NewProxy(
// 启用HTTPS解密
goproxy.WithDecryptHTTPS(certCache),
goproxy.WithCACertAndKey("ca.crt", "ca.key"),
// 设置监控指标
goproxy.WithMetrics(metricsCollector),
// 设置请求超时和连接池
goproxy.WithRequestTimeout(30 * time.Second),
goproxy.WithConnectionPoolSize(100),
goproxy.WithIdleTimeout(90 * time.Second),
// 启用DNS缓存
goproxy.WithDNSCacheTTL(10 * time.Minute),
// 启用请求重试
goproxy.WithEnableRetry(3, 1*time.Second, 10*time.Second),
// 启用CORS支持
goproxy.WithEnableCORS(true),
)
// 启动HTTP服务器和监控服务器
go func() {
log.Println("监控服务器启动在 :8081")
http.Handle("/metrics", metricsCollector.GetHandler())
if err := http.ListenAndServe(":8081", nil); err != nil {
log.Fatalf("监控服务器启动失败: %v", err)
}
}()
// 启动代理服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
多后端DNS解析和负载均衡
package main
import (
"log"
"net/http"
"time"
"github.com/darkit/goproxy/pkg/dns"
"github.com/darkit/goproxy"
)
func main() {
// 创建DNS解析器
resolver := dns.NewResolver(
dns.WithLoadBalanceStrategy(dns.RoundRobin), // 设置负载均衡策略
dns.WithTTL(5*time.Minute), // 设置DNS缓存TTL
)
// 添加多个后端服务器
resolver.AddWithPort("api.example.com", "192.168.1.1", 8080)
resolver.AddWithPort("api.example.com", "192.168.1.2", 8080)
resolver.AddWithPort("api.example.com", "192.168.1.3", 8080)
// 添加通配符域名解析
resolver.AddWildcardWithPort("*.example.com", "192.168.1.1", 8080)
resolver.AddWildcardWithPort("*.example.com", "192.168.1.2", 8080)
// 创建自定义委托
delegate := &CustomDelegate{
resolver: resolver,
}
// 创建代理
p := goproxy.New(&goproxy.Options{
Delegate: delegate,
})
// 启动HTTP服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
// CustomDelegate 自定义委托
type CustomDelegate struct {
goproxy.DefaultDelegate
resolver *dns.CustomResolver
}
// ResolveBackend 解析后端服务器
func (d *CustomDelegate) ResolveBackend(req *http.Request) (string, error) {
// 从请求中获取目标主机
host := req.Host
if host == "" {
host = req.URL.Host
}
// 解析域名获取后端服务器
endpoint, err := d.resolver.ResolveWithPort(host, 80)
if err != nil {
return "", err
}
return endpoint.String(), nil
}
从配置文件加载DNS规则
package main
import (
"encoding/json"
"log"
"net/http"
"os"
"github.com/darkit/goproxy/pkg/dns"
"github.com/darkit/goproxy"
)
func main() {
// 创建DNS解析器
resolver := dns.NewResolver()
// 从JSON文件加载DNS规则
if err := loadDNSConfig(resolver, "dns_config.json"); err != nil {
log.Fatalf("加载DNS配置失败: %v", err)
}
// 创建自定义委托
delegate := &CustomDelegate{
resolver: resolver,
}
// 创建代理
p := goproxy.New(&goproxy.Options{
Delegate: delegate,
})
// 启动HTTP服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
// DNSConfig DNS配置结构
type DNSConfig struct {
Records map[string][]string `json:"records"` // 域名到IP地址列表的映射
Wildcards map[string][]string `json:"wildcards"` // 通配符域名到IP地址列表的映射
}
func loadDNSConfig(resolver *dns.CustomResolver, filename string) error {
data, err := os.ReadFile(filename)
if err != nil {
return err
}
var config DNSConfig
if err := json.Unmarshal(data, &config); err != nil {
return err
}
// 加载精确匹配记录
for host, ips := range config.Records {
for _, ip := range ips {
if err := resolver.Add(host, ip); err != nil {
return err
}
}
}
// 加载通配符记录
for pattern, ips := range config.Wildcards {
for _, ip := range ips {
if err := resolver.AddWildcard(pattern, ip); err != nil {
return err
}
}
}
return nil
}
示例配置文件 dns_config.json
:
{
"records": {
"api.example.com": [
"192.168.1.1:8080",
"192.168.1.2:8080",
"192.168.1.3:8080"
]
},
"wildcards": {
"*.example.com": [
"192.168.1.1:8080",
"192.168.1.2:8080"
]
}
}
动态管理后端服务器
// 添加新的后端服务器
resolver.AddWithPort("api.example.com", "192.168.1.4", 8080)
// 删除特定的后端服务器
resolver.RemoveEndpoint("api.example.com", "192.168.1.1", 8080)
// 删除整个域名记录
resolver.Remove("api.example.com")
// 清除所有记录
resolver.Clear()
架构设计
GoProxy采用模块化设计,主要包含以下模块:
- 代理核心(Proxy):处理HTTP请求和响应,实现代理功能
- 反向代理(ReverseProxy):处理反向代理请求,支持请求修改
- 路由(Router):基于主机名、路径、正则表达式等规则路由请求到不同的后端
- 代理上下文(Context):保存请求上下文信息,用于在处理过程中传递数据
- 代理委托(Delegate):定义代理处理请求的各个阶段的回调方法,用于自定义处理逻辑
- 连接缓冲区(ConnBuffer):封装网络连接,提供缓冲读写功能
- 负载均衡(LoadBalancer):实现负载均衡算法,支持轮询、随机、权重等
- 健康检查(HealthChecker):检查上游服务器的健康状态,自动剔除不健康的服务器
- 缓存(Cache):实现HTTP缓存,减少重复请求
- 缓存适配器(CacheAdapter):统一不同缓存实现的接口,提高代码可读性和性能
- 证书生成(CertGenerator):动态生成TLS证书,支持HTTPS解密
- 限流(RateLimit):实现请求限流,防止过载
- 监控(Metrics):收集代理运行指标,用于监控和分析
- 重试(Retry):实现请求重试,提高请求成功率
配置选项
GoProxy提供了丰富的配置选项,可以通过Options
结构体进行配置:
type Options struct {
// 配置
Config *config.Config
// 委托
Delegate Delegate
// 证书缓存
CertCache CertificateCache
// HTTP缓存
HTTPCache cache.Cache
// 负载均衡器
LoadBalancer loadbalance.LoadBalancer
// 健康检查器
HealthChecker *healthcheck.HealthChecker
// 监控指标
Metrics metrics.Metrics
// 客户端跟踪
ClientTrace *httptrace.ClientTrace
}
函数式选项模式
GoProxy 现在支持函数式选项模式(Functional Options Pattern),通过一系列的 With
方法提供更加灵活和可读性更高的配置方式。此模式的优势在于:
- 参数配置更加直观和清晰
- 可以灵活选择需要的配置项,不必记忆参数顺序
- 代码可读性更高,便于维护
- 可以逐步添加新的配置选项而不破坏兼容性
可以使用 NewProxy
函数和函数式选项创建代理:
// 创建一个简单的代理
proxy := goproxy.NewProxy()
// 创建一个功能丰富的代理
proxy := goproxy.NewProxy(
goproxy.WithConfig(config.DefaultConfig()),
goproxy.WithHTTPCache(myCache),
goproxy.WithDecryptHTTPS(myCertCache),
goproxy.WithCACertAndKey("ca.crt", "ca.key"),
goproxy.WithMetrics(myMetrics),
goproxy.WithLoadBalancer(myLoadBalancer),
goproxy.WithRequestTimeout(10 * time.Second),
goproxy.WithEnableCORS(true)
)
可用的 With 方法
GoProxy 提供了以下 With 方法用于配置代理的各个方面:
基础配置选项
WithConfig(cfg *config.Config)
: 设置代理配置WithDisableKeepAlive(disableKeepAlive bool)
: 设置连接是否重用WithTransport(t *http.Transport)
: 使用自定义HTTP传输WithClientTrace(t *httptrace.ClientTrace)
: 设置HTTP客户端跟踪
功能模块选项
WithDelegate(delegate Delegate)
: 设置委托类WithHTTPCache(c cache.Cache)
: 设置HTTP缓存WithLoadBalancer(lb loadbalance.LoadBalancer)
: 设置负载均衡器WithHealthChecker(hc *healthcheck.HealthChecker)
: 设置健康检查器WithMetrics(m metrics.Metrics)
: 设置监控指标
功能开启选项
WithDecryptHTTPS(c CertificateCache)
: 启用中间人代理解密HTTPSWithEnableECDSA(enable bool)
: 启用ECDSA证书生成(默认使用RSA)WithEnableWebsocketIntercept()
: 启用WebSocket拦截WithReverseProxy(enable bool)
: 启用反向代理模式WithEnableRetry(maxRetries int, baseBackoff, maxBackoff time.Duration)
: 启用请求重试WithRateLimit(rps float64)
: 设置请求限流WithEnableCORS(enable bool)
: 启用CORS支持
证书相关选项
WithTLSCertAndKey(certPath, keyPath string)
: 设置TLS证书和密钥WithCACertAndKey(caCertPath, caKeyPath string)
: 设置CA证书和密钥
性能和超时相关选项
WithConnectionPoolSize(size int)
: 设置连接池大小WithIdleTimeout(timeout time.Duration)
: 设置空闲超时时间WithRequestTimeout(timeout time.Duration)
: 设置请求超时时间WithDNSCacheTTL(ttl time.Duration)
: 设置DNS缓存TTL
配置HTTPS解密
要启用HTTPS解密功能,需要在配置中设置以下选项:
config := &config.Config{
// 启用HTTPS解密
DecryptHTTPS: true,
// 方式一:使用CA证书和私钥动态生成证书
CACert: "path/to/ca.crt", // CA证书路径
CAKey: "path/to/ca.key", // CA私钥路径
// 选择证书生成算法(可选)
UseECDSA: true, // 使用ECDSA生成证书(默认为false,使用RSA)
// 方式二:使用固定的TLS证书和私钥
// TLSCert: "path/to/server.crt",
// TLSKey: "path/to/server.key",
}
或者使用函数式选项模式:
proxy := goproxy.NewProxy(
goproxy.WithDecryptHTTPS(&goproxy.MemCertCache{}),
goproxy.WithCACertAndKey("path/to/ca.crt", "path/to/ca.key"),
goproxy.WithEnableECDSA(true), // 使用ECDSA生成证书
// 或者使用静态TLS证书
// goproxy.WithTLSCertAndKey("path/to/server.crt", "path/to/server.key")
)
同时,建议配置证书缓存以提高性能:
certCache := &goproxy.MemCertCache{}
扩展点
GoProxy提供了多个扩展点,可以通过实现相应的接口进行扩展:
- Delegate:代理委托接口,用于自定义代理处理逻辑
- LoadBalancer:负载均衡接口,用于实现自定义负载均衡算法
- Cache:缓存接口,用于实现自定义缓存策略
- CertificateCache:证书缓存接口,用于自定义证书存储方式
- Metrics:监控接口,用于实现自定义监控指标收集
反向代理特性
GoProxy的反向代理模式提供以下特性:
- 路由规则:支持基于主机名、路径、正则表达式等的路由规则
- 请求修改:支持修改发往后端服务器的请求
- 响应修改:支持修改来自后端服务器的响应
- 保留客户端信息:支持添加X-Forwarded-For和X-Real-IP头
- CORS支持:支持自动添加CORS头
- WebSocket支持:支持WebSocket协议的透明代理
- 负载均衡:支持多种负载均衡算法
- 健康检查:支持对后端服务器进行健康检查
- 监控指标:支持收集反向代理的监控指标
监控指标
GoProxy提供了两种监控指标实现:PrometheusMetrics和SimpleMetrics。
PrometheusMetrics
PrometheusMetrics是一个完整的Prometheus指标实现,提供以下指标:
proxy_requests_total
: 请求总数(按方法、路径、状态码分类)proxy_request_latency_seconds
: 请求延迟(按方法、路径分类)proxy_request_size_bytes
: 请求大小(按方法、路径分类)proxy_response_size_bytes
: 响应大小(按方法、路径分类)proxy_errors_total
: 错误总数(按类型分类)proxy_active_connections
: 活跃连接数proxy_connection_pool_size
: 连接池大小proxy_cache_hit_rate
: 缓存命中率proxy_memory_usage_bytes
: 内存使用量
使用示例:
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy/pkg/metrics"
"github.com/darkit/goproxy"
)
func main() {
// 创建Prometheus指标收集器
metricsCollector := metrics.NewPrometheusMetrics()
// 创建代理
p := goproxy.NewProxy(
goproxy.WithMetrics(metricsCollector),
)
// 启动监控服务器
go func() {
log.Println("监控服务器启动在 :8081")
http.Handle("/metrics", metricsCollector.GetHandler())
if err := http.ListenAndServe(":8081", nil); err != nil {
log.Fatalf("监控服务器启动失败: %v", err)
}
}()
// 启动代理服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
SimpleMetrics
SimpleMetrics是一个简单的指标实现,提供基本的指标收集功能:
- 请求计数
- 错误计数
- 活跃连接数
- 累计响应时间
- 传输字节数
- 后端健康状态
- 后端响应时间
- 缓存命中计数
使用示例:
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy/pkg/metrics"
"github.com/darkit/goproxy"
)
func main() {
// 创建简单指标收集器
metricsCollector := metrics.NewSimpleMetrics()
// 创建代理
p := goproxy.NewProxy(
goproxy.WithMetrics(metricsCollector),
)
// 启动监控服务器
go func() {
log.Println("监控服务器启动在 :8081")
http.Handle("/metrics", metricsCollector.GetHandler())
if err := http.ListenAndServe(":8081", nil); err != nil {
log.Fatalf("监控服务器启动失败: %v", err)
}
}()
// 启动代理服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
指标中间件
GoProxy还提供了一个指标中间件,可以用于收集HTTP请求的指标:
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy/pkg/metrics"
)
func main() {
// 创建指标收集器
metricsCollector := metrics.NewPrometheusMetrics()
// 创建指标中间件
metricsMiddleware := metrics.NewMetricsMiddleware(metricsCollector)
// 创建HTTP处理器
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 处理请求
w.Write([]byte("Hello, World!"))
})
// 使用中间件包装处理器
wrappedHandler := metricsMiddleware.Middleware(handler)
// 启动HTTP服务器
log.Println("HTTP服务器启动在 :8080")
if err := http.ListenAndServe(":8080", wrappedHandler); err != nil {
log.Fatalf("HTTP服务器启动失败: %v", err)
}
}
使用压缩中间件
GoProxy提供了压缩中间件,支持请求和响应的gzip压缩:
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy/pkg/middleware"
"github.com/darkit/goproxy"
)
func main() {
// 创建压缩中间件
compressionMiddleware := middleware.NewCompressionMiddleware(6, 1024) // 压缩级别6,最小压缩大小1KB
// 创建代理
p := goproxy.NewProxy(
goproxy.WithMiddleware(compressionMiddleware),
)
// 启动HTTP服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
压缩中间件提供以下特性:
- 自动检测客户端是否支持gzip压缩
- 智能判断内容类型是否适合压缩
- 可配置压缩级别(0-9)
- 可配置最小压缩大小
- 支持多种内容类型
- 自动处理压缩请求体
- 自动添加压缩相关响应头
使用认证授权系统
GoProxy提供了完整的认证授权系统,支持JWT认证和基于角色的访问控制:
package main
import (
"log"
"net/http"
"github.com/darkit/goproxy/pkg/auth"
"github.com/darkit/goproxy"
)
func main() {
// 创建认证系统
auth := auth.NewAuth("your-secret-key")
// 添加用户和角色
auth.AddUser("admin", "password123", []string{"admin"})
auth.AddUser("user", "password456", []string{"user"})
// 创建代理
p := goproxy.NewProxy(
goproxy.WithAuth(auth),
)
// 启动HTTP服务器
log.Println("代理服务器启动在 :8080")
if err := http.ListenAndServe(":8080", p); err != nil {
log.Fatalf("代理服务器启动失败: %v", err)
}
}
认证授权系统提供以下特性:
- JWT令牌认证
- 基于角色的访问控制
- 用户管理
- 密码加密存储
- 权限管理
- 认证中间件
贡献
欢迎贡献代码、报告问题或提出建议。请遵循以下步骤:
- Fork 项目
- 创建特性分支 (
git checkout -b feature/amazing-feature
) - 提交更改 (
git commit -m 'Add some amazing feature'
) - 推送到分支 (
git push origin feature/amazing-feature
) - 创建 Pull Request
许可证
本项目采用 MIT 许可证,详情请参阅 LICENSE 文件。