flaviomilan/fackel

GitHub: flaviomilan/fackel

一个由 LangGraph ReAct Agent 驱动的自主渗透测试框架,集成 OSINT 侦察、端口扫描、漏洞检测与报告生成的全流程能力。

Stars: 3 | Forks: 0

# Fackel

Fackel logo

由 ReAct agents 驱动的自主渗透测试框架。
LLM 驱动的侦察、扫描、分类和报告生成。

Python 3.12+ License: Apache 2.0 LangGraph

## 什么是 Fackel? Fackel 是一个多 Agent 渗透测试框架,其中 **LLM 决定做什么,而不是 硬编码的流水线**。每个专家 Agent 都使用 [ReAct](https://arxiv.org/abs/2210.03629) 模式(Reason + Act)来自主 选择调用哪些工具、解释结果并决定下一步。 ``` Target → OSINT → Approval Gate → Port Scan → Vuln Scan → Triage → Report ↕ ↕ ↕ ↕ ↕ ↕ 27 tools Human-in- 2 tools 12 tools LLM-as- LLM (passive) the-Loop (active) (active) a-judge synthesis ``` ### 主要特性 | 特性 | 描述 | |---------|-------------| | **真正的 ReAct agents** | 每个专家都是一个拥有自己系统提示、工具和 LLM 的 `create_agent`。模型决定策略,而不是代码。 | | **5 阶段流水线** | OSINT → 端口扫描 → 漏洞扫描 → 分类 → 报告。每个阶段建立在前一个阶段之上。 | | **Human-in-the-loop** | 在主动扫描之前,审批关卡会暂停并显示发现的目标供操作员审查。 | | **LLM-as-a-judge** | 质量评估器对每个阶段进行评分,并驱动自适应路由——跳过空阶段,针对部分结果调整策略。 | | **实时可观测性** | 工具调用、结果、错误和 LLM 推理过程在发生时实时流式传输到终端。 | | **输入验证护栏** | 每个工具都通过 `guard_target()` 验证其输入(目标类型、shell 元字符)——通过 `ToolException` 进行代码级强制执行,而不仅仅是提示指令。 | | **弹性工具执行** | `ToolException` + `handle_tool_error` 将清晰的错误传播给 LLM。熔断器在重复失败后禁用不稳定的 HTTP 服务。通过环境变量可配置每个工具的超时。 | | **Per-agent 模型配置** | 通过环境变量为不同的 Agent 分配不同的模型。 | | **自动提供者门控** | 当 API 密钥缺失时,需要密钥的工具会被自动移除,防止浪费 LLM 调用。 | | **双层提示** | 共享的核心提示(身份 + 反幻觉规则)+ 每阶段特定的任务技能提示。 | | **双重报告** | 控制台上的简洁 LLM 报告 + 保存到磁盘的综合归档报告。 | | **LangSmith 追踪** | 设置两个环境变量,所有 Agent 阶段都会显示为分层追踪——Token 使用情况、工具 I/O、延迟、中间件活动。 | ## 快速开始 ### 需求 | 需求 | 备注 | |-------------|-------| | Python 3.12+ | 必需 | | [`uv`](https://docs.astral.sh/uv/) 或 `pip` | 包管理器 | | OpenAI API key | 或任何兼容的提供商(Azure, Anthropic via LangChain) | | Go ≥ 1.21 | 用于大多数扫描二进制文件(可选——仅主动扫描需要) | | Ruby (gem) | 用于 `wpscan`, `whatweb`(可选) | | `naabu`, `nmap` | 用于端口扫描(主动扫描) | | `nuclei`, `httpx`, `katana`, `subfinder` | 用于漏洞扫描(可选) | 请参阅 [docs/tools.md](docs/tools.md) 获取每个工具所需二进制文件的完整列表。 #### 自动化工具安装 ``` # 自动安装所有外部二进制文件 ./scripts/install-tools.sh # 仅核心工具 (nmap, naabu, nuclei, httpx, subfinder) ./scripts/install-tools.sh --minimal # 审计 — 检查已安装/缺失的工具 ./scripts/install-tools.sh --check ``` ### 安装 ``` # 克隆并安装 git clone https://github.com/your-org/fackel.git cd fackel uv sync --python 3.12 ``` 或使用 pip: ``` python -m venv .venv && source .venv/bin/activate pip install -e . ``` ### 配置 ``` cp .env.example .env # 编辑 .env — OPENAI_API_KEY 是唯一必需的 key ``` ### 运行 ``` # 被动扫描 (仅 OSINT → 报告) fackel example.com --no-active-scan # 全面扫描 (OSINT → 端口扫描 → 漏洞扫描 → 分类筛选 → 报告) fackel example.com # 详细模式 — 实时查看 LLM 推理过程 fackel example.com -v # 将报告保存到特定文件 fackel example.com -o report.md # 检查已配置的 provider API keys fackel example.com --check-providers --no-active-scan ``` ## 流水线概览 ``` ┌─────────────────┐ │ osint_node │ ← 27 passive tools │ (ReAct agent) │ dns, whois, subdomains, etc. └────────┬────────┘ │ ┌─────────▼──────────┐ │ route_after_osint │ │ (conditional) │ └──┬─────────────┬───┘ │ │ active_scan │ │ no active scan + IPs found │ │ or no IPs ▼ │ ┌─────────────────┐ │ │ approval_gate │ │ │ (HitL interrupt)│ │ └───┬────────┬────┘ │ approve │ │ reject │ ▼ └────┐ │ ┌────────────┐ │ │ │ port_scan │ │ │ │ (ReAct) │ │ │ └─────┬───────┘ │ │ │ │ │ ┌─────────▼───────────┐ │ │ │route_after_port_scan│ │ │ │(LLM-as-a-judge) │ │ │ └──┬──────────────┬───┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌────────────┐ ┌─────────┐ │ │ │ vuln_scan │ │ triage │ │ │ │ (ReAct) │ │(struct) │◄ │ └─────┬──────┘ └────┬────┘ │ │ │ │ ▼ │ │ ┌──────────┐ │ │ │ triage │ │ │ │ (struct) │ │ │ └─────┬────┘ │ │ │ │ │ ▼ ▼ ▼ ┌──────────────────────────────────┐ │ report_node │ │ (LLM synthesis) │ └──────────────┬───────────────────┘ │ END ``` 每个阶段都是一个 LangGraph 节点。编排器管理状态流、 条件路由,并累积各阶段的发现结果。 请参阅 [docs/architecture.md](docs/architecture.md) 获取完整的架构细节。 ## CLI 输出 标准模式显示工具调用和结果: ``` Target: eversafe.info Active scan: yes ──────────────────────────────────────────────────────────── ▶ OSINT ──────────────────────────────────────────────────────────── 🔧 dns_resolve(target=eversafe.info) 🔧 whois_lookup(domain=eversafe.info) 🔧 subfinder_enum(domain=eversafe.info, all_sources=True) 🔧 crtsh_subdomain_enum(domain=eversafe.info) ✓ OSINT complete ──────────────────────────── ▶ Approval ──────────────────── ╭──────────────── ⚠ Approval Required ─────────────────────╮ │ OSINT found 4 IP(s) and 5 subdomain(s). │ │ Proceed with active scanning? │ ╰──────────────────────────────────────────────────────────╯ Approve? [Y/n]: y ──────────────────────────────────────────────────────────── ▶ Port Scan ──────────────────────────────────────────────────────────── 🔧 naabu_scan(host=104.21.36.250, top_ports=1000) 🔧 nmap_port_scan(host=104.21.36.250, ports=80,443) 📊 Quality: complete (score: 0.9) → proceed ✓ Port Scan complete ──────────────────────────────────────────────────────────── ▶ Vuln Scan ──────────────────────────────────────────────────────────── 🔧 nuclei_scan(target=eversafe.info) 🔧 httpx_scan(domain=eversafe.info, tech_detect=True) 🔧 wafw00f_detect(target=eversafe.info) 📊 Quality: complete (score: 0.85) → proceed ✓ Vuln Scan complete ════════════════════════════════════════════════════════════ # eversafe.info 渗透测试报告 ... Completed in 220.9s ``` 使用 `-v`(详细模式),LLM 推理也会显示: ``` 💭 ### Structured Summary 💭 **Domain:** eversafe.info 💭 **Discovered IP Addresses:** 💭 - 104.21.36.250 💭 - 172.67.201.157 ``` ## 专家 Agents | Agent | 类型 | 工具 | 目的 | |-------|------|-------|---------| | **OSINT** | ReAct | 27 工具 | 被动侦察——DNS, WHOIS, 子域名 (subfinder, crt.sh, VirusTotal, Amass), 反向 DNS, Shodan/Censys/FOFA, IP 富化, TLS 证书, 历史 DNS, 被动 URL 发现 (gau), 云资源枚举 (CloudBrute), Web 技术指纹识别 (WhatWeb), 参数发现 (ParamSpider), JS 端点提取 (LinkFinder), 子域名接管 (Subzy), 机密扫描 (TruffleHog), 职位搜索, 邮件分析 | | **Port Scan** | ReAct | 2 工具 | 主动扫描——发现开放端口 (`naabu`) 和指纹服务 (`nmap`) | | **Vuln Scan** | ReAct | 12 工具 | 漏洞扫描——Nuclei 模板, XSS 检测 (DalFox), HTTP 技术检测, WAF 检测, Web 爬取, S3 存储桶审计, TLS 分析, WordPress 扫描 (WPScan), CORS 错误配置 (Corsy) | | **Triage** | Structured LLM | *(无)* | 差距分析——识别发现但未评估的技术,标记覆盖缺口 | | **Report** | LLM chain | *(无)* | 将所有发现、评估和缺口综合成 Markdown 渗透测试报告 | | **Judge** | Structured LLM | *(无)* | 质量评估器——对每个阶段评分(0.0–1.0)并推荐路由 | 请参阅 [docs/agents.md](docs/agents.md) 获取详细的 Agent 文档。 ## 工具清单 | 工具 | 目标类型 | 依赖项 | Agent | |------|------------|----------|-------| | `dns_resolve` | HOST | — | OSINT | | `whois_lookup` | DOMAIN | `whois` binary | OSINT | | `shodan_lookup` | *(custom)* | `SHODAN_API_KEY` | OSINT | | `censys_lookup` | HOST | `CENSYS_API_ID` + `CENSYS_API_SECRET` | OSINT | | `dnsdumpster_lookup` | DOMAIN | — | OSINT | | `virustotal_subdomain_enum` | DOMAIN | `VIRUSTOTAL_API_KEY` | OSINT | | `crtsh_subdomain_enum` | DOMAIN | — | OSINT | | `subfinder_enum` | DOMAIN | `subfinder` binary | OSINT | | `reverse_dns_lookup` | IP | — | OSINT | | `ipinfo_lookup` | IP | — | OSINT | | `bgp_lookup` | IP | — | OSINT | | `httpx_scan` | HOST_OR_URL | `httpx` binary | OSINT, Vuln Scan | | `tlscert_lookup` | DOMAIN | — | OSINT | | `securitytrails_history` | DOMAIN | `SECURITYTRAILS_API_KEY` | OSINT | | `urlscan_search` | DOMAIN | — | OSINT | | `otx_passive_dns` | DOMAIN | `OTX_API_KEY` | OSINT | | `fofa_search` | *(custom)* | `FOFA_EMAIL` + `FOFA_KEY` | OSINT | | `gau_urls` | DOMAIN | `gau` binary | OSINT | | `cloudbrute_enum` | *(keyword)* | `cloudbrute` binary | OSINT | | `job_search` | *(free text)* | — | OSINT | | `analyze_email` | *(email)* | `HIBP_API_KEY` / `EMAILREP_API_KEY` | OSINT | | `naabu_scan` | HOST | `naabu` binary | Port Scan | | `nmap_port_scan` | HOST | `nmap` binary | Port Scan | | `nuclei_scan` | DOMAIN | `nuclei` binary | Vuln Scan | | `wafw00f_detect` | HOST_OR_URL | `wafw00f` binary | Vuln Scan | | `graphql_scan` | URL | — | Vuln Scan | | `feroxbuster_scan` | HOST_OR_URL | `feroxbuster` binary | Vuln Scan | | `katana_crawl` | HOST_OR_URL | `katana` binary | Vuln Scan | | `testssl_scan` | HOST | `testssl.sh` binary | Vuln Scan | | `dalfox_scan` | HOST_OR_URL | `dalfox` binary | Vuln Scan | | `s3scanner_scan` | *(bucket name)* | `s3scanner` binary | Vuln Scan | | `extract_webpage_content` | URL | — | Vuln Scan | | `amass_enum` | DOMAIN | `amass` binary | OSINT | | `subzy_check` | DOMAIN | `subzy` binary | OSINT | | `paramspider_crawl` | DOMAIN | `paramspider` binary | OSINT | | `whatweb_scan` | HOST_OR_URL | `whatweb` binary | OSINT | | `linkfinder_extract` | HOST_OR_URL | `linkfinder` binary | OSINT | | `trufflehog_scan` | *(repo URL)* | `trufflehog` binary | OSINT | | `wpscan_scan` | HOST_OR_URL | `wpscan` binary + `WPSCAN_API_TOKEN` | Vuln Scan | | `corsy_scan` | HOST_OR_URL | `corsy` binary | Vuln Scan | 请参阅 [docs/tools.md](docs/tools.md) 获取包含输入 Schema 和验证规则的完整工具参考。 ## 配置 ### 每个Agent的模型 每个 Agent 从环境变量读取其模型,回退到 `gpt-5-mini`: | 变量 | Agent | 默认值 | |----------|-------|---------| | `FACKEL_MODEL_OSINT` | OSINT agent | `gpt-5-mini` | | `FACKEL_MODEL_PORT_SCAN` | Port scan agent | `gpt-5-mini` | | `FACKEL_MODEL_VULN_SCAN` | Vuln scan agent | `gpt-5-mini` | | `FACKEL_MODEL_TRIAGE` | Triage agent | `gpt-5-mini` | | `FACKEL_MODEL_REPORT` | Report generator | `gpt-5-mini` | | `FACKEL_MODEL_JUDGE` | Phase quality evaluator | `gpt-5-mini` | ``` # 使用更强大的模型生成报告 export FACKEL_MODEL_REPORT=gpt-4o ``` ### API 密钥 | 变量 | 必需 | 使用者 | |----------|----------|---------| | `OPENAI_API_KEY` | **是** | 所有 Agents (LLM) | | `SHODAN_API_KEY` | 否 | `shodan_lookup` | | `VIRUSTOTAL_API_KEY` | 否 | `virustotal_subdomain_enum` | | `CENSYS_API_ID` / `CENSYS_API_SECRET` | 否 | `censys_lookup` | | `FOFA_EMAIL` / `FOFA_KEY` | 否 | `fofa_search` | | `SECURITYTRAILS_API_KEY` | 否 | `securitytrails_history` | | `OTX_API_KEY` | 否 | `otx_passive_dns` | | `HIBP_API_KEY` | 否 | `analyze_email` (优雅降级) | | `EMAILREP_API_KEY` | 否 | `analyze_email` (优雅降级) | | `WPSCAN_API_TOKEN` | 否 | `wpscan_scan` | 缺少 API 密钥(且 `hard_fail=True`)的工具会从 Agents 中**自动移除**, 防止 LLM 尝试注定失败的调用。 ### 基础设施(可选) ``` # 启动 MongoDB 持久化栈 docker compose up -d ``` `docker-compose.yml` 提供: - **MongoDB 7** — 扫描持久化和查询系统 ### 可观测性(可选) Fackel 使用 **LangSmith** 进行 LLM 可观测性。设置环境变量,所有 Agent 追踪将自动出现: ``` export LANGSMITH_TRACING=true export LANGSMITH_API_KEY=lsv2_pt_... export LANGSMITH_PROJECT=fackel ``` 请参阅 [docs/configuration.md](docs/configuration.md) 获取完整的配置参考。 ## Python API ``` from fackel.agents.orchestrator import run # 阻塞模式 — 返回最终状态 result = run("example.com", active_scan=True) print(result["report"]) ``` ## 添加新工具 1. 在 `src/tools/` 中创建一个新文件,包含一个带 `@tool` 装饰器的函数和 Pydantic 输入 Schema: ``` # src/tools/recon/my_tool.py from langchain_core.tools import ToolException, tool from pydantic import BaseModel, Field from fackel.tooling import TargetType, format_tool_output, guard_target class MyToolInput(BaseModel): target: str = Field(description="Domain or IP to scan.") @tool(args_schema=MyToolInput) def my_recon_tool(target: str) -> dict: """Describe what this tool does — the LLM reads this docstring.""" target = guard_target(target, "my_recon_tool", TargetType.HOST) # guard_target raises ToolException on invalid input # ... implementation ... return format_tool_output("my_recon_tool", target, "success", data=result) # 启用 LangChain 错误传播 — LLM 将错误视为工具结果。 my_recon_tool.handle_tool_error = True # type: ignore[attr-defined] ``` 2. 导入并将其添加到相关 Agent 的工具列表中。 3. LLM 将根据其文档字符串和 Agent 的系统提示, 自主决定何时以及如何使用它。 请参阅 [docs/development.md](docs/development.md) 获取完整的开发指南。 ## 项目结构 ``` src/ ├── cli/ │ └── main.py # Typer CLI with real-time Rich rendering ├── fackel/ │ ├── agents/ │ │ ├── config.py # build_llm(), get_model(), default_middleware() │ │ ├── prompts/ │ │ │ ├── __init__.py # Prompt loader with caching │ │ │ ├── soul.md # Shared agent identity + rules │ │ │ └── skills/ │ │ │ ├── osint.md # OSINT playbook │ │ │ ├── port_scan.md # Port scan strategy │ │ │ ├── vuln_scan.md # Vuln scan playbook │ │ │ ├── triage.md # Coverage gap analysis │ │ │ ├── report.md # Report writing rules │ │ │ └── judge.md # Quality scoring guide │ │ ├── orchestrator/ │ │ │ ├── state.py # ScanState (TypedDict + reducers) │ │ │ ├── graph.py # StateGraph + SqliteSaver checkpointer │ │ │ ├── streaming.py # Dual-mode agent streaming + HITL │ │ │ ├── evaluator.py # LLM-as-a-judge quality scoring │ │ │ ├── extractors.py # IP/subdomain/fingerprint extraction │ │ │ ├── main.py # Public API: run() │ │ │ └── nodes/ # Graph node functions │ │ │ ├── osint.py # OSINT node + quality-gated retry │ │ │ ├── port_scan.py # Port scan node + evaluator │ │ │ ├── vuln_scan.py # Vuln scan node + evaluator │ │ │ ├── triage.py # Triage node │ │ │ └── report_and_gates.py # Report node + approval gate │ │ ├── osint/agent.py # OSINT ReAct agent (27 tools) │ │ ├── port_scan/agent.py # Port scan ReAct agent (2 tools) │ │ ├── vuln_scan/agent.py # Vuln scan ReAct agent (12 tools) │ │ ├── triage/agent.py # Triage structured output │ │ └── report/agent.py # Report synthesis │ ├── tooling/ │ │ ├── validators.py # guard_target() (raises ToolException) │ │ ├── execution.py # run_command, require_binary, get_tool_timeout │ │ ├── sanitizers.py # Input sanitisation helpers │ │ ├── ip_classifier.py # IP classification (CDN, cloud, hosting) │ │ └── ddgs.py # DuckDuckGo search wrapper │ ├── provider_keys.py # API key gating + tool filtering │ └── report_writer.py # Full archival report builder └── tools/ ├── circuit_breaker.py # Per-service circuit breaker ├── recon/ # 22 passive reconnaissance tools ├── osint/ # 3 open-source intelligence tools ├── scanning/ # 7 active scanning tools └── vuln/ # 5 vulnerability assessment tools ``` ## 文档 | 文档 | 描述 | |----------|-------------| | [docs/architecture.md](docs/architecture.md) | 系统架构、图流程、状态管理、提示系统 | | [docs/agents.md](docs/agents.md) | Agent 规范、提示、LLM-as-a-judge 评估器 | | [docs/tools.md](
标签:AI安全, Chat Copilot, CTI, ESC4, FTP漏洞扫描, GitHub, LangGraph, OSINT, Petitpotam, Python, ReAct模式, 人机交互, 反取证, 安全编排, 安全评估, 实时处理, 密码管理, 情报分析, 插件系统, 数据统计, 无后门, 智能研判, 端口扫描, 网络安全, 网络诊断, 自主智能体, 自动化攻击模拟, 自动化渗透, 逆向工具, 隐私保护