Files
MeshSate/docs/策略配置说明.md
zhaolei 16f134e328 feat: MeshSafe 文件摆渡安全卫士 v1.0 初始提交
核心功能:
- 6 层检测管线: L0 结构分析 → L1 ClamAV → L2 文档深度检测 → L3 关键词匹配 → L4 YARA → L5 PE/二进制
- FastAPI + PostgreSQL + Redis + Docker Compose 架构
- 客户端 HMAC-SHA256 签名鉴权 + 限流 + 幂等性
- 控制台 UI (登录/Dashboard/诊断中心/策略管理/任务列表/测试中心/产品介绍页)
- 三层诊断定时器 (error_scan 30s / db_aggregate 30s / container_check 5min)

并发与稳定性修复:
- 诊断定时器 Redis 时间槽位锁 (多 worker 同一槽位只有一个执行)
- JSONL 存储 fcntl 跨进程排他锁 + 容错解码 + 原子重写
- 移除 SQLite fallback, 统一 PostgreSQL
- API_CLIENTS 脱敏为环境变量, .env 已 .gitignore
2026-10-28 19:07:11 +08:00

460 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MeshSafe 策略配置说明
| 项目 | 内容 |
|---|---|
| 适用对象 | 安全管理员、系统管理员 |
| 配置文件 | `config/policy.yaml` |
| 生效方式 | 修改后调用 `POST /api/v1/policies/reload` 或重启服务 |
| 文档版本 | v1.0 |
---
## 目录
1. [配置总览](#1-配置总览)
2. [字段详解](#2-字段详解)
3. [裁决流程](#3-裁决流程)
4. [调整场景手册](#4-调整场景手册)
5. [校验与错误处理](#5-校验与错误处理)
6. [变更管理](#6-变更管理)
---
## 1. 配置总览
策略文件采用 YAML 格式,路径由环境变量 `MESHSAFE_POLICY_FILE` 指定(默认 `/app/config/policy.yaml`)。
**核心原则:策略与代码分离。** 调整判定规则、阈值、白名单只需修改本文件,不需要重新构建或发布镜像。
```yaml
version: "2026.10.1"
description: "MeshSafe 默认全局策略(法院文书摆渡场景)"
global:
block_score: 70
review_score: [30, 70]
engine_failure_mode: fail_closed
max_file_size: 52428800
sync_max_size: 52428800
allow_encrypted_archive: false
allow_encrypted_document: false
allowed_extensions: [ ... ]
sandbox_required_extensions: [ ... ]
rule_overrides: { ... }
notification: { ... }
audit: { ... }
```
### 顶层结构
| 键 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `version` | string | 是 | 策略版本号,建议用日期格式。写入每条扫描结果 |
| `description` | string | 否 | 策略说明 |
| `global` | map | 是 | 全局阈值与行为开关 |
| `allowed_extensions` | list | 是 | 允许传输的扩展名白名单 |
| `sandbox_required_extensions` | list | 否 | 强制走沙箱深检的类型 |
| `rule_overrides` | map | 否 | 特定规则的强制处置 |
| `notification` | map | 否 | 判定理由的输出控制 |
| `audit` | map | 否 | 审计记录内容控制 |
---
## 2. 字段详解
### 2.1 global
#### 2.1.1 `block_score`
| 项 | 说明 |
|---|---|
| 类型 | 整数,0~100 |
| 默认 | `70` |
| 含义 | 风险评分 **≥ 此值** 时判定为 `malicious`,处置动作为 `reject` |
调整方向:调低 → 更严格(更多文件被拒),调高 → 更宽松(需积累更多信号才拒绝)。
> 注意:单条 `critical` 级信号通常权重已达 50~90,因此 `block_score` 低于 50 时,大量正常文档会因多条低级信号叠加被拒。
#### 2.1.2 `review_score`
| 项 | 说明 |
|---|---|
| 类型 | 数组 `[下界, 上界]` |
| 默认 | `[30, 70]` |
| 含义 | 评分落在该区间时判定为 `suspicious`,处置动作为 `manual_review`(转人工复核) |
**这是误报缓冲的关键参数。** 调整方向:调低下界 → 更多文件进入人工复核(更安全但人工压力大);调高下界 → 更少人工复核(但风险文件可能被直接放行)。
#### 2.1.3 `engine_failure_mode`
| 项 | 说明 |
|---|---|
| 类型 | 字符串 `fail_closed` / `fail_open` |
| 默认 | `fail_closed` |
| 含义 | 检测引擎不可用时的整体行为 |
| 取值 | 行为 | 适用 |
|---|---|---|
| `fail_closed` | 直接拒绝,并说明引擎不可用 | **生产环境必须使用此项** |
| `fail_open` | 放行但标记 | 仅限测试环境 |
> 等保三级要求"安全优先",生产环境使用 `fail_open` 会在测评时被判定为不符合项。
#### 2.1.4 `max_file_size`
| 项 | 说明 |
|---|---|
| 类型 | 整数(字节) |
| 默认 | `52428800`(50 MB) |
| 含义 | 单文件大小上限。超限直接拒绝 |
#### 2.1.5 `sync_max_size`
| 项 | 说明 |
|---|---|
| 类型 | 整数(字节) |
| 默认 | `52428800`(50 MB) |
| 含义 | 同步模式处理的文件大小上限。超限转异步 |
必须 ≤ `max_file_size`。若大于,则会出现"文件本身允许但无法同步处理"的中间态。
#### 2.1.6 `allow_encrypted_archive` / `allow_encrypted_document`
| 项 | 说明 |
|---|---|
| 类型 | 布尔 |
| 默认 | `false` |
| 含义 | 是否允许加密的压缩包 / 加密的文档 |
加密文件无法被静态分析,**在无法确认内容安全的前提下不应放行**。确需放行时,应配合人工复核流程。
### 2.2 allowed_extensions
允许传输的扩展名白名单。
```yaml
allowed_extensions:
- .docx
- .pdf
- .xlsx
- .jpg
- .png
- .zip
```
规则:
- 必须以 `.` 开头(小写),否则加载校验失败
- 比较时统一转小写,配置中的大写会被拒绝
- **列表为空表示不限制**,生产环境强烈不建议
- 只校验**顶层文件**的扩展名;归档内的子文件由各自规则判定(受 `rule_overrides` 控制)
> 白名单是第一道也是最粗的一道防线。它挡不住"扩展名正确但内容是恶意"的攻击——那是 L1/L2 层的职责。
### 2.3 sandbox_required_extensions
强制走沙箱异步深检的扩展名。
```yaml
sandbox_required_extensions:
- .exe
- .msi
- .js
- .vbs
- .iso
```
**当前版本(P3 一期)沙箱未实现**,配置此项的效果是:命中的文件会走异步模式,并在 `meta` 中标注需要深检。P4 阶段接入 CAPE 后无需修改本项。
### 2.4 rule_overrides
特定规则的强制处置。**这是绕过评分直接裁决的能力**,用于把"一票否决"型规则固化下来。
```yaml
rule_overrides:
MRaptorAutoExecSuspicious:
action: reject
reason: "文档宏具备自动执行且包含可疑行为,按策略直接拒绝"
DDEAutoExecution:
action: reject
reason: "检测到 DDE/DDEAUTO 自动执行字段,按策略直接拒绝"
```
| 字段 | 说明 |
|---|---|
| `action` | 处置动作,见下表 |
| `reason` | 判定理由,可直接展示给用户(支持中文) |
**action 取值**
| 取值 | 行为 |
|---|---|
| `pass` | 放行 |
| `pass_with_flag` | 放行并标记 |
| `manual_review` | 转人工复核(同时把评分提升至 65,确保落入复核区间) |
| `reject` | 拒绝 |
| `reject_and_notify` | 拒绝并通知(当前实现等同 `reject`) |
**生效逻辑**
1. 命中 `rule_overrides` 的规则会**优先于评分**处理
2. 若 `action` 为 `reject` 类 → 立即返回拒绝结论,不再累加评分
3. 若 `action` 为 `manual_review` → 评分提升至 65 并继续后续裁决
**为什么用覆盖而不是纯评分**:像 `PathTraversal`、`DDEAutoExecution` 这类信号,一旦出现就足以判定不可放行,不应依赖其他信号累加来"凑够"阈值。
> 规则名必须与《接口文档》§6 中的 `rule` 字段完全一致,包括大小写。写错不会报错,只是永不生效——因此**每次修改后应实际测试验证**。
### 2.5 notification
```yaml
notification:
include_reason: true
max_reason_length: 500
```
| 字段 | 说明 |
|---|---|
| `include_reason` | 是否在结果中返回判定理由。关闭后 `reason` 为空字符串 |
| `max_reason_length` | 理由最大长度,超出截断(末尾加 `...`) |
> `include_reason` 只影响**返回给调用方的内容**,不影响审计日志。审计日志始终记录完整信息。
### 2.6 audit
```yaml
audit:
log_findings: true
log_extracted_paths: true
```
| 字段 | 说明 |
|---|---|
| `log_findings` | 审计日志中是否记录命中的规则明细 |
| `log_extracted_paths` | 是否记录归档内提取出的文件路径 |
关闭 `log_findings` 可显著降低审计日志体积,代价是事后无法还原"当初为什么判定为恶意"。**建议保持开启**。
---
## 3. 裁决流程
```
┌─────────────────────────┐
检测信号 ────────▶│ 步骤 1:引擎可用性检查 │──▶ 引擎不可用 → fail_closed 拒绝
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ 步骤 2:文件大小检查 │──▶ 超限 → 拒绝
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ 步骤 3:扩展名白名单 │──▶ 不在清单 → 拒绝
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ 步骤 4:加密文件检查 │──▶ 加密且不允许 → 拒绝
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ 步骤 5:规则覆盖匹配 │──▶ 命中 reject 类 → 立即拒绝
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ 步骤 6:权重累加评分 │
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ 步骤 7:阈值映射处置 │
└─────────────────────────┘
```
### 3.1 评分计算
```
score = min(Σ(命中信号的 weight), 100)
```
已被 `rule_overrides` 处理的信号不重复累加。
### 3.2 阈值映射
| 评分区间 | verdict | action |
|---|---|---|
| `score == 0` | `clean` | `pass` |
| `0 < score < review_low` | `suspicious` | `pass_with_flag` |
| `review_low ≤ score < block_score` | `suspicious` | `manual_review` |
| `score ≥ block_score` | `malicious` | `reject` |
### 3.3 权重来源
| 层级 | 典型权重 |
|---|---|
| L0 结构层 | 10 ~ 50 |
| L1 ClamAV | 25 ~ 90 |
| L2 文档深度 | 15 ~ 80 |
| L2B YARA / 二进制 | 10 ~ 85 |
权重定义在各检测引擎内部,调整权重要改代码——**因此优先用 `rule_overrides` 表达策略意图**,而不是频繁改权重。
---
## 4. 调整场景手册
### 4.1 场景:误报过多,业务被阻塞
**症状**:大量正常文档被判为 `manual_review` 或 `reject`。
**排查步骤**
1. 查审计日志,找出被拒文件的命中规则
2. 判断是哪条规则在误报
**处理方式**
| 误报来源 | 处理 |
|---|---|
| 某条规则过于敏感 | 用 `rule_overrides` 将该规则降级为 `pass_with_flag`,并改写 `reason` 说明 |
| 阈值过低 | 提高 `review_score` 下界,或提高 `block_score` |
| 白名单缺少某类型 | 在 `allowed_extensions` 补充 |
| 正常文件确实含宏(如模板文件) | 用 `rule_overrides` 对特定规则放行,**但需评估该文件是否会成为攻击载体** |
> 建议不要直接调高 `block_score`——那会让真正的恶意文件更容易通过。优先降级具体规则。
### 4.2 场景:漏报,需要提升严格度
| 措施 | 配置 |
|---|---|
| 降低复核门槛 | 调低 `review_score` 下界 |
| 直接提高拒绝门槛 | 调低 `block_score` |
| 某类风险必须拦截 | 在 `rule_overrides` 中加 `reject` |
| 禁用某类可执行文件 | 确认 `allowed_extensions` 中不含该类型 |
| 加密文件也拦截 | 保持 `allow_encrypted_*` 为 `false` |
### 4.3 场景:新增业务通道,需要独立策略
**当前版本为全局单策略。** 如需按通道区分,两种做法:
**做法 A(不推荐,需改代码)**:在策略中引入 `channels` 段,裁决时按 `channel` 取对应子策略。
**做法 B(推荐,零代码改动)**:在摆渡系统侧做分流。摆渡系统按通道自行维护白名单,检测服务只做统一的恶意性判定。
> 本期方案已确认采用全局策略。通道字段贯穿全链路(数据库、审计日志、API),后续扩展无需重构。
### 4.4 场景:允许某类加密文件
```yaml
global:
allow_encrypted_document: true
```
**同时必须配套**:加密文件无法静态检测,风险由人工复核承担。建议同时把该类文件的处置设为 `manual_review`:
```yaml
rule_overrides:
PdfEncrypted:
action: manual_review
reason: "PDF 已加密,无法自动检测,转人工复核"
```
### 4.5 场景:新增一种文件类型要放行
1. 在 `allowed_extensions` 补充扩展名
2. 确认该类型没有对应的深度检测引擎(否则即使放行也只是"未检测",不是"已检测通过")
3. 若该类型有特殊风险(如脚本类),评估是否需要新增检测规则
---
## 5. 校验与错误处理
### 5.1 加载时校验项
策略文件在加载时执行严格校验,**任一项不通过则拒绝加载并保留原有策略**:
| 校验项 | 规则 |
|---|---|
| 根节点类型 | 必须是映射结构 |
| `review_score` | 下界必须小于上界 |
| `block_score` | 不应低于 `review_score` 上界;须在 0~100 之间 |
| `rule_overrides[].action` | 必须是合法动作枚举 |
| `allowed_extensions` | 每项必须以 `.` 开头 |
| `sync_max_size` | 须 ≤ `max_file_size` |
> **为什么校验失败要保留旧策略**:如果加载失败时回退到"默认策略"或"空策略",等于把生产环境的判定逻辑悄悄改掉了,比直接报错危险得多。
### 5.2 重载失败的表现
```json
{
"detail": "策略校验失败: block_score (50) 不应低于 review_score 上界 (70)"
}
```
原策略继续生效。修正后重新调用重载接口。
### 5.3 常见配置错误
| 错误 | 后果 | 修正 |
|---|---|---|
| 扩展名写成 `docx`(漏点) | 加载校验失败 | 改为 `.docx` |
| 扩展名大写 `.DOCX` | 加载校验失败 | 改为小写 |
| `rule_overrides` 规则名拼错 | **静默失效** | 对照接口文档 §6 核对,并实际测试 |
| `block_score` 调得极低(如 10) | 正常文件大量被拒 | 回调至 60~80 |
| `allowed_extensions` 留空 | 所有类型都被拒 | 补充清单 |
> **规则名拼错是唯一会静默失效的配置错误**,务必实测。
---
## 6. 变更管理
### 6.1 变更流程
```
提出变更 → 安全管理员评审 → 备份当前策略 → 修改配置
→ 语法校验(本地) → 重载 → 用样本文件验证 → 记录变更
```
### 6.2 变更记录要求
每次策略变更应记录:
| 项 | 说明 |
|---|---|
| 变更时间 | 精确到分钟 |
| 变更人 | 姓名与账号 |
| 变更内容 | 具体字段的前后值 |
| 变更原因 | 业务或安全需求说明 |
| 影响评估 | 是否影响在途文件、是否需要通知对接方 |
| 验证方式 | 用哪些样本文件验证、结果如何 |
### 6.3 版本追溯
每次扫描结果携带 `meta.policy_version` 与 `meta.policy_sha256`。数据库中保留策略版本快照,可用于**按历史策略复现**某一历史文件的判定结果。
### 6.4 灰度建议
策略变更影响面大时,建议:
1. 先在测试环境用真实样本文件验证
2. 对比新旧策略的判定差异(可通过 `rescan` 接口批量重跑)
3. 差异符合预期后再在生产重载
---
## 附录:完整默认策略
见 `config/policy.yaml`。本文档说明各字段含义,实际以配置文件为准。
---
**文档结束** · 配套文档:《总体方案》《接口文档》《等保三级对照表》《运维手册》