# HTTPDNS后端开发计划(V1.0) ## 0. 文档信息 - 目标文件:`EdgeHttpDNS/HTTPDNS后端开发计划.md` - 交付范围:`EdgeAdmin + EdgeAPI + EdgeNode + SDK对接接口` - 交付策略:一次性全量交付(非分阶段) - 核心约束: - 仅新协议 - 无 `/bootstrap` - `/resolve` 使用 GET 参数 - 线路匹配仅基于客户端 IP 归属 - 独立 `edgeHTTPDNS*` 数据表 - 新增独立节点角色 `NodeRoleHTTPDNS` - 访问日志 MySQL + ClickHouse 双写(查询优先 ClickHouse) ## 1. 目标与成功标准 1. 将 HTTPDNS 从当前 Admin 侧 mock/store 方案落地为真实后端能力。 2. 打通“配置 -> 下发 -> 解析 -> 日志 -> 查询”闭环。 3. 与当前前端设计严格对齐: - 菜单:集群管理、应用管理、访问日志、运行日志、解析测试 - SNI 固定为“隐匿 SNI” - 自定义解析不含 SDNS 参数 4. 成功标准: - 管理页面均通过 RPC 读取真实数据,无本地 mock 依赖 - `/resolve` 可按应用/域名/线路返回解析结果 - 访问日志与运行日志可查询、可筛选、可分页 - 节点配置与状态可下发和回传 - 主备集群服务域名可在应用设置中配置并生效 - EdgeNode 支持 SNI 与 Host 解耦路由,并可执行 WAF 动态验签与隐匿 SNI 转发 ## 2. 架构与边界 ### 2.1 服务边界 1. EdgeAdmin:仅负责页面动作与 RPC 编排,不存业务状态。 2. EdgeAPI:负责数据存储、策略匹配、接口服务、日志汇聚。 3. EdgeNode(HTTPDNS节点):负责执行解析、接收策略任务、上报运行日志/访问日志,并执行 SNI/Host 解耦路由、WAF 动态验签、隐匿 SNI 转发。 4. SDK:手动配置应用关联主备服务域名,调用 `/resolve` 获取结果。 ### 2.2 不做项 1. 不做 `/bootstrap` 接口。 2. 不做 ECH / SNI 分级策略。 3. 不做 SDNS 参数匹配。 4. 不做第三方 DNS 依赖复用。 ## 3. 公开接口与契约(需新增/调整) ### 3.1 HTTP 解析接口 1. `GET /resolve` 2. 请求参数: - `appId`(必填) - `dn`(必填) - `qtype`(可选,A/AAAA,默认 A) - `cip`(可选) - `sid`、`sdk_version`、`os`(可选,用于日志) - `nonce`、`exp`、`sign`(可选,验签开启时必需) 3. 响应结构(统一): - `code`、`message`、`requestId` - `data`: - `domain` - `qtype` - `ttl` - `records[]`(`type`,`ip`,`weight?`,`line?`,`region?`) - `client`(`ip`,`region`,`carrier`,`country`) - `summary`(命中规则摘要) 4. 错误码最低集合: - app 无效/禁用 - 域名未绑定 - 验签失败 - 无可用解析记录 - 内部解析失败/超时 ### 3.2 管理 RPC(EdgeAdmin -> EdgeAPI) 1. 新增服务: - `HTTPDNSClusterService` - `HTTPDNSNodeService` - `HTTPDNSAppService` - `HTTPDNSDomainService` - `HTTPDNSRuleService` - `HTTPDNSAccessLogService` - `HTTPDNSRuntimeLogService` - `HTTPDNSSandboxService` 2. 最小方法集: - 集群:增删改查、设置默认集群、TLS证书绑定、节点列表/状态 - 应用:增删改查、主备集群设置、启停、验签开关、密钥重置 - 域名:绑定/解绑/列表 - 自定义解析:规则增删改查、启停、排序 - 日志:访问日志分页查询、运行日志分页查询 - 测试:在线解析测试调用(入参包含 appId、clusterId、domain、qtype、clientIp) ### 3.3 节点日志上报 RPC(EdgeNode -> EdgeAPI) 1. `CreateHTTPDNSAccessLogs`(批量) 2. `CreateHTTPDNSRuntimeLogs`(批量) 3. 幂等键:`requestId + nodeId` 4. 支持高吞吐批量提交和失败重试 ### 3.4 节点路由与 WAF 策略下发契约(EdgeAPI -> EdgeNode) 1. 下发内容最小集合: - `appId/domain/serviceDomain` - `sniMode`(固定为隐匿 SNI) - `hostRouteMode`(SNI 与 Host 解耦) - `wafVerifyEnabled` - `wafVerifyPolicy`(验签字段、时效窗口、失败动作) 2. 节点执行口径: - 入站按 `serviceDomain` 接入,按 Host/业务域名做路由匹配 - TLS 握手与业务 Host 解耦,避免真实业务域名暴露在 SNI - 命中需要验签的应用时,先执行 WAF 动态验签,再继续解析链路 3. 失败处置: - 验签失败按策略拒绝并记录运行日志、访问日志错误码 - 路由未命中返回统一错误码并上报审计日志 ## 4. 数据模型设计(独立 HTTPDNS 表) 1. `edgeHTTPDNSClusters` - `id,name,isOn,isDefault,serviceDomain,defaultTTL,fallbackTimeoutMs,installDir,tlsPolicyJSON,createdAt,updatedAt` 2. `edgeHTTPDNSNodes` - `id,clusterId,name,isOn,isUp,isInstalled,isActive,statusJSON,installStatusJSON,installDir,uniqueId,secret,createdAt,updatedAt` 3. `edgeHTTPDNSApps` - `id,name,appId,isOn,primaryClusterId,backupClusterId,sniMode(fixed_hide),createdAt,updatedAt` 4. `edgeHTTPDNSAppSecrets` - `id,appId,signEnabled,signSecretEnc,signUpdatedAt,updatedAt` 5. `edgeHTTPDNSDomains` - `id,appId,domain,isOn,createdAt,updatedAt` 6. `edgeHTTPDNSCustomRules` - `id,appId,domainId,ruleName,lineScope,lineCarrier,lineRegion,lineProvince,lineContinent,lineCountry,ttl,isOn,priority,updatedAt` 7. `edgeHTTPDNSCustomRuleRecords` - `id,ruleId,recordType,recordValue,weight,sort` 8. `edgeHTTPDNSAccessLogs` - `id,requestId,clusterId,nodeId,appId,domain,qtype,clientIP,clientRegion,carrier,sdkVersion,os,resultIPs,status,errorCode,costMs,createdAt,day` 9. `edgeHTTPDNSRuntimeLogs` - `id,clusterId,nodeId,level,type,tag,description,count,createdAt,day` ### 4.1 索引与唯一约束 1. 唯一:`edgeHTTPDNSApps.appId` 2. 唯一:`edgeHTTPDNSDomains(appId,domain)` 3. 唯一:`edgeHTTPDNSAccessLogs(requestId,nodeId)` 4. 索引: - 访问日志:`day,clusterId,nodeId,domain,status,createdAt` - 规则匹配:`domainId,isOn,priority,lineScope,...` - 应用查询:`name,appId,isOn` ## 5. 解析引擎实现(EdgeAPI) 1. 输入校验:`appId/dn/qtype` 2. 应用与域名校验: - app 存在且启用 - 域名已绑定到 app 3. 线路归属: - `cip` 优先,其次 remote IP - 映射字段:运营商/大区/省份/洲/国家 4. 规则匹配: - 精确匹配 > 半精确 > 默认 - 同级按 `priority` 从小到大 5. 记录返回: - 权重关闭:返回全部记录 - 权重开启:按权重算法返回单条或子集(固定口径) 6. TTL 取值: - 命中规则取规则 TTL - 未命中规则取集群默认 TTL 7. 验签: - `signEnabled=true` 时必须通过签名校验 - `signEnabled=false` 时跳过签名校验 8. 访问日志: - 解析结束异步写日志 - 双写 MySQL/ClickHouse ## 6. 节点与任务链路 1. 在 `EdgeCommon/pkg/nodeconfigs` 增加 `NodeRoleHTTPDNS`。 2. 在任务系统增加 HTTPDNS 任务类型: - 配置变更 - 应用变更 - 域名变更 - 规则变更 - 证书变更 - 路由与 WAF 策略变更 3. EdgeNode 增加 HTTPDNS 子服务: - 接收配置快照 - 执行解析 - 上报运行/访问日志 - 执行 SNI/Host 解耦路由 - 执行 WAF 动态验签 - 执行隐匿 SNI 转发 4. 复用现有安装升级框架,但节点角色、任务通道、日志 tag 独立。 ## 7. EdgeAdmin 后端改造 1. 将 `internal/web/actions/default/httpdns/*` 的 store/mock 读写改为 RPC。 2. 删除/停用旧能力路由: - `/httpdns/policies` - `/httpdns/guide` - `/httpdns/ech` 3. 保留必要跳转,避免旧链接 404。 4. `sandbox/test` 改为调用真实解析服务(可保留测试开关)。 5. 解析测试页面交互固定为: - 配置区标题“解析测试” - 所属集群使用下拉框 - 解析域名使用下拉框并按目标应用联动 ## 8. 安全与审计 1. Secret 持久化使用加密存储(至少密文列),返回时脱敏。 2. 操作审计记录: - 验签开关启停 - Sign Secret 重置 - 应用主备集群修改 3. 验签失败日志保留 `requestId,errorCode,sourceIP`。 4. 防滥用: - `/resolve` 增加基础限流与异常请求过滤(按 appId + IP 维度)。 5. 节点侧安全执行: - WAF 动态验签失败必须留存审计日志(含 requestId/appId/sourceIP) - SNI/Host 解耦路由命中结果需可追踪(用于问题回溯) ## 9. 测试与验收 ### 9.1 单元测试 1. 规则匹配优先级与线路匹配 2. 验签成功/失败路径 3. 权重返回算法 4. DAO CRUD 与唯一约束 ### 9.2 集成测试 1. EdgeAdmin -> RPC -> DB 全链路 2. `/resolve` 各错误码分支 3. 节点日志上报双写(MySQL+CH) 4. CH 不可用时 MySQL 回退查询 5. EdgeAPI 策略下发 -> EdgeNode 路由/WAF 执行 -> 日志落库全链路 ### 9.3 回归测试 1. 智能DNS功能不受影响 2. 菜单与权限不串模块 3. 旧入口跳转正确,无新增 404 ### 9.4 验收用例 1. 应用配置主备服务域名后,SDK可解析成功 2. 主集群故障时可切备集群 3. 自定义解析按线路返回预期 IP 4. 访问日志筛选与概要展示正确 5. 运行日志级别/字段与智能DNS一致 6. EdgeNode 可在 SNI 与 Host 解耦场景下正确路由到目标应用 7. 开启 WAF 动态验签后,合法请求通过、非法签名请求被拒绝且有审计日志 ## 10. 发布与回滚 1. 发布顺序: - DB migration - EdgeAPI(DAO+RPC+resolve) - EdgeNode(角色+上报) - EdgeAdmin(RPC切换) 2. 开关控制: - `httpdns.resolve.enabled` - `httpdns.log.clickhouse.enabled` 3. 回滚策略: - 关闭 `resolve` 新实现开关 - 访问日志读取切回 MySQL - Admin 保留只读能力 ## 11. 默认值与固定决策 1. 无 `/bootstrap`,SDK手动配置主备服务域名。 2. `SNI` 固定“隐匿 SNI”。 3. 自定义解析无 SDNS 参数。 4. 线路仅客户端 IP 归属。 5. 日志双写,查询优先 ClickHouse。 6. 节点角色独立:`NodeRoleHTTPDNS`。