267 lines
9.6 KiB
Markdown
267 lines
9.6 KiB
Markdown
# SysMonitord 开发规范与架构说明书
|
||
|
||
> **版本**: v1.0.1
|
||
> **日期**: 2026-03-22
|
||
|
||
---
|
||
|
||
## 1. 设计理念与架构总览
|
||
|
||
### 1.1 核心架构
|
||
SysMonitord 采用 **模块化** 设计,旨在降低耦合度,提升扩展性。系统主要包含以下核心域:
|
||
|
||
* **Config Domain (配置域)**: 负责配置的拉取、解析、合并与热更新。
|
||
* **Monitor Domain (监控域)**: 负责SSH审计、系统基础指标采集。
|
||
* **Security Domain (安全域)**: 负责文件完整性扫描与实时防护。
|
||
* **Network Domain (通讯域)**: 负责与中心服务器的 WebSocket 长连接通讯。
|
||
|
||
### 1.2 配置分层设计 (核心规范)
|
||
为了解决“配置混乱、前后端字段对不上”以及“官方策略与用户环境耦合”的问题,我们将配置严格划分为两个独立的 JSON 文件:
|
||
|
||
1. **官方策略**: `official.json`
|
||
* **权限**: 只读,由官方/安全团队维护,随版本更新发布。
|
||
* **内容**: **仅包含安全基线**(核心白名单Hash、强制忽略路径、扫描范围)。
|
||
* **注意**: **不再包含服务器地址**,因为官方策略包应适用于所有客户环境,不应硬编码服务端地址。
|
||
* **优先级**: 基线级(定义“什么是合法的”)。
|
||
|
||
2. **用户配置**: `user.json`
|
||
* **权限**: 读写,由用户/运维人员维护,可通过控制台动态下发。
|
||
* **内容**: **运行时环境配置**(服务器地址、审计开关、业务自定义白名单、性能阈值)。
|
||
* **优先级**: 补充级(在官方基线之上进行扩充或覆盖特定参数)。
|
||
|
||
---
|
||
|
||
## 2. 配置文件数据结构定义
|
||
|
||
> **重要**: 前后端交互必须严格遵循以下数据结构定义。字段命名统一使用 **snake_case** (下划线命名法)。
|
||
|
||
### 2.1 官方策略结构
|
||
**用途**: 定义不可篡改的安全基线,与具体部署环境无关。
|
||
|
||
```json
|
||
{
|
||
"version": "1.0.20260322",
|
||
"whitelist_files": {
|
||
"/bin/ls": ["sha256:abc123def456..."],
|
||
"/bin/cat": ["sha256:789xyz..."],
|
||
"/usr/bin/top": ["sha256:example123..."]
|
||
},
|
||
"whitelist_processes": [
|
||
"systemd",
|
||
"sshd",
|
||
"dockerd",
|
||
"nginx",
|
||
"python3"
|
||
],
|
||
"ignored_paths": [
|
||
"/tmp/",
|
||
"/var/log/",
|
||
"/proc/",
|
||
"/sys/",
|
||
"/dev/"
|
||
],
|
||
"scan_paths": [
|
||
"/bin",
|
||
"/sbin",
|
||
"/usr/bin",
|
||
"/usr/sbin",
|
||
"/etc/init.d"
|
||
]
|
||
}
|
||
```
|
||
|
||
**字段说明**:
|
||
* `whitelist_files`: `Map<string, []string>`。Key 为绝对路径,Value 为允许的 Hash 列表(支持多版本二进制)。
|
||
* `ignored_paths`: `[]string`。忽略扫描的目录前缀,用于减少无效报警和性能消耗。
|
||
|
||
### 2.2 用户配置结构
|
||
**用途**: 定义业务个性化需求及连接参数。
|
||
|
||
```json
|
||
{
|
||
"version": "user_v1",
|
||
"connection": {
|
||
"center_server_url": "ws://localhost:8090/api/v1/ws",
|
||
"audit_server_url": ""
|
||
},
|
||
"modules": {
|
||
"file_scanner": false,
|
||
"file_watcher": true,
|
||
"ssh_monitor": true,
|
||
"system_monitor": true
|
||
},
|
||
"supplement_files": {
|
||
"/home/admin/app/myapp": ["sha256:user_hash_123..."]
|
||
},
|
||
"supplement_processes": [
|
||
"java_app",
|
||
"python_worker",
|
||
"my_custom_service"
|
||
],
|
||
"ignored_paths": [
|
||
"/home/admin/logs/",
|
||
"/var/cache/myapp/"
|
||
],
|
||
"monitor_config": {
|
||
"ssh_monitor": {
|
||
"enabled": true,
|
||
"alert_on_root_login": true
|
||
},
|
||
"system_monitor": {
|
||
"collect_interval": "10s",
|
||
"collect_network": true,
|
||
"collect_process": true,
|
||
"process_limit": 10,
|
||
"scan_cpu_threshold": 80
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**字段变更说明**:
|
||
* `connection`: 服务器地址**仅**在此处配置,实现环境与策略分离。
|
||
* `supplement_processes`: 统一为数组格式 `[]string`,简化白名单管理逻辑。
|
||
* `scan_cpu_threshold`: 新增字段,允许用户自定义扫描时的CPU上限,默认推荐 80。
|
||
|
||
---
|
||
|
||
## 3. 通讯协议规范
|
||
|
||
Agent 与 Server 之间通过 WebSocket 进行全双工通讯。数据格式采用统一的 JSON 信封结构。
|
||
|
||
### 3.1 消息信封格式
|
||
|
||
所有下行和上行消息均遵循以下结构:
|
||
|
||
```go
|
||
// 位于 network/types.go
|
||
type Packet struct {
|
||
Type string `json:"type"` // 消息类型,大写下划线命名
|
||
Timestamp int64 `json:"timestamp"` // Unix 时间戳 (秒级)
|
||
Code int `json:"code"` // 状态码:200=成功, 400=参数错误, 500=服务器错误
|
||
Payload interface{} `json:"payload"` // 实际业务数据负载
|
||
}
|
||
```
|
||
|
||
### 3.2 上行消息类型定义
|
||
|
||
| Type 常量 | Payload 结构 | 说明 | 触发频率 |
|
||
| :--- | :--- | :--- | :--- |
|
||
| `STATUS_UPDATE` | `SystemMetrics` | 系统状态心跳 | 30s/次 |
|
||
| `SSH_ALERT` | `SSHLoginEvent` | SSH 登录审计日志 | 事件触发 |
|
||
| `REALTIME_FILE_ALERT` | `FileEventPayload` | 实时文件篡改/新增告警 | 事件触发 |
|
||
| `SCAN_RESULT` | `FileEventPayload` | 周期性全盘扫描结果 | 周期触发 |
|
||
|
||
**Payload 结构定义**:
|
||
|
||
```go
|
||
// 1. 系统状态心跳
|
||
type SystemMetrics struct {
|
||
CpuPercent float64 `json:"cpu_percent"` // 保留2位小数,例: 45.23
|
||
MemPercent float64 `json:"mem_percent"`
|
||
DiskUsage float64 `json:"disk_usage"` // 根分区使用率
|
||
LoadAvg1 float64 `json:"load_avg_1"` // 1分钟负载
|
||
AgentVersion string `json:"agent_version"` // Agent 当前版本
|
||
}
|
||
|
||
// 2. SSH 审计日志
|
||
type SSHLoginEvent struct {
|
||
User string `json:"user"` // 登录用户名
|
||
IP string `json:"ip"` // 来源IP
|
||
Port int `json:"port"` // 来源端口
|
||
Status string `json:"status"` // "SUCCESS" 或 "FAILED"
|
||
Time int64 `json:"event_time"` // 事件发生时间戳
|
||
Method string `json:"method"` // "password" 或 "key"
|
||
}
|
||
|
||
// 3. 文件告警负载
|
||
type FileEventPayload struct {
|
||
FilePath string `json:"filepath"`
|
||
Operation string `json:"operation"` // CREATE, MODIFY, DELETE
|
||
Status string `json:"status"` // DETECTED, HASH_MISMATCH
|
||
Timestamp int64 `json:"event_time"`
|
||
}
|
||
```
|
||
|
||
### 3.3 下行消息类型定义
|
||
|
||
| Type 常量 | Payload 结构 | 说明 |
|
||
| :--- | :--- | :--- |
|
||
| `CONFIG_UPDATE` | `{ "url": "..." }` | 通知 Agent 配置已更新,需重新拉取 |
|
||
| `TASK_SCAN` | `{ "path": "/" }` | 下发即时扫描任务 |
|
||
| `TASK_STOP` | `null` | 停止指定模块 |
|
||
| `COMMAND_RESPONSE` | `{ "result": "ok" }` | 服务端对上行消息的确认或错误返回 |
|
||
|
||
---
|
||
|
||
## 4. 核心模块实现规范
|
||
|
||
### 4.1 配置加载器
|
||
|
||
**逻辑规范**:
|
||
1. 启动时加载 `user.json` 获取服务器地址。
|
||
2. 连接服务器,通过 HTTP GET 请求拉取最新的 `official.json`。
|
||
3. 将两者合并为内存配置对象 `RuntimeConfig`。
|
||
|
||
**错误处理**:
|
||
* 若 `user.json` 缺失,尝试连接默认地址或提示启动失败(视部署策略而定)。
|
||
* 若拉取 `official.json` 失败,使用本地缓存(如果存在)继续运行,并输出 WARN 日志,不应 Crash 进程。
|
||
|
||
### 4.2 白名单管理器
|
||
|
||
**逻辑规范**:
|
||
1. **判定优先级**: 首先检查 `IgnoredPaths` -> 其次检查 `WhitelistFiles`。
|
||
2. **合并策略 (重要)**:
|
||
* 对于文件白名单:采用 **并集策略**。
|
||
* 若 `official.json` 允许 Hash A,`user.json` 允许 Hash B,则该文件 Hash 为 A 或 B 均判定为合法。
|
||
* 实现示例:
|
||
```go
|
||
// 伪代码
|
||
allowedHashes := append(officialConfig.WhitelistFiles[path], userConfig.SupplementFiles[path]...)
|
||
if contains(allowedHashes, currentHash) { status = SAFE }
|
||
```
|
||
|
||
3. **判定结果状态**:
|
||
* `IGNORED`: 在忽略列表中
|
||
* `SAFE`: 在白名单中且 Hash 匹配
|
||
* `NON_WHITELISTED`: 未在白名单中
|
||
* `HASH_MISMATCH`: 在白名单中但 Hash 不匹配
|
||
|
||
4. **并发安全**: 必须使用 `sync.RWMutex` 保护配置更新和查询操作。
|
||
|
||
### 4.3 监控模块
|
||
|
||
**数据规范**:
|
||
* **时间单位**: 配置文件中使用字符串 (`"30s"`),代码中解析为 `time.Duration`。传输协议中使用 **秒级 Unix 时间戳** (int64)。
|
||
* **数据精度**: 百分比和容量数据,传输时统一保留小数点后 **2位**。
|
||
* **性能限制**: `process_limit` 必须生效,防止采集 Top N 进程时导致 Payload 超过 WebSocket 帧大小限制。
|
||
|
||
---
|
||
|
||
## 5. 错误处理与日志规范
|
||
|
||
### 5.1 日志分级
|
||
* `DEBUG`: 详细的扫描路径、心跳发送详情(生产环境默认关闭)。
|
||
* `INFO`: 模块启动/停止、配置更新成功、检测到的安全事件。
|
||
* `WARN`: CPU 负载避让生效(暂停扫描)、网络断线重连中、使用本地缓存配置。
|
||
* `ERROR`: 配置下载失败、文件权限错误、JSON 解析失败。
|
||
|
||
### 5.2 异常处理策略
|
||
* **网络中断**: 必须实现 **指数退避** 重连机制。
|
||
* 初始延迟: 1s
|
||
* 最大延迟: 60s
|
||
* 因子: 2.0
|
||
* **JSON 解析失败**: 丢弃收到的畸形消息,记录 ERROR 日志,不断开连接。
|
||
|
||
---
|
||
|
||
## 6. 前后端对接检查清单
|
||
|
||
在开发前后端接口时,请对照以下清单进行自测:
|
||
|
||
- [ ] **字段命名**: 后端 JSON Tag 是否使用了 `snake_case` (如 `cpu_percent`),而非 `camelCase`?
|
||
- [ ] **空值处理**: 当列表为空时,后端返回的是 `[]` 空数组,还是 `null`? (建议统一返回 `[]`)。
|
||
- [ ] **时间格式**: 时间戳是返回 Unix 毫秒还是秒? (本文档强制要求 **秒**)。
|
||
- [ ] **枚举值**: 告警类型 (`REALTIME_FILE_ALERT` 等) 及状态码 (`Code: 200`) 是否有明确定义?
|
||
- [ ] **版本兼容**: 当新增字段时,旧版 Agent 是否会因为未知字段 Crash? (Go 解析 JSON 默认忽略未知字段,确认其他语言实现也遵循此原则)。
|
||
- [ ] **服务器地址**: 确认 `official.json` 中不包含任何硬编码的服务器 IP 或域名。 |