# goproxy **Repository Path**: vipkwds/goproxy ## Basic Information - **Project Name**: goproxy - **Description**: 代理节点 + 中控平面的完整解决方案,支持通过 SSE 实时推送配置 - **Primary Language**: Go - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-30 - **Last Updated**: 2026-06-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # goproxy 代理节点 + 中控平面的完整解决方案,支持通过 SSE 实时推送配置。 [![Go Version](https://img.shields.io/badge/Go-1.18%2B-blue)](https://golang.org/) [![License](https://img.shields.io/badge/License-MIT-green)](LICENSE) [![Beta](https://img.shields.io/badge/beta版-blue)](https://gitee.com/vipkwds/goproxy/tree/v1.0.0) ## 架构 ``` ┌─────────────┐ ┌──────────────────┐ ┌─────────────┐ │ Client │───────▶│ proxyNode │◀──────│ admin │ │ (浏览器) │ │ (代理节点) │ │ (中控) │ └─────────────┘ └────────┬─────────┘ └──────┬──────┘ │ │ │ HTTP/Redis │ SSE │ │ ▼ ▼ ┌─────────────┐ ┌──────────────────┐ │ Backend │ │ Redis (全局配置) │ │ (目标服务) │ └──────────────────┘ └─────────────┘ ``` ## 组件 ### proxyNode (`integration/node.go`) 代理节点,处理实际的 HTTP 流量。 **功能**: - 基于域名的路由匹配(精确匹配 → 泛匹配 → wildcard `*`) - 三种匿名模式:`anonymous`、`anonymous_with_id`、`transparent` - Header 过滤和透传(**业务强依赖字段强制保留**) - 通过 SSE 实时接收中控推送的配置(替代轮询) - 注册/心跳机制,断线后自动重连 - **连接时自动推送配置** - 新 proxyNode 连接后自动收到当前全局配置 - **业务 API 路由** - 内置 bizPrefix 机制,支持按需注册业务接口 **启动示例**: ```go node, _ := integration.NewNode(integration.NodeOptions{ NodeID: "proxy-node-001", ListenAddr: ":8090", Registry: integration.RegistryOptions{ Enabled: true, ControlServer: "http://127.0.0.1:18888", Secret: "your-secret", PublicAddr: "proxy.example.com:80", }, BizPrefixSecret: "your-salt", // 生成 bizPrefix 的盐值 BizRouters: map[string]http.HandlerFunc{ "[get]/users": handleGetUsers, // 支持 method 限制 "[post]/users": handlePostUsers, "/health": handleHealth, // 任意 method }, BizFallbackHandle: func(scene string, w http.ResponseWriter, r *http.Request) { switch scene { case "method_not_allowed": http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) case "route_not_found": http.NotFound(w, r) } }, }) node.Start(context.Background()) // 运行时动态注册(可选) node.BizRouterRegister("/orders", handleOrders) bizPrefix := node.GetBizPrefix() // 获取生成的 bizPrefix ``` ### admin (`examples/admin/`) 中控后台 + 代理转发入口,基于 Gin 框架。 **路由**: - `POST /api/v1/proxy/register` - 节点注册 - `POST /api/v1/proxy/heartbeat` - 节点心跳 - `GET /api/v1/proxy/poll` - 配置轮询(已废弃,优先使用 SSE) - `GET /api/v1/proxy/sse/:nodeID` - SSE 配置推送 - `POST /api/v1/proxy/config` - 推送配置变更 - `GET /admin/nodes` - 节点列表页面 - `GET /admin/config` - 配置管理页面 - `GET /` - 管理后台首页 ### internal/proxy (`internal/proxy/`) 核心代理引擎: - `router.go` - 域名路由匹配,支持 wildcard `*` - `server.go` - HTTP Server 和连接管理 - `header.go` - Header 过滤和注入 - `anonymous.go` - 匿名模式实现 - `connect.go` - CONNECT 隧道处理 ### internal/registry (`internal/registry/`) 节点注册客户端: - 支持注册、心跳 - 心跳失败后自动进入退避重连(5s → 60s 指数退避) - admin 重启后自动重新注册并恢复心跳 ## 配置推送流程(SSE 实时推送) ``` 1. proxyNode 启动 → 注册到 admin → 启动 SSE Client 2. admin 配置变更 → BroadcastConfig() → 通过 SSE 推送到所有节点 3. proxyNode 收到推送 → applyConfig() → 更新路由规则 4. proxyNode 连接 SSE 时 → admin 自动推送当前全局配置(无需手动触发) ``` SSE 断线后会在 node.go 外层自动重连,使用 5s 基础退避(最大 60s)。 ## 业务 API 路由(bizPrefix) proxyNode 内置业务 API 路由机制,允许在代理节点上注册业务接口。 ### 核心概念 - **bizPrefix** - 基于 `NodeID + BizPrefixSecret` 通过 SHA256 生成,唯一且不可预测 - **格式**:`/biz_{sha256(NodeID+BizPrefixSecret)[:16]}`,如 `/biz_a1b2c3d4e5f6...` - **安全保证**:外部无法预知 bizPrefix,需掌握 BizPrefixSecret 才能配置正确路由 ### Pattern 格式 ``` /users → 任意 method [get]/users → 仅 GET [get;post]/users → GET 或 POST(分隔符支持:空格/逗号/竖线/分号) [*,post]/users → 任意或 POST(即 all) ``` ### Fallback 处理 | 场景 | 默认响应 | 可自定义 | |------|---------|---------| | method_not_allowed | 405 Method Not Allowed | BizFallbackHandle | | route_not_found | 404 Not Found | BizFallbackHandle | ## Header 过滤策略 proxyNode 支持基于白名单的 Header 过滤,但**业务强依赖字段始终强制保留**。 ### 白名单模式 - `HeaderWhitelist == nil/空` → 不过滤,透传所有 Header - `HeaderWhitelist` 非空 → 仅保留白名单内字段 ### 强制保留字段 无论白名单如何配置,以下字段始终透传: ``` Accept, Accept-Encoding, Accept-Language, Authorization, Connection, Content-Type, Cookie, Host, Referer, Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site, User-Agent ``` **说明**:Cookie、Authorization 等字段是 HTTP 业务基础,白名单配置时无需担心被误删。 ### 使用示例 ```go // 1. admin 侧:获取 bizPrefix 用于配置路由 bizPrefix := node.GetBizPrefix() // 配置路由时使用此前缀 // 2. proxyNode 侧:注册业务路由 node.BizRouterRegister("[get]/users", func(w http.ResponseWriter, r *http.Request) { bizPrefix := proxy.GetBizPrefixFromContext(r.Context()) // 从 context 获取 w.Write([]byte("users list")) }) // 3. 请求示例 // GET /biz_a1b2c3d4e5f6.../users → handleGetUsers // POST /biz_a1b2c3d4e5f6.../users → 405 ``` ## 依赖 - `gitee.com/vipkwds/sse` - SSE 实现 - `github.com/redis/go-redis/v9` - Redis 客户端 - `github.com/gin-gonic/gin` - admin 框架 ## 运行示例 ```bash # 启动 admin(中控) cd examples/admin && go run . # 启动 proxyNode cd examples/proxynode && go run . # 访问管理后台 open http://127.0.0.1:18888/admin/nodes ```