This repository has been archived on 2026-03-28. You can view files and clone it, but cannot push or open issues or pull requests.
old-sysmonitord/docs/ARCHITECTURE.md
2026-03-26 21:17:43 +08:00

9.7 KiB
Raw Permalink Blame History

SysMonitord 开发规范与架构说明书

版本: v1.0.2 日期: 2026-03-26


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 官方策略结构

用途: 定义不可篡改的安全基线,与具体部署环境无关。

{
  "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 用户配置结构

用途: 定义业务个性化需求及连接参数。

{
  "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/"
  ],
  "scan_paths": [
    "/home/admin/app/",
    "/usr/local/bin/"
  ],
  "monitor_config": {
    "ssh_monitor": {
      "enabled": true,
      "alert_on_root_login": true
    },
    "system_monitor": {
      "enabled": true,
      "interval": 30,
      "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 消息信封格式

所有下行和上行消息均遵循以下结构:

// 位于 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 结构定义:

// 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 Auser.json 允许 Hash B则该文件 Hash 为 A 或 B 均判定为合法。
    • 实现示例:
    // 伪代码
    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 或域名。