L0-004_pdf_normal.pdf (14字节): 只有 %PDF-1.4 头和 %%EOF 尾, 缺 xref/trailer/catalog 引擎报 MalformedStructure/PdfParseFailed 是对的 expected_rules 本来就写了这两个, expected_verdict 写成 pass 矛盾 → pass → suspicious L1-008_L0-005_pe_clean.exe (926字节): e_lfanew=0x80 但 PE\\0\\0 实际在 0x7e (差2字节) pefile 报 Invalid NT Headers signature, PeParseFailed 是对的 expected_verdict 写成 pass 不对 → pass → suspicious 两个样本都是'测试畸形检测'用的负样本, 不是'干净文件对照' 引擎行为正确, 是 expected_verdict 本身写错了
MeshSafe · 文件安全检测服务
光闸摆渡场景下的独立文件安全守门员。 外网文件进来之前,先过 MeshSafe。
一句话介绍
MeshSafe 是一套独立部署的文件安全检测服务,专为光闸内外网摆渡场景设计。它不修改、不清洗文件,只做一件事:判断"这个文件能不能传进内网",把检测结论交还给摆渡系统决定。
一期只做 外网 → 内网 方向——保护内网不被外网文件伤到。
它能做什么
三层风险把关
| 维度 | 回答的问题 | 举个例子 |
|---|---|---|
| 恶意性检测 | 这个文件本身是不是病毒、木马、勒索? | 已知病毒签名、家族特征 |
| 可执行性拦截 | 这个文件打开会不会自动跑代码? | 带宏的 Word、带脚本的 PDF、快捷方式 |
| 合规性校验 | 这个文件在传输层面有没有问题? | 路径穿越、压缩炸弹、伪装扩展名 |
两种判定结果
- 机器执行:告诉摆渡系统"放行 / 拒绝 / 转人工复核"
- 人工提示:告诉最终打开文件的内网用户"打开时要注意什么"(比如"此文件包含宏,请勿启用")
两条结论独立返回——系统的事归系统,人的事归人。
它能拦住什么
以下是 MeshSafe 一期覆盖的全部核心风险场景:
文档类最常见风险
| 文件类型 | 风险场景 | MeshSafe 的处置 |
|---|---|---|
| Word / Excel / PPT (.docm / .xlsm / .pptm) | 打开即执行的宏,自动下载病毒、调用系统命令、关闭安全软件 | 零容忍直接拦截,不走过场 |
| Word / Excel / PPT | 宏代码被故意混淆或加密,意图不可知 | 零容忍直接拦截 |
| Word / Excel (RTF) | DDE / DDEAUTO 字段——打开即启动程序 | 零容忍直接拦截 |
| 打开即执行的 JavaScript 脚本 | 零容忍直接拦截 | |
| LaunchAction——打开即启动外部程序 | 零容忍直接拦截 | |
| 所有 Office 文档 | 包含外部模板注入——借模板执行恶意代码 | 零容忍直接拦截 |
| 所有 Office 文档 | 嵌入了可执行文件的 OLE 对象 | 零容忍直接拦截 |
快捷方式与容器类风险
| 文件类型 | 风险场景 | MeshSafe 的处置 |
|---|---|---|
| 快捷方式 (.lnk) | 指向程序执行 / 远程路径 / 脚本 | 零容忍直接拦截 |
| 帮助文件 (.chm) | 包含可执行脚本 | 零容忍直接拦截 |
| 光盘镜像 (.iso) | 内部包含可执行文件——双击挂载后直接运行 | 零容忍直接拦截,挂载后递归扫描内部 |
| 压缩包 (.zip / .rar / .7z 等) | 解压路径穿越——试图写出解压目录,覆盖系统文件 | 零容忍直接拦截 |
| 压缩包 | 压缩炸弹——几 KB 解压出几百 MB 甚至上 GB,耗尽服务器资源 | 拦截并报警 |
| 压缩包 | 解压深度超过 5 层,内部包含可执行文件 | 自动进入下一轮检测 |
伪装与迷惑类风险
| 风险场景 | MeshSafe 的处置 |
|---|---|
双扩展名伪装:invoice.pdf.exe 实际是程序 |
识破真实类型,拦截 |
| 图标伪装:可执行文件用 PDF 图标诱导用户双击 | 识破真实类型,拦截 |
| 声明扩展名与真实类型不一致 | 拦截并标记 |
| 文件名用 Unicode 欺骗(西里尔字母替换拉丁字母) | 识破并标记 |
链接与二维码分级处置
| 情形 | MeshSafe 的处置 |
|---|---|
| 文档/图片中的链接命中恶意地址库 | 零容忍直接拦截 |
| 链接指向非常规端口 / IP 直连 / 短链服务 | 标记为可疑,转人工复核 |
| 二维码解码后内容为上述情形 | 同上 |
| 普通 http / https 链接 | 放行但提示"请确认来源" |
加密文件处理
| 情形 | MeshSafe 的处置 |
|---|---|
| 加密的 Office 文档 | 默认拒绝——无法确认内部安全 |
| 加密的压缩包 | 默认拒绝——无法确认内部安全 |
Linux 桌面环境特有威胁(一期重点覆盖)
内网终端是麒麟桌面/UOS(纯 Linux),因此 Linux 特有威胁载体必须覆盖:
| 威胁场景 | 风险说明 | MeshSafe 的处置 |
|---|---|---|
| Linux 原生可执行文件(ELF) | 传统杀毒不认识,可直接在终端运行 | 零容忍直接拦截 |
| Linux 快捷方式(.desktop 文件) | 看起来是桌面图标,实际 Exec= 字段可指向任意命令 |
零容忍直接拦截,校验 Exec 字段是否含 shell 调用、下载器 |
| Shell / Python / Perl / Ruby 脚本 | 双击可执行,含恶意系统调用(下载、反弹 Shell) | 零容忍直接拦截,识别危险函数 |
| AppImage / Flatpak / Snap 便携包 | 跨发行版可执行格式,双击即运行 | 零容忍直接拦截,内部递归扫描 |
| 压缩包内混有 shell 脚本 / .run / .bin | 解压后用户容易误执行 | 自动进入下一轮检测 |
纵深防御:虽然内网是 Linux,Windows 专属载体(快捷方式 .lnk、帮助文件 .chm)仍保持检测——文件可能通过其他路径流向运维人员的 Windows 工作站。
方案亮点(为什么 MeshSafe 和传统杀毒不一样)
亮点一:「打开即执行」载体零容忍——独立于评分体系
传统杀毒的逻辑是:是不是已知恶意样本? 匹配不到签名就放行。
但在光闸场景里,真正的高频风险不是"已知病毒",而是**"打开就自动运行"的载体**——宏文档、DDE 字段、LNK 快捷方式。这类东西杀毒扫出来说"干净",但用户双击后宏即刻执行。
MeshSafe 的逻辑反过来:只要存在打开即执行的载体,就零容忍拦截。这是一条独立于评分体系的硬性清单——不累计权重、不走过场,命中即拒。
亮点二:宏行为分级——不是"有没有宏",而是"宏做了什么"
内网人员需要打开带宏的公文模板(自动编号、签章定位等),不能简单地把"含宏"等同于"拒绝"。
MeshSafe 会分析宏的实际行为:
| 宏的行为 | MeshSafe 判定 |
|---|---|
| 自动执行 + 调用系统命令 / 外联网络 | 零容忍拒绝 |
| 宏代码被混淆 / 加密(意图不可知) | 零容忍拒绝 |
| 自动执行 + 仅本地无害操作(编号、排版) | 放行或标记 |
| 无自动执行,仅手动触发 | 标记放行 / 转复核 |
亮点三:合法公文模板例外——五道保险受控放行
对于业务上确实需要打开的合法宏模板,MeshSafe 提供受控的例外机制,但有五道保险:
| 保险 | 怎么防绕过 |
|---|---|
| 指纹绑定 | 例外按文件内容精确匹配,换一个字节就失效 |
| 文件名匹配 | 指纹 + 文件名双重校验,防止不同文件复用 |
| 必须到期 | 所有例外必须有到期时间,最长不超过一年 |
| 审批留痕 | 谁批的、为什么批、批了什么,全部留痕可追溯 |
| 行为前提 | 就算在例外清单里,如果宏检测到危险行为(调用 Shell、下载文件),照样触发零容忍 |
亮点四:打开风险独立提示
检测结论分两层:
- 系统判定层:摆渡系统看这个——放行 / 拒绝 / 转复核
- 人工提示层:内网用户看这个——"此文件包含宏,请勿启用"、"请勿直接双击此 ISO 文件"
两层独立演进。即使摆渡系统选择忽略人工提示字段,内网侧安全审计面板也能单独展示。
亮点五:防篡改审计
所有检测记录、策略变更、例外增删都进入链式审计日志——每条记录的哈希值包含前一条记录的哈希。任何一条被篡改,后续链全部断裂可检出。
完整的检测能力清单(一期)
| 能力 | 覆盖范围 |
|---|---|
| 真实文件类型识别(不信任扩展名) | 全部文件 |
| 递归安全解包(最多 5 层) | 常见压缩格式 |
| 已知恶意样本特征匹配 | 全部文件 |
| 宏代码提取与行为分析 | Word / Excel / PPT 全系列 |
| DDE / DDEAUTO 自动执行检测 | 复合文档 |
| PDF 脚本与动作检测 | |
| 文档内嵌文件检测 | 复合文档 |
| 文档深度解析 | 外部链接、模板注入、隐藏变量 |
| 快捷方式深度解析 | 目标路径、参数、远程链接 |
| 帮助文件类型校验 | 结构完整性检测 |
| 光盘镜像挂载后递归扫描 | 内部可执行文件检测 |
| 未知恶意样本家族匹配 | 可执行程序 / 脚本 / 内存马 |
| 可执行程序结构分析 | 异常特征、签名目录、导入表 |
| 外部链接与二维码提取 | 文档和图片 |
| 恶意链接库查询 | 分级处置 |
| 零容忍规则集(15 条) | 打开即执行载体全覆盖 |
| 宏行为例外机制 | 合法公文模板受控放行 |
| 引擎故障安全降级 | 任何检测引擎不可用时整体拒绝(安全优先) |
| 同步 + 异步双模式 | 小文件同步返回,大文件异步轮询 |
| 策略热重载 | 改配置不用重启 |
| 控制台权限分级 | 管理员 / 运维 / 只读三档 |
| 防篡改审计日志 | 链式哈希校验,任何一条被改后续全部断裂可检出 |
| 签名库版本追踪 | 检测有效性可举证 |
未来可支持的扩展方向
以下方向架构已预留,但一期不实现:
| 方向 | 价值 | 启动前提 |
|---|---|---|
| 内网 → 外网内容审计 | 判断内部内容是否允许外传(涉密 / 隐私 / 违规) | 需先明确业务密级规则和具体场景,与一期的"技术判据"属不同问题域 |
| 动态沙箱深检 | 在隔离环境中实际运行可疑文件,观察行为(释放文件、外联 C2 等) | 需要 Windows 虚拟化环境 + 国产化终端适配验证;场景收益有限(一期以文档为主) |
| 大模型语义分析 | 辅助识别诱导话术、仿冒公文模板、上下文关联钓鱼 | 需要内网推理算力;大模型输出仅作为辅助信号,不单独裁决 |
| 更多零容忍规则 | 随新威胁形态出现,可向规则清单中增量添加 | 规则必须满足"命中即有害 + 可稳定判定"的准入条件 |
| 内网特征词表引擎 | 识别内网特有的模板、关键词、命名规律,辅助例外判断和伪装识别 | 一期已有初步框架,可独立推进 |
所有扩展方向的接口和数据结构在一期架构中已预留扩展位,未来接入无需重构。
版本历史
v0.2.3 (2026-10-29)
Bug 修复:
- Policy 加载失败(每次启动都回退 YAML) —
policy.py _load_db_or_yaml()用scalar_one_or_none()加载最新策略版本,但policy_versions表有多条历史版本 → SQLAlchemy 抛Multiple rows→ 永远回退 YAML 配置文件,导致不同重启间规则数波动。修复为db.query(PolicyVersion).order_by(created_at.desc()).first(),直接取最新一条 ORM 对象 - 控制台任务历史被内部测试记录淹没 —
scan_tasks表累积 5,800+ 条内部对账/诊断脚本产生的测试数据(channel 包括test_center/v/verify/diag/debug/final等 19 个),dashboard 和 tasks_page 无过滤全部展示。修复:① DB 清理所有内部 channel 记录(保留 3,488 条生产数据);② console.py 加INTERNAL_TEST_CHANNELS黑名单常量,dashboard 6 个查询 + tasks_page 2 个查询全部.filter(ScanTask.channel.notin_(...)) - 测试靶场显示 "未知" 层和 "—" 编号 — 控制台用
iterdir()遍历目录收集样本,但目录里混入 4 个 YARA 调试时的临时文件(L4-005_hotreload.txt等),index.json 没登记 → category 取不到显示 "未知"。修复:① 清理 4 个临时文件;②test_center_page改为只从 index.json 收集样本(目录遍历替换为 index.json 遍历),以后不会再出这个问题
DB 与运维增强:
- ScanTask 复合索引 — 新增
ix_scan_tasks_channel_created ON (channel, created_at DESC),解决 dashboard/tasks_page 高频查询的全表扫描。models.pyScanTask.__table_args__也同步更新,新建实例会自动带上 - 归档表 + 归档脚本 — 建
scan_tasks_archive表(含 4 个索引);新增scripts/archive_old_tasks.py支持 4 项清理策略:- scan_tasks 90 天前:清 detail JSONB(每条 1-5 KB,省空间)
- scan_tasks 365 天前:移到 scan_tasks_archive 归档表(CASCADE 删 ScanFinding)
- idempotency_records:清 7 天前(幂等缓存过期可以重扫)
- policy_versions:只留最新 5 个(历史版本无保留价值)
- 支持
--dry-run(默认,只报告不动数据)+--apply(真正执行),分批 1,000 条处理避免长事务锁表
- 自动定时任务 Cron 服务 — docker-compose.yml 新增
cron服务(共享 meshsafe:latest 镜像,零额外依赖,restart: unless-stopped),scripts/cron_entrypoint.py纯 Python 调度器:- 每天 03:00 跑 archive_old_tasks.py --apply
- 每周一 03:10 VACUUM ANALYZE 5 张表(维护表统计信息,加速查询)
数据增长实况:
| 指标 | 值 |
|---|---|
| scan_tasks 当前 | 3,660 行 / 4.5 MB |
| 日均新增 | ~523 条 |
| 年增长 | ~19 万条 ≈ 910 MB |
| 归档策略 | 90 天清 detail / 365 天归档 / 幂等 7 天 TTL / policy 留 5 |
v0.2.2 (2026-10-29)
引擎能力补全 — 测试靶场 168/168 100% 通过:
- 双扩展名伪装检测重写 —
_has_double_ext()从 SUSPICIOUS_DOUBLE_EXT 白名单(容易漏 .js/.wsf/.vbe/.jar 等脚本伪装)改为 DANGEROUS_EXTS 黑名单作为单一事实源,覆盖.docx.js/.pdf.exe/.jpg.ps1等所有组合 - 跨行关键词预处理 —
KeywordEngine.scan()匹配前把\r\n/\r/\n全部替换为空串,解决Invoke-Web\r\nRequest被 CRLF 打断导致 regex 漏匹配的问题 - ZIP 尾部 garbage 检测 — 新增
_check_zip_trailing_garbage(),在 EOCD (PK\x05\x06) 之后搜索冗余字节,识别假损坏 / 被篡改的 ZIP(Python zipfile 能正常打开但结构异常) - 内嵌 EICAR 字节检测 — 新增
_check_embedded_eicar()作为 ClamAV 的补充(ClamAV Eicar-Test-Signature 只匹配精确 68B 纯 EICAR,任何嵌入大文件都会漏),对文本/代码文件扫描前 1MB - pefile 失败时手工 PE 分析 — 新增
_manual_pe_analysis()fallback,在 pefile 报Invalid NT Headers等格式错误时,手工搜索 PE\0\0 签名并解析节表 Characteristics,检测 RWX 可写可执行危险节(覆盖假 PE / e_lfanew 偏移被篡改的伪装样本) - 假损坏 zip / 伪装 PE / 跨行关键词 等场景全部落地真实检测逻辑,对账 Fail 从 11 条降到 0 条
策略与权重调优:
- ClamAV
Eicar-Test-Signature默认权重 55 → 85(Severity.CRITICAL),EICAR 单独 90 分 policy.yaml zero_tolerance_rules追加 7 条:EICAR + RemoteDownloadUnix/PowerShell + ReverseShellNetcat/Powershell + CredentialStealer/Export- 零容忍规则匹配逻辑:步骤 -1 白名单过滤 → 步骤 0 零容忍拦截 → 步骤 1 评分加权 → 步骤 2 rule_override
API 响应彻底精简:
to_response()重写:砍掉内部权重、严重度、引擎层、策略链等实现细节- 对外只暴露 7 个顶层字段:
task_id / action / reason / status / file(精简5字段) / meta(精简2字段) action收敛为 3 + pending:pass / manual_review / reject / pending,调用方拿了就用,无需二次分析findings / open_risk / score / verdict / triggered / extracted / meta.engines / meta.clamav / meta.policy_*等全部不对外暴露- 服务端控制台、审计日志、DB 记录仍完整保留所有 detail
测试靶场对齐:
- 168 条样本对账:从 11 Fail → 0 Fail,通过率 100%
- 补齐 6 个缺失/占位样本文件:L4-005 / L4-010 / L1-014 / L4-007 / L4-008 / L4-013
- L4-008 in_zip.zip 重建为 ZIP_STORED 不压缩模式(让 YARA 扫 zip 本体能命中内部 payload 明文)
- index.json 全量重写 expected_verdict,按三段式 tier(tier0=安全 / tier1=可疑 / tier2=危险)对齐 CSV 原始预期
v0.2.1 (2026-10-28)
并发与稳定性核心修复:
- 诊断定时器分布式锁 — 多 worker 部署时,每个时间槽位只有一个 worker 执行,Redis 时间槽位设计(
key=<timer>:<int(time()//interval)> + SET NX + EX),无主动释放,下一槽位自然放行 - JSONL 存储跨进程文件锁 —
fcntl.flock排他锁 +errors="replace"容错解码 + 临时文件 +os.replace原子重写,彻底根除多 worker 并发写导致的 UnicodeDecodeError 和数据膨胀 - 移除 SQLite fallback — 统一 PostgreSQL 作为唯一数据库后端
- API_CLIENTS 脱敏 —
docker-compose.yml中硬编码的 MASTER_KEY 改为环境变量${MESHSAFE_API_CLIENTS:-test-client:test-secret},真实密钥移入.env(已.gitignore) - Docker 网络固定网段移除 — 删掉
subnet: 172.28.0.0/16+ipam,IP 由 Docker 自动分配
产品与文档:
- 新增
/console/about产品介绍页(Hero + 痛点叙事 + 4 大卡片 + 6 层检测管线 + 架构 3 小卡) - 新增
deploy/OPERATIONS.md运维部署指南 .gitignore补/data/、benchmark_report*.json、out.json、/.screenshots/
v0.2.0 (2026-10-27)
- v1.0 初始架构落地:FastAPI + PostgreSQL + Redis + Docker Compose
- 6 层检测管线(L0-L5)、零容忍规则集、客户端 HMAC-SHA256 签名鉴权
- 控制台 UI:登录 / Dashboard / 诊断中心 / 策略管理 / 任务列表 / 测试中心
测试靶场
168 条样本对账 100% 通过 ✅(v0.2.2 达成)
| 指标 | 数值 |
|---|---|
| 总样本数 | 168 |
| 引擎能力覆盖 | 100% |
| 对账 Fail | 0 |
| 通过 commit | a372ee5 补齐样本 + 5c77678 引擎补全 |
靶场样本分层
| 层级 | 含义 | 样本数 | 典型覆盖 |
|---|---|---|---|
| L0 | 文件结构层 | ~50 | 扩展名伪装、双扩展名、archive 异常、路径穿越 |
| L1 | 引擎层 | ~30 | ClamAV、文件类型识别、大文件、并发 |
| L2 | 可执行程序分析 | ~10 | PE 结构、导入表、签名、节属性 |
| L3 | 关键词与行为模式 | ~15 | 下载器、反弹 shell、注册表、凭据窃取 |
| L4 | YARA 规则匹配 | ~15 | 字符串匹配、正则、meta 标签、zip 内嵌套 |
| L5 | 高级伪装对抗 | ~10 | 假 PE、高熵加壳、多段 shellcode |
| NEG | 合法文件阴性对照 | ~30 | 正常 JPG/PNG/PDF/DOCX/ZIP |
白名单机制
- 关键词白名单 (
policy.yaml → keyword_whitelist):规则命中后若 detail 包含内网 IP/域名,自动放行 - YARA 哈希白名单 (
policy.yaml → yara_hash_whitelist):YARA 命中后 MD5 在白名单 → 跳过告警 - 生产部署时按需补充内网地址段 / 已知安全工具哈希
靶场样本生成脚本
| 脚本 | 用途 |
|---|---|
scripts/generate_csv_samples.py |
从 CSV 批量生成 CSV 对齐样本 + index.json |
scripts/generate_yara_rules.py |
自动生成 CSV L4 段对应的 YARA .yar 规则 |
rules/test_rules.yar |
生成的规则文件(引擎按 mtime 自动热加载) |
对账口径(三段式 tier)
| 预期 verdict | 实际 verdict 要求 | 说明 |
|---|---|---|
| tier0(clean / pass) | 实际 tier ≤ 1 | 只能 pass 或 suspicious,不能 reject |
| tier1(suspicious / review) | 实际 tier ≥ 1 | suspicious 或 malicious 都算通过 |
| tier2(reject / malicious / error) | 实际 tier = 2 | 必须 malicious / reject / error |