TestNet 客户端架构设计
一、架构概览
TestNet 客户端是基于 Go 构建的轻量级分布式扫描节点,负责执行服务端下发的扫描任务并上报结果。
1.1 设计目标
- 轻量级: 单一二进制文件,无外部依赖,快速部署
- 跨平台: 支持 Linux、macOS、Windows
- 安全隔离: 多层安全防护,防止滥用和攻击
- 高可用: 自动重连、重试机制、状态恢复
- 可扩展: 支持多种执行器类型,易于扩展
1.2 核心架构
┌─────────────────────────────────────────────────────────────┐
│ TestNet Client │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ node/ │ │ task/ │ │ configfile/│ │
│ │ 生命周期 │ │ 任务执行 │ │ 配置同步 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ┌──────▼────────────────▼────────────────▼──────┐ │
│ │ security/ (安全策略) │ │
│ └───────────────────────────────────────────────┘ │
│ │ │
│ ┌──────▼──────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ dsl/ │ │ config/ │ │ logger/ │ │
│ │ DSL模型 │ │ 配置管理 │ │ 日志 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ External Executors │
├─────────────────────────────┤
│ Docker │ Shell │ HTTP │ DNS │ TCP │
└─────────────────────────────┘二、核心模块详解
2.1 节点生命周期 (node/)
节点生命周期模块负责客户端的注册、心跳、离线管理。
目录结构
internal/node/
├── node.go # 核心逻辑
├── node_test.go # 单元测试
└── doc.go # 包文档核心流程
graph TD
A[启动] --> B[加载配置]
B --> C[向服务端注册]
C --> D{注册成功?}
D -->|是| E[启动心跳循环]
D -->|否| F[重试注册]
F --> C
E --> G[监听任务]
G --> H{收到停止信号?}
H -->|否| I[发送心跳]
I --> J{心跳成功?}
J -->|是| G
J -->|否| K[重新注册]
K --> C
H -->|是| L[通知离线]
L --> M[清理资源]
M --> N[退出]重连机制
- 注册失败:指数退避重试(1s, 2s, 4s, ...最大 30s)
- 心跳失败:连续 3 次失败后重新注册
- 网络中断:自动检测并重连
具体实现请参阅源码:internal/node/node.go
2.2 任务执行引擎 (task/)
任务执行引擎是客户端的核心模块,负责任务轮询、执行、结果上报。
目录结构
internal/task/
├── task.go # TaskManager 核心
├── executor.go # 执行器路由
├── docker_executor.go # Docker 执行器
├── http_executor.go # HTTP 执行器
├── dns_executor.go # DNS 执行器
├── tcp_executor.go # TCP 执行器
├── execution_spec_adapter.go # ExecutionSpec 适配
├── callback.go # 任务回调
└── *_test.go # 测试文件核心流程
graph TD
A[任务轮询] --> B{获取到任务?}
B -->|否| A
B -->|是| C[解析 ExecutionSpec]
C --> D[安全检查]
D --> E{检查通过?}
E -->|否| F[上报失败]
E -->|是| G[选择执行器]
G --> H[执行任务]
H --> I[实时上报日志]
I --> J{执行完成?}
J -->|否| I
J -->|是| K[收集结果]
K --> L[上报结果]
L --> A执行器路由
任务执行引擎根据 ExecutionSpec 的 execType 路由到对应的执行器:DOCKER、HTTP、DNS、TCP、SHELL。
各执行器实现请参阅源码:internal/task/executor.go、internal/task/docker_executor.go、internal/task/http_executor.go、internal/task/dns_executor.go、internal/task/tcp_executor.go。
2.3 执行器详解
| 执行器 | 用途 | 源码文件 |
|---|---|---|
| Docker | 容器化工具执行,支持 Podman 兼容 | docker_executor.go |
| HTTP | HTTP 请求探针,内置 SSRF 防护 | http_executor.go |
| DNS | DNS 查询解析 | dns_executor.go |
| TCP | TCP 端口探测与 Banner 抓取 | tcp_executor.go |
| SHELL | 本地 Shell 命令执行 | executor.go |
2.4 安全策略 (security/)
客户端内置五层安全防护:二进制白名单、环境变量屏蔽、卷挂载限制、SSRF 内网阻断、容器特权阻断。
详细实现请参阅源码:internal/security/ 目录。
2.5 配置文件同步 (configfile/)
扫描节点支持从服务端拉取配置文件并自动同步,使用 symlink 管理版本。同步流程采用 SHA-256 校验确保完整性。
详细实现请参阅源码:internal/configfile/manager.go。
三、数据模型
3.1 ExecutionSpec
ExecutionSpec 是服务端下发给客户端的执行规范,定义了任务的执行类型、超时、输入输出资产类型及各类执行器配置。
完整结构定义请参阅源码:internal/dsl/execution_spec.go。
3.2 任务状态
任务状态流转:PENDING → ASSIGNED → RUNNING → COMPLETED / FAILED。
四、性能优化
- 并发控制:使用信号量控制最大并发任务数
- 长轮询:HTTP 长轮询拉取任务,减少网络开销
- 日志批量上报:任务日志批量上报,降低请求频率
详细实现请参阅源码:internal/task/task.go、internal/task/reporter.go。
五、监控与调试
- 健康检查:客户端提供健康检查端点,返回节点状态、活跃任务数、系统资源使用情况
- 日志级别:支持动态调整日志级别(debug/info/warn/error)
- 性能指标:任务执行成功率、平均执行时间、并发任务数、内存/CPU 使用率
六、故障排查
常见问题
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| 无法连接服务端 | 网络问题、密钥错误 | 检查网络、验证密钥 |
| Docker 任务失败 | 镜像不存在、权限问题 | 拉取镜像、检查权限 |
| 任务超时 | 网络慢、目标不可达 | 增加超时时间 |
| SSRF 拦截 | 访问内网地址 | 检查目标地址合法性 |
调试命令
./testnet-client -verbose
./testnet-client test --spec spec.yaml --mock mock.yaml
./testnet-client validate --spec spec.yaml
./testnet-license show-machine-id