# 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 │ │ │ │ │ │ │ │ │ └──────────┬──────────┘ └──────────┬──────────┘ │ │ │ │ │ │ └──────────────┬─────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 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 ` 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 │ │ │ │ │ │ │ │ │ │ │ └────────┬─────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 返回本地模板目录路径 │ │ │ │ /opt/xingrin/nuclei-repos// │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 执行 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 不一致并自动同步。