devpedrois/crabwalk
GitHub: devpedrois/crabwalk
Crabwalk 是一款基于 Rust 和 BLAKE3 并行哈希的文件系统快照与差异对比 CLI 工具,用于检测目录中文件内容及元数据的未授权变更。
Stars: 0 | Forks: 0
# Crabwalk
[](#)
[](./LICENSE)
[](https://www.rust-lang.org)
[](#security)
**用于安全审计和部署验证的文件系统快照差异对比工具。**
Crabwalk 会对目录进行时间点快照(包含 BLAKE3 哈希、权限、时间戳、所有权),并通过对比来精确展示发生了哪些变化。专为基础设施安全团队、系统管理员和合规工作流而构建。
```
crabwalk snap /etc --output baseline.json
# ... 部署、事故或时间流逝 ...
crabwalk snap /etc --output current.json
crabwalk diff baseline.json current.json --format table
```
```
Crabwalk Diff Report
Summary: Added: 1 | Removed: 1 | Modified: 2 | Metadata: 3 | Total: 7
┌──────────────────┬─────────────────────────┬────────────────────────────────┐
│ Status │ Path │ Details │
├──────────────────┼─────────────────────────┼────────────────────────────────┤
│ ADDED │ etc/cron.d/backdoor │ │
│ REMOVED │ etc/app.conf │ │
│ MODIFIED │ bin/sshd │ hash: a1b2c3... → f4e5d6... │
│ META │ etc/sudoers │ permissions: 0440 → 0777 │
└──────────────────┴─────────────────────────┴────────────────────────────────┘
```
## 目录
- [用例](#use-cases)
- [环境要求](#requirements)
- [安装](#installation)
- [快速开始](#quick-start)
- [命令](#commands)
- [忽略模式](#ignore-patterns)
- [输出格式](#output-formats)
- [架构](#architecture)
- [安全](#security)
- [性能](#performance)
- [贡献](#contributing)
- [许可证](#license)
## 用例
- **部署验证** - 对比发布前后的文件系统状态
- **安全审计** - 检测二进制文件、配置或权限的未授权更改
- **配置漂移检测** - 发现不同环境之间或随时间推移的配置漂移
- **合规证据** - 将确定性的、可复现的审计快照持久化作为交付物
- **事件响应** - 准确查明事件发生期间发生了什么变化以及发生时间
## 环境要求
- Rust 1.75 或更新版本
- Cargo(随 Rust 一起安装)
通过 [rustup](https://rustup.rs) 安装 Rust:
```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
## 安装
### 从源码安装
```
git clone https://github.com/devpedrois/crabwalk
cd crabwalk
cargo build --release
```
编译生成的二进制文件位于 `target/release/crabwalk`。将其复制到您需要的任何位置:
```
cp target/release/crabwalk /usr/local/bin/crabwalk
```
### 免安装运行
```
cargo run -- snap /etc --output baseline.json
cargo run -- diff baseline.json current.json
```
## 快速开始
**1. 对目录进行快照:**
```
crabwalk snap /etc --output baseline.json
```
**2. 进行更改,再次快照:**
```
crabwalk snap /etc --output current.json
```
**3. 对比两个快照的差异:**
```
crabwalk diff baseline.json current.json --format table
```
**4. 导出为 HTML 报告:**
```
crabwalk diff baseline.json current.json --format html --output report.html
```
## 命令
### `crabwalk snap `
递归遍历目录并生成一个 JSON 快照,其中包含每个条目的 BLAKE3 哈希、权限、时间戳和所有权。
```
crabwalk snap [OPTIONS]
OPTIONS:
-o, --output Write snapshot to file (default: stdout)
--max-size Skip files larger than SIZE (e.g. 100MB, 1GB)
--no-ignore Do not load .crabwalkignore files
--follow-symlinks Follow symlinks [default: off, see Security]
--threads Rayon worker threads (default: number of CPU cores)
```
示例:
```
# 对 /etc 建立快照,跳过大于 10MB 的文件
crabwalk snap /etc --max-size 10MB --output etc-snap.json
# 使用 4 个线程
crabwalk snap /var/www --threads 4 --output www-snap.json
# 建立快照且忽略 .crabwalkignore
crabwalk snap /app --no-ignore --output app-snap.json
```
### `crabwalk diff `
对比两个快照文件并报告发生的更改。将每项更改分类为 `Added`(新增)、`Removed`(移除)、`Modified`(内容修改)或 `MetadataChanged`(元数据修改:权限、所有权、mtime)。
```
crabwalk diff [OPTIONS]
OPTIONS:
-f, --format Output format: table, json, html (default: table)
-o, --output Write output to file (default: stdout, required for html)
--ignore-mtime Ignore mtime-only differences
--ignore-metadata Suppress metadata-only changes, show content changes only
--only Filter change types: added,removed,modified,metadata
```
退出代码:
| 代码 | 含义 |
|------|---------|
| `0` | 未检测到更改 |
| `1` | 检测到更改 |
| `2` | 执行或输入错误 |
示例:
```
# 终端中以人类可读的表格显示
crabwalk diff before.json after.json
# 输出 JSON 到文件
crabwalk diff before.json after.json --format json --output diff.json
# 仅显示内容更改,忽略权限/mtime 漂移
crabwalk diff before.json after.json --ignore-metadata
# 仅显示新增和删除的文件
crabwalk diff before.json after.json --only added,removed
# HTML 报告
crabwalk diff before.json after.json --format html --output report.html
```
## 忽略模式
在要进行快照的目录中创建一个 `.crabwalkignore` 文件。使用与 `.gitignore` 相同的语法,由 ripgrep 使用的同一个 `ignore` crate 提供支持。
```
# .crabwalkignore
# 忽略构建产物
target/
*.log
# 忽略版本控制元数据
.git/
# 取反:始终包含此特定日志
!important.log
# 忽略缓存目录
**/__pycache__/
**/node_modules/
```
传入 `--no-ignore` 可完全禁用此行为。
## 输出格式
### 表格(默认)
带颜色的终端输出。最适合交互式使用和快速审查。
- 绿色:`ADDED`
- 红色:`REMOVED`
- 黄色:`MODIFIED`
- 青色:`META`
```
crabwalk diff old.json new.json
```
### JSON
机器可读的结构化输出。适用于通过管道传递给其他工具、作为交付物存储或构建仪表板。
```
crabwalk diff old.json new.json --format json
```
输出结构:
```
{
"old_snapshot": "baseline.json",
"new_snapshot": "current.json",
"timestamp": "2026-05-20T12:00:00Z",
"summary": {
"added": 1,
"removed": 1,
"modified": 2,
"metadata_changed": 3,
"total": 7
},
"entries": [
{
"path": "etc/sudoers",
"change_type": "MetadataChanged",
"details": ["permissions: 0440 -> 0777"]
}
]
}
```
### HTML
包含摘要卡片和交互式过滤器的独立 HTML 报告。需要指定 `--output`。
```
crabwalk diff old.json new.json --format html --output report.html
open report.html
```
## 架构
```
crabwalk/
├── Cargo.toml # Dependencies and package metadata
├── .crabwalkignore.example # Example ignore pattern file
│
├── src/
│ ├── main.rs # Entry point: CLI parse -> dispatch to snap/diff
│ ├── cli.rs # Clap structs: SnapArgs, DiffArgs, OutputFormat
│ │
│ ├── walker.rs # Recursive directory traversal via walkdir
│ │ # Applies filters before hashing
│ │ # Never follows symlinks outside root
│ │
│ ├── hasher.rs # BLAKE3 streaming hash in 64KB chunks via BufReader
│ │ # Never loads entire file into memory
│ │ # Send + Sync for rayon parallelism
│ │
│ ├── snapshot.rs # Snapshot + FileEntry structs with serde
│ │ # Entries always sorted by path (determinism)
│ │
│ ├── diff.rs # Diff engine: HashMap-indexed comparison
│ │ # Categorizes: Added, Removed, Modified, MetadataChanged
│ │
│ ├── filter.rs # .crabwalkignore via `ignore` crate
│ │ # --max-size enforcement before hashing
│ │ # Special file detection and skip
│ │
│ ├── output/
│ │ ├── mod.rs # OutputFormatter trait + format dispatch
│ │ ├── table.rs # comfy-table + colored terminal output
│ │ ├── json.rs # serde_json pretty output to stdout or file
│ │ └── html.rs # Askama compiled template -> HTML report
│ │
│ └── error.rs # CrabwalkError enum via thiserror
│ # Io, Walk, Hash, Snapshot, Diff, Filter, Output
│
├── templates/
│ └── report.html # Askama HTML diff report template
│
├── tests/
│ ├── snap_test.rs # Snapshot determinism, metadata, errors
│ ├── diff_test.rs # All change categories
│ ├── filter_test.rs # Ignore patterns and max-size
│ ├── security_test.rs # Symlinks, special files, path traversal
│ └── integration_test.rs # End-to-end: snap -> modify -> snap -> diff
│
└── benches/
└── walker_bench.rs # Criterion: sequential vs parallel, various sizes
```
### 数据流
```
PATH
|
v
[walker.rs] -- recursive walk, metadata collection
|
v
[filter.rs] -- .crabwalkignore, --max-size, skip special files
|
v
[hasher.rs] -- rayon par_iter: BLAKE3 streaming hash per file
|
v
[snapshot.rs] -- sort by path, serialize to JSON
|
v (two snapshots)
[diff.rs] -- HashMap comparison, categorize changes
|
v
[output/] -- table | json | html
```
### 主要依赖
| Crate | 版本 | 用途 |
|-------|---------|---------|
| `clap` | 4 | 带有 derive 宏的 CLI 解析 |
| `walkdir` | 2 | 递归目录遍历 |
| `blake3` | 1 | 流式加密哈希(比 SHA-256 更快) |
| `rayon` | 1.10 | 通过 `par_iter()` 实现数据并行 |
| `serde` + `serde_json` | 1 | 快照序列化 |
| `ignore` | 0.4 | `.gitignore` 风格的模式匹配(与 ripgrep 相同) |
| `comfy-table` + `colored` | 7 / 2 | 带颜色的终端表格输出 |
| `askama` | 0.12 | 编译时类型安全的 HTML 模板 |
| `thiserror` | 2 | 符合人体工程学的错误类型派生 |
| `chrono` | 0.4 | ISO 8601 时间戳 |
## 安全
Crabwalk 是一款安全审计工具。它默认将文件系统视为具有潜在威胁的环境。
### 纵深防御
| 层级 | 威胁 | 缓解措施 |
|-------|--------|-----------|
| 1. 软链接安全 | 软链接逃逸至 `/etc/shadow` | 默认不跟随软链接。`--follow-symlinks` 为可选启用项,且会限制在根目录内 |
| 2. 路径标准化 | 通过精心构造的路径进行目录遍历 | 所有快照路径均相对于根目录,绝不使用绝对路径 |
| 3. 流式哈希 | 大文件导致 OOM | 通过 64KB 的 `BufReader` 数据块计算 BLAKE3。任意文件大小均保持恒定内存占用 |
| 4. 特殊文件保护 | 无限读取 `/dev/zero`,管道阻塞 | 跳过字符设备、块设备、FIFO 和套接字并进行报告 |
| 5. 错误报告 | 隐藏篡改行为的静默失败 | 每个 I/O 错误都会记录在 `FileEntry.error` 中。快照元数据中包含 `total_errors` |
| 6. TOCTOU 感知 | 文件在遍历与哈希计算期间发生更改 | 扫描中途消失的文件会产生错误条目,绝不会引发 panic |
| 7. 快照完整性 | 被篡改的快照文件 | 确定性的 JSON 排序。用于兼容性检查的 Schema 版本字段 |
| 8. 输入验证 | 格式错误的路径或选项 | 所有 CLI 输入在处理前均经过验证。严格的 serde 反序列化 |
### Crabwalk 不会做的事
- 不验证其自身二进制文件的完整性(请使用您的包管理器或 TPM 来实现此目的)
- 快照未进行加密签名(如有需要,请自行进行 GPG 签名)
- 不进行实时操作(它是一个时间点工具,不是 daemon)
## 性能
Crabwalk 使用 Rayon 跨所有可用的 CPU 核心并行计算文件哈希。无论文件大小如何,内存占用始终保持不变。
### 基准测试结果
2026-05-20 的参考运行结果(`cargo bench --bench walker_bench`):
| 基准测试 | 时间 |
|-----------|------|
| `snapshot_small / sequential` | ~9.91 ms |
| `snapshot_small / parallel` | ~4.46 ms |
| `snapshot_medium / sequential` | ~107.06 ms |
| `snapshot_medium / parallel` | ~41.21 ms |
| `hash_single_file / 1KB` | ~43.36 µs |
| `hash_single_file / 100KB` | ~76.67 µs |
| `hash_single_file / 1MB` | ~316.56 µs |
| `hash_single_file / 10MB` | ~4.13 ms |
| `diff_engine / 100 entries` | ~35.75 µs |
| `diff_engine / 1000 entries` | ~404.13 µs |
| `diff_engine / 10000 entries` | ~6.83 ms |
并行模式在中等工作负载下可带来约 2.5 倍的加速。diff 引擎随条目数量呈线性扩展。
### 运行基准测试
```
cargo bench --bench walker_bench
```
使用 Hyperfine 对比串行与并行:
```
hyperfine \
"crabwalk snap ./target --threads 1 --output /tmp/seq.json" \
"crabwalk snap ./target --threads 8 --output /tmp/par.json"
```
## 许可证
MIT。详见 [LICENSE](./LICENSE)。
标签:Rust, 可视化界面, 文件系统, 网络流量审计, 运维工具, 通知系统