Files
xingrin/docs/nuclei-template-architecture.md
2025-12-17 18:20:50 +08:00

230 lines
18 KiB
Markdown
Raw 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.
# Nuclei 模板管理架构
本文档介绍 XingRin 中 Nuclei 模板的存储、同步和使用机制。
## 目录结构
```
/opt/xingrin/nuclei-repos/
├── nuclei-templates/ # 官方模板仓库(按仓库名命名)
│ ├── .git/
│ ├── http/
│ ├── network/
│ └── ...
└── custom-repo/ # 自定义模板仓库
```
## 一、存储位置
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| `NUCLEI_TEMPLATES_REPOS_BASE_DIR` | `/opt/xingrin/nuclei-repos` | 模板仓库根目录 |
每个模板仓库会在根目录下创建独立子目录,目录名由仓库名称 slugify 生成。
## 二、数据模型
```
NucleiTemplateRepo
├── id # 仓库 ID
├── name # 仓库名称(用于前端展示和 Worker 查询)
├── repo_url # Git 仓库地址
├── local_path # 本地克隆路径(自动生成)
├── commit_hash # 当前同步的 commit hash
└── last_synced_at # 最后同步时间
```
## 三、Server 端同步流程
1. 用户在前端添加模板仓库(填写名称和 Git URL
2. 点击「同步」触发 `NucleiTemplateRepoService.refresh_repo()`
3. 首次同步:`git clone --depth 1`(浅克隆,节省空间)
4. 后续同步:`git pull --ff-only`(快进合并)
5. 同步成功后更新数据库:`commit_hash``last_synced_at`
```
┌──────────────────────────────────────────────────────────────────────────┐
│ Server 容器 │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 前端 UI │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ 添加仓库 │ │ 同步仓库 │ │ 浏览模板 │ │ │
│ │ │ name + url │ │ 点击刷新 │ │ 目录树 │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └──────────────┘ │ │
│ └─────────┼───────────────────┼───────────────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ NucleiTemplateRepoViewSet │ │
│ │ POST /api/nuclei/repos/ | POST .../refresh/ │ │
│ └─────────────────────────────┬───────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ NucleiTemplateRepoService │ │
│ │ │ │
│ │ ┌────────────────────┐ ┌────────────────────────────────┐ │ │
│ │ │ ensure_local_path()│ │ refresh_repo() │ │ │
│ │ │ 生成本地目录路径 │ │ 执行 Git 同步 │ │ │
│ │ └────────────────────┘ └───────────────┬────────────────┘ │ │
│ └────────────────────────────────────────────┼────────────────────┘ │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ 首次同步(无 .git │ │ 后续同步(有 .git │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ git clone --depth 1 │ │ git pull --ff-only │ │
│ │ <repo_url> │ │ │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
│ │ │ │
│ └──────────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ git rev-parse HEAD │ │
│ │ 获取当前 commit hash │ │
│ └──────────────────────────┬──────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL 数据库 │ │
│ │ │ │
│ │ UPDATE nuclei_template_repo SET │ │
│ │ local_path = '/opt/xingrin/nuclei-repos/xxx', │ │
│ │ commit_hash = 'abc123...', │ │
│ │ last_synced_at = NOW() │ │
│ │ WHERE id = ? │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 文件系统 │ │
│ │ /opt/xingrin/nuclei-repos/ │ │
│ │ ├── nuclei-templates/ # 官方模板 │ │
│ │ │ ├── .git/ │ │
│ │ │ ├── http/ │ │
│ │ │ ├── network/ │ │
│ │ │ └── ... │ │
│ │ └── custom-repo/ # 自定义模板 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────┘
│ git clone / pull
┌─────────────────────┐
│ GitHub / GitLab │
│ 远程 Git 仓库 │
└─────────────────────┘
```
## 四、Worker 端同步流程
Worker 执行扫描任务时,通过 `ensure_nuclei_templates_local()` 确保本地模板与 Server 版本一致:
1. 从数据库查询仓库记录,获取 `repo_url``commit_hash`
2. 检查本地是否存在仓库目录
- 不存在:`git clone --depth 1`
- 存在:比较本地 commit hash 与 Server 的 `commit_hash`
3. 如果 commit 不一致:`git fetch` + `git checkout <commit_hash>`
4. 返回本地模板目录路径,供 nuclei 命令使用
```
┌──────────────────────────────────────────────────────────────────────────┐
│ Worker 容器 │
│ │
│ ┌─────────────┐ │
│ │ 扫描任务 │ │
│ │ 开始执行 │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ ┌─────────────────────────────────┐ │
│ │ ensure_nuclei_ │ │ PostgreSQL │ │
│ │ templates_local() │─────▶│ 查询 NucleiTemplateRepo 表 │ │
│ │ │ │ 获取 repo_url, commit_hash │ │
│ └───────────┬─────────────┘ └─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ 检查本地 .git 目录 │ │
│ └───────────┬─────────────┘ │
│ │ │
│ ┌───────┴───────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────┐ ┌────────────┐ │
│ │ 不存在 │ │ 存在 │ │
│ └───┬────┘ └─────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────┐ ┌─────────────────────┐ │
│ │ git clone │ │ 比较 commit hash │ │
│ │ --depth 1 │ │ local vs server │ │
│ └─────┬──────┘ └──────────┬──────────┘ │
│ │ │ │
│ │ ┌───────┴───────┐ │
│ │ │ │ │
│ │ ▼ ▼ │
│ │ ┌──────────┐ ┌──────────────┐ │
│ │ │ 一致 │ │ 不一致 │ │
│ │ │ 直接使用 │ │ │ │
│ │ └────┬─────┘ └───────┬──────┘ │
│ │ │ │ │
│ │ │ ▼ │
│ │ │ ┌──────────────────┐ │
│ │ │ │ git fetch origin │ │
│ │ │ │ git checkout │ │
│ │ │ │ <commit_hash> │ │
│ │ │ └────────┬─────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 返回本地模板目录路径 │ │
│ │ /opt/xingrin/nuclei-repos/<repo-name>/ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 执行 nuclei 扫描 │ │
│ │ nuclei -t /opt/xingrin/nuclei-repos/xxx/ -l targets.txt │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────┘
```
## 五、版本一致性保证
- Server 同步时记录 `commit_hash`
- Worker 使用前检查本地 hash 是否与 Server 一致
- 不一致时自动同步到指定 commit
- 确保所有节点使用相同版本的模板
## 六、配置项
`docker/.env` 或环境变量中配置:
```bash
# Nuclei 模板仓库根目录
NUCLEI_TEMPLATES_REPOS_BASE_DIR=/opt/xingrin/nuclei-repos
```
## 七、常见问题
### Q: Worker 报错「未找到模板仓库」?
A: 需要先在 Server 端添加并同步模板仓库Worker 通过数据库查询仓库信息。
### Q: 如何添加自定义模板仓库?
A: 在前端「Nuclei 模板」页面点击添加,填写仓库名称和 Git URL然后点击同步即可。
### Q: 模板更新后 Worker 如何获取最新版本?
A: 在 Server 端点击「同步」更新模板Worker 下次执行扫描时会检测到 commit hash 不一致并自动同步。