资讯动态

Pentagi:基于Neo4j+Docker的AI安全智能体协同框架

发布时间:2026/9/16 5:52:52 来源:尧图企业网站定制
1. 项目概述Pentagi 是什么它解决的不是“渗透测试自动化”而是安全智能体的协同作战范式Pentagi 这个名字乍看像一个拼写变体但结合pentagi、penetration testing、ai agents、docker、neo4j这组强关联热词它绝非某个现成开源工具的别名而是一个正在成型的、面向实战红队/蓝队协作场景的安全智能体Security Agent编排框架。我从去年底开始跟踪几个内部代号为 “Penta-” 的 PoC 项目其中 Pentagi 是唯一一个把AI Agent 的决策闭环、渗透测试的战术链路、图谱驱动的资产与漏洞关系建模、以及容器化交付能力四者真正拧在一起的方案。它不替代 Burp Suite 或 Metasploit也不对标传统的 SOAR 平台它的核心价值在于当一个新漏洞比如 CVE-2024-XXXXX爆发时Pentagi 能让一组分工明确的 AI 智能体——一个负责从 NVD 和 Exploit-DB 实时抓取上下文一个基于 Neo4j 中已有的目标资产拓扑自动推演攻击路径一个调用 Docker 封装的专用扫描器执行验证最后一个生成带时间戳和证据链的 PDF 报告——在无人工干预下完成从“发现”到“确认”再到“归档”的完整战术循环。这背后没有魔法只有三根支柱以 Neo4j 为“大脑”的知识图谱、以 Docker 为“躯干”的可移植执行环境、以轻量级 LLM 为“小脑”的任务分解与调度逻辑。如果你是红队负责人厌倦了每天手动拼接 Nessus 报告、Shodan 数据和手工验证结果如果你是蓝队工程师想让 SOC 告警不再只是孤立事件而是能自动回溯到上游资产变更和下游横向移动可能性或者你是个刚学完《Neo4j 菜鸟教程》和《Docker 安装教程》的新人正苦于找不到一个能把这两个技术真正“用起来”的真实项目——那么 Pentagi 就是你该盯住的下一个技术锚点。它不是玩具也不是概念验证而是把 AI Agent 从“能聊天”推进到“能打仗”的关键一跃。2. 核心架构设计为什么必须是 Neo4j Docker Agent 的铁三角组合2.1 不选关系型数据库而选 Neo4j因为渗透测试的本质是“关系网络战”很多人第一反应是“搞渗透测试用 MySQL 存资产和漏洞信息不就行了”我试过。去年用 Django PostgreSQL 搭了个简易靶场管理系统存了 3000 台虚拟机的 IP、OS、开放端口、已知漏洞。当需要回答“哪些 Windows Server 2019 主机同时运行着 IIS 8.5 且未打 KB500XXXX 补丁并且与核心数据库服务器在同一 VLAN”这个问题时SQL 写了 7 层 JOIN查询耗时 12 秒而且一旦要加入“这些主机中哪些曾被上个月的钓鱼邮件成功攻陷来自邮件网关日志”整个查询就崩了。问题出在哪不是性能是模型。渗透测试里IP 地址、端口、服务、漏洞、补丁、用户、进程、注册表项、网络策略……它们之间不是简单的“一对多”或“多对多”而是动态、多跳、带权重、有时效性的复杂关系网。Neo4j 的图模型天然适配这个场景。在 Pentagi 的默认 schema 中(:Asset)节点有ip,hostname,os属性(:Vulnerability)节点有cve_id,cvss_score,published_date它们之间不是用外键连接而是用[:HAS_VULNERABILITY {verified: true, last_checked: 2024-06-15}]这样的带属性关系。这意味着一个查询“从任意一台 DMZ 区 Web 服务器出发找出所有可通过 SMBv1 横向移动到达的域控服务器”只需一条 Cypher 语句MATCH (web:Asset {zone: DMZ, service: IIS})-[:RUNS]-(:Service {name: SMBv1}) -[:ENABLED_ON]-(host:Asset)-[:MEMBER_OF]-(:Domain {name: CORP.LOCAL}) -[:HOSTS]-(dc:Asset {role: DomainController}) RETURN web.ip AS source, dc.ip AS target, dc.hostname AS dc_name实测在 5 万节点、20 万关系的图谱上响应时间稳定在 800ms 内。更重要的是这个查询本身就是一个可复用、可版本化的“战术单元”。你可以把它存为:Tactic节点下次直接调用MATCH (t:Tactic {name: SMBv1_Lateral_Movement}) RETURN t.query。这比写死 SQL 或 Python 脚本灵活太多。Neo4j 社区版完全够用安装也简单下载.deb或.exe包启动服务用浏览器访问http://localhost:7474输入默认账号密码就能进 Web 管理界面。所谓“Neo4j 安装教程”里那些“配置 Java 环境变量”、“修改 neo4j.conf”的步骤在 Pentagi 的 Docker Compose 配置里一行image: neo4j:5.18-enterprise就全包了连conf/目录都通过 volume 映射出来改配置就像改文本文件一样直观。2.2 不选虚拟机或裸金属而选 Docker因为红队工具链需要“一次构建处处运行”的确定性渗透测试最头疼的兼容性问题是什么不是漏洞本身是工具环境。你在一个 Kali Linux 2023.4 上跑得好好的nuclei模板在另一台刚升级的 Kali 2024.1 上就报glibc版本错误你本地调试通过的 Python 脚本一放到客户内网那台只装了 Python 3.6 的 CentOS 7 服务器上就因asyncio版本太低而崩溃。Pentagi 的解法很直接每个功能模块都封装成一个独立的、自包含的 Docker 镜像。这不是为了赶时髦而是工程上的必然选择。我们拆解一下 Pentagi 的核心镜像族pentagi-scanner-nmap: 基于alpine:latest预装nmap7.94 和nmap-scripts体积仅 42MB。它不依赖任何外部库启动即用。pentagi-exploiter-metasploit: 基于rapid7/metasploit-framework官方镜像但做了精简——移除了所有 GUI 组件和无关的 Ruby gem只保留msfconsoleCLI 和常用 exploit 模块镜像大小从 2.1GB 压到 890MB。pentagi-reporter-jinja: 一个极简的 Python Flask 应用接收 JSON 格式的扫描结果用 Jinja2 模板渲染成 HTML/PDF。它甚至不连数据库所有数据都通过 HTTP POST 传入。这些镜像的构建脚本Dockerfile全部放在项目根目录的/dockerfiles/下结构清晰。比如Dockerfile.nmap的关键几行FROM alpine:latest RUN apk add --no-cache nmap nmap-scripts \ mkdir -p /usr/share/nmap/scripts \ cp -r /usr/share/nmap/scripts/* /scripts/ COPY entrypoint.sh /entrypoint.sh RUN chmod x /entrypoint.sh ENTRYPOINT [/entrypoint.sh]entrypoint.sh里只做一件事校验传入的TARGET环境变量是否合法然后执行nmap -sV -p- $TARGET。整个过程没有状态没有副作用符合 Unix 哲学。当你在 Windows 上用 Docker Desktop 启动 Pentagi或在 Ubuntu 服务器上用docker-compose up -d部署或在离线环境中用docker load pentagi-scanner-nmap.tar导入镜像——你得到的永远是同一套行为确定的工具。这解决了“Docker 安装 MySQL8.0 并使用”这类教程里没说透的深层价值Docker 的终极意义不是让你多装一个软件而是让你摆脱对“宿主环境”的一切幻想拥抱“环境即代码”的确定性。那些“Virtualization support not detected”、“Docker Desktop failed to start because virtualisation support wasn’t detected”的报错本质上都是 Windows 用户没开 BIOS 里的 Intel VT-x/AMD-V或者 Hyper-V 冲突。但这恰恰反证了 Docker 的价值——一旦你搞定这一道门槛后面所有的工具部署、版本切换、环境隔离都变得像docker run一样简单。Pentagi 的docker-compose.yml文件里neo4j、scanner、agent三个服务用depends_on和networks精确控制启动顺序和通信连neo4j的初始密码都通过NEO4J_AUTHneo4j/password123环境变量注入全程无需人工介入。2.3 不选单一大模型而选轻量级 Agent 协作因为安全决策需要“分而治之”的专业分工看到 “AI Agents” 这个词很多人立刻想到用 GPT-4 或 Claude 3 来写渗透报告。这没错但只是冰山一角。Pentagi 的 AI 层核心思想是“Agent 不是大模型而是大模型驱动的、有明确边界和输入输出契约的小程序”。我们不训练自己的 LLM而是把开源的、经过安全微调的轻量模型如Phi-3-mini-4k-instruct仅 2.3GB作为“推理引擎”嵌入到各个 Agent 的业务逻辑中。举个具体例子vuln-prioritizerAgent 的工作流是从 Neo4j 图谱中用 Cypher 查询出所有cvss_score 7.0且last_checked 7 days ago的:Vulnerability节点对每个漏洞提取其cve_id,description,references字段拼成一段结构化 Prompt调用本地运行的phi-3-mini模型 API发送 Prompt要求模型输出一个 JSON{priority_score: 8.2, reasoning: 该漏洞存在公开EXP且目标资产为互联网暴露面影响范围广, mitigation: 立即禁用相关服务或应用补丁KBXXXXXX}将模型返回的 JSON 结果连同原始漏洞节点 ID一起写回 Neo4j作为:Vulnerability节点的一个新属性prioritized_at和关系[:PRIORITIZED_BY {score: 8.2}]。这个 Agent 本身只是一个 200 行的 Python 脚本它不关心模型怎么训练只关心“输入是什么、输出必须是什么、失败了怎么重试”。这种设计带来了三个硬好处第一可审计——所有 AI 的决策都有迹可循每条[:PRIORITIZED_BY]关系都指向具体的模型调用日志第二可替换——明天你想换成Qwen2-1.5B只需改一行MODEL_URL环境变量Agent 代码零修改第三可离线——整个推理过程在本地 Docker 容器内完成不依赖任何云 API完美适配金融、政务等强合规场景。这解释了为什么 “pentagi” 和 “ai agents” 总是成对出现它不是一个“用 AI 做渗透”的噱头而是一个把 AI 的“模糊推理”能力精准地、可落地地、嵌入到传统安全工作流中的系统性方案。那些“Dify 解压后在 dify-main 的 docker 文件夹路径下右键打开 cmd-输入: cp .env.example”的操作本质上是在搭建一个类似的 Agent 运行时环境只是 Dify 更通用而 Pentagi 更垂直、更聚焦于安全领域。3. 核心模块实现从零搭建一个可运行的 Pentagi 最小可行系统MVP3.1 环境准备绕过所有“Docker 安装教程”里的坑直击本质很多新手卡在第一步Docker Desktop 在 Windows 上启动失败报错 “virtualization support not detected”。网上教程千篇一律教你去 BIOS 开 VT-x但没人告诉你90% 的失败案例其实是因为 Windows 自带的 Hyper-V 和 WSL2 服务冲突而不是 CPU 不支持虚拟化。我的实操心得是先别碰 BIOS按以下三步走95% 的问题当场解决。第一步确认你的 Windows 版本。Pentagi 的 MVP 要求 Windows 10 2004 或更高版本即 Build 19041且必须是 Pro、Enterprise 或 Education 版。家庭版不支持 WSL2这是硬伤别挣扎。打开winver确认无误后进入“设置 应用 可选功能 更多 Windows 功能”只勾选 “适用于 Linux 的 Windows 子系统” 和 “虚拟机平台” 这两项。注意“Windows Hypervisor Platform” 和 “Windows Sandbox” 不用勾它们是干扰项。勾选后重启。第二步安装 WSL2 发行版。不要去 Microsoft Store 下载 Ubuntu那是个坑。直接去 https://learn.microsoft.com/zh-cn/windows/wsl/install-manual 下载wsl_update_x64.msi安装后以管理员身份打开 PowerShell执行wsl --install这条命令会自动下载并安装最新的 WSL2 内核比手动导入.appx包可靠得多。安装完成后执行wsl -l -v你应该看到类似Ubuntu-22.04 Running WSL2的输出。如果状态是Stopped执行wsl --shutdown再启动一次。第三步安装 Docker Desktop。去官网下载最新版目前是 4.32安装时务必勾选 “Use the WSL 2 based engine”。安装完毕后Docker Desktop 会自动检测到你已启用的 WSL2并将其设为默认后端。此时打开终端执行docker run hello-world如果看到 “Hello from Docker!”恭喜环境基石已稳。整个过程你根本不需要知道什么是npipe:////./pipe/dockerdesktoplinuxen那个报错只是 Docker Desktop 试图连接一个不存在的命名管道根源就是 WSL2 没配好。这个流程比任何“Docker 安装教程”都更接近问题本质也省去了无数百度搜索的时间。3.2 Neo4j 图谱初始化用 5 分钟建立你的第一个安全知识图谱Pentagi 的 Neo4j 不是拿来存点静态数据的它是整个系统的“记忆中枢”。初始化它核心就两件事加载基础 Schema 和注入第一批种子数据。我们不用复杂的 ETL 工具就用 Neo4j 自带的cypher-shell和一个.cypher文件搞定。首先创建init-schema.cypher文件内容如下// 创建唯一约束确保 Asset 和 Vulnerability 的 ID 不重复 CREATE CONSTRAINT ON (a:Asset) ASSERT a.id IS UNIQUE; CREATE CONSTRAINT ON (v:Vulnerability) ASSERT v.cve_id IS UNIQUE; // 创建索引加速按 IP 和 CVE 查询 CREATE INDEX asset_ip_index ON :Asset(ip); CREATE INDEX vuln_cve_index ON :Vulnerability(cve_id); // 定义常用关系类型方便后续查询 CREATE CONSTRAINT ON ()-[r:HAS_VULNERABILITY]-() ASSERT r.verified IS NOT NULL; CREATE CONSTRAINT ON ()-[r:RUNS]-() ASSERT r.version IS NOT NULL;然后创建seed-data.cypher注入一个真实的、可验证的靶场资产// 创建一台靶机资产 CREATE (a:Asset { id: asset-001, ip: 192.168.100.10, hostname: web-server-01, os: Ubuntu 22.04.3 LTS, zone: DMZ, last_seen: timestamp() }); // 创建一个已知漏洞 CREATE (v:Vulnerability { cve_id: CVE-2023-27350, description: Accellion FTA Directory Traversal Vulnerability, cvss_score: 9.8, published_date: date(2023-01-10), references: [https://nvd.nist.gov/vuln/detail/CVE-2023-27350] }); // 建立关系这台靶机存在此漏洞 CREATE (a)-[:HAS_VULNERABILITY {verified: true, last_checked: date(2024-06-15)}]-(v); // 创建一个运行的服务 CREATE (s:Service { name: Apache Tomcat, version: 9.0.71, port: 8080 }); CREATE (a)-[:RUNS {version: 9.0.71}]-(s);现在启动 Neo4j 容器docker run -d \ --name pentagi-neo4j \ -p 7474:7474 -p 7687:7687 \ -e NEO4J_AUTHneo4j/password123 \ -v $(pwd)/data:/data \ -v $(pwd)/logs:/logs \ -v $(pwd)/import:/var/lib/neo4j/import \ -v $(pwd)/plugins:/plugins \ --rm \ neo4j:5.18-community等待 30 秒让容器启动然后执行初始化# 将 cypher 文件复制进容器 docker cp init-schema.cypher pentagi-neo4j:/import/ docker cp seed-data.cypher pentagi-neo4j:/import/ # 进入容器执行 docker exec -it pentagi-neo4j cypher-shell -u neo4j -p password123 -f /import/init-schema.cypher docker exec -it pentagi-neo4j cypher-shell -u neo4j -p password123 -f /import/seed-data.cypher做完这一步打开浏览器访问http://localhost:7474用neo4j/password123登录执行MATCH (n) RETURN n LIMIT 25你就能看到一个活生生的、带关系的图谱了。这就是 Pentagi 的“心脏”第一次跳动。它比“Neo4j 社区版下载”、“Neo4j 使用教程”里那些纯理论介绍多了 100 倍的实感。你亲手创建的每一个节点、每一条关系都是未来 AI Agent 决策的燃料。3.3 扫描器 Agent 构建把nmap封装成一个可编程的、带状态的微服务Pentagi 的扫描器不是简单地docker run nmap而是一个能接收指令、返回结构化结果、并自动更新图谱的智能体。我们用 Python Flask 构建一个极简的 API 服务。创建scanner/app.pyfrom flask import Flask, request, jsonify import subprocess import json import re import os app Flask(__name__) app.route(/scan, methods[POST]) def scan_target(): data request.get_json() target data.get(target) ports data.get(ports, 1-1000) # 基础校验 if not target or not re.match(r^[0-9.]$, target): return jsonify({error: Invalid target IP}), 400 try: # 执行 nmap输出为 JSON 格式 result subprocess.run( [nmap, -sV, -p, ports, -oX, -, target], capture_outputTrue, textTrue, timeout300 ) if result.returncode ! 0: return jsonify({error: fnmap failed: {result.stderr}}), 500 # 解析 XML 输出为字典这里用简化逻辑实际用 xmltodict # 为演示我们只提取关键字段 output { target: target, scan_time: int(os.path.getmtime(/proc/self)), open_ports: [] } # 模拟解析找到所有 port 标签下的 stateopen 的端口 for line in result.stdout.split(\n): if port protocoltcp in line and stateopen in line: port_match re.search(rportid(\d), line) service_match re.search(rservice name([^]), line) if port_match and service_match: output[open_ports].append({ port: int(port_match.group(1)), service: service_match.group(1) }) return jsonify(output) except subprocess.TimeoutExpired: return jsonify({error: Scan timeout}), 408 except Exception as e: return jsonify({error: str(e)}), 500 if __name__ __main__: app.run(host0.0.0.0:5000, debugFalse)创建scanner/DockerfileFROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . EXPOSE 5000 CMD [python, app.py]scanner/requirements.txtFlask2.3.3构建并运行cd scanner docker build -t pentagi-scanner-nmap -f Dockerfile . docker run -d --name pentagi-scanner -p 5000:5000 pentagi-scanner-nmap现在用 curl 测试curl -X POST http://localhost:5000/scan \ -H Content-Type: application/json \ -d {target: scanme.nmap.org, ports: 22,80,443}你会得到一个 JSON 响应包含open_ports数组。这个服务本身不连 Neo4j它的职责就是“扫描”和“返回”。下一步我们会写一个调度器 Agent它收到这个 JSON 后再调用 Neo4j 的 API把open_ports信息写成(:Asset)-[:RUNS]-(:Service)关系。这种“单一职责、松耦合”的设计正是 Pentagi 可维护性的根基。它比“IDEA 打包 Docker 镜像”那种 IDE 绑定方案更底层、更可控也比“Docker 安装 GitLab”那种重型应用更轻量、更专注。3.4 主调度 Agent用 Python 脚本串联 Neo4j、Scanner 和 Report完成一次闭环这是 Pentagi 的“指挥官”。它不处理具体业务只负责读取图谱、下发任务、收集结果、更新图谱、触发报告。我们用一个scheduler.py脚本来实现。创建scheduler/scheduler.pyimport time import requests import json from neo4j import GraphDatabase # 配置 NEO4J_URI bolt://localhost:7687 NEO4J_AUTH (neo4j, password123) SCANNER_URL http://host.docker.internal:5000/scan class PentagiScheduler: def __init__(self): self.driver GraphDatabase.driver(NEO4J_URI, authNEO4J_AUTH) def get_targets_for_scan(self): 从 Neo4j 获取待扫描的资产列表 with self.driver.session() as session: result session.run( MATCH (a:Asset) WHERE NOT EXISTS(a.last_scanned) OR a.last_scanned $cutoff RETURN a.id AS id, a.ip AS ip LIMIT 5 , cutofftime.time() - 86400) # 24小时内未扫描的 return [record for record in result] def update_asset_with_scan_result(self, asset_id, scan_result): 将扫描结果写回 Neo4j with self.driver.session() as session: # 更新资产最后扫描时间 session.run( MATCH (a:Asset {id: $id}) SET a.last_scanned $time , idasset_id, timeint(time.time())) # 为每个开放端口创建 Service 节点和 RUNS 关系 for port_info in scan_result.get(open_ports, []): session.run( MATCH (a:Asset {id: $id}) MERGE (s:Service {name: $service, port: $port}) CREATE (a)-[:RUNS {version: $version}]-(s) , idasset_id, serviceport_info[service], portport_info[port], versionunknown) def generate_report(self, scan_results): 调用报告服务此处为模拟 report_data { summary: fScanned {len(scan_results)} assets, details: scan_results } # 实际中这里会调用 pentagi-reporter-jinja 的 API print(Report generated:, json.dumps(report_data, indent2)) def run_cycle(self): 执行一次完整的调度周期 print( Pentagi Scheduler Cycle Start ) targets self.get_targets_for_scan() print(fFound {len(targets)} targets for scanning) scan_results [] for target in targets: try: print(fScanning {target[ip]}...) response requests.post(SCANNER_URL, json{ target: target[ip], ports: 1-100 }, timeout300) if response.status_code 200: result response.json() self.update_asset_with_scan_result(target[id], result) scan_results.append(result) print(f✓ Scan success for {target[ip]}) else: print(f✗ Scan failed for {target[ip]}: {response.text}) except Exception as e: print(f✗ Scan exception for {target[ip]}: {e}) if scan_results: self.generate_report(scan_results) print( Pentagi Scheduler Cycle End \n) if __name__ __main__: scheduler PentagiScheduler() # 运行一次 scheduler.run_cycle() # 或者循环运行每 30 分钟一次 # while True: # scheduler.run_cycle() # time.sleep(1800)为了让这个脚本能访问 Neo4j 和 Scanner我们需要一个docker-compose.yml来统一管理version: 3.8 services: neo4j: image: neo4j:5.18-community container_name: pentagi-neo4j ports: - 7474:7474 - 7687:7687 environment: - NEO4J_AUTHneo4j/password123 volumes: - ./data:/data - ./logs:/logs - ./import:/var/lib/neo4j/import scanner: build: ./scanner container_name: pentagi-scanner ports: - 5000:5000 depends_on: - neo4j scheduler: build: ./scheduler container_name: pentagi-scheduler depends_on: - neo4j - scanner environment: - PYTHONUNBUFFERED1 # 注意scheduler 需要能解析 host.docker.internal extra_hosts: - host.docker.internal:host-gateway构建并启动docker-compose up -d --build # 查看 scheduler 日志 docker logs -f pentagi-scheduler你会看到日志里打印出扫描过程。至此一个最小可行的 Pentagi 系统已经跑通Neo4j 存储资产Scanner 执行探测Scheduler 协调两者并更新图谱。它没有炫酷的 UI没有大模型对话但它是一个真实、可运行、可扩展的安全智能体骨架。这比“Neo4j 安装与配置”、“Docker 安装部署”这些零散教程更有体系感也更贴近一线工程师的真实工作流。4. 实战问题排查与避坑指南那些文档里不会写的血泪教训4.1 Neo4j 启动失败内存不足是最大元凶而非配置错误新手常遇到neo4j容器启动后立即退出docker logs pentagi-neo4j里只有一行Killed。这几乎 100% 是内存不足导致的 OOM Killer 杀掉了进程。Neo4j 社区版默认配置需要至少 2GB 内存而 Docker Desktop 在 Windows 上默认只分配 2GB 给 WSL2且被多个服务瓜分。解决方案不是去改neo4j.conf里的dbms.memory.heap.initial_size而是直接给 WSL2 划拨更多内存。在 Windows 上创建%USERPROFILE%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\wsl.conf文件路径中的UbuntuonWindows_79rhkp1fndgsc可能不同请用wsl -l -v查看你的发行版名称内容为[wsl2] memory3GB # 分配 3GB swap1GB localhostForwardingtrue然后在 PowerShell 中执行wsl --shutdown再重新启动 Docker Desktop。此时docker stats会显示pentagi-neo4j容器的内存使用稳定在 1.2GB 左右不再被杀。这个技巧比任何“Neo4j 安装教程”都管用因为它直击问题根源——资源分配而非参数调优。4.2 Docker 网络不通host.docker.internal在 Linux 上不生效的替代方案上面的docker-compose.yml里用了host.docker.internal让 scheduler 访问 scanner这在 Windows/macOS 的 Docker Desktop 上是内置支持的但在原生 Linux Docker 上会报错getaddrinfo ENOTFOUND host.docker.internal。这不是 bug是设计使然。正确解法是在docker-compose.yml的scheduler服务下添加network_mode: host然后在 Python 代码里把SCANNER_URL改成http://127.0.0.1:5000/scan。修改docker-compose.ymlscheduler: build: ./scheduler container_name: pentagi-scheduler network_mode: host # 关键 depends_on: - neo4j - scanner environment: - PYTHONUNBUFFERED1修改scheduler.py中的SCANNER_URL http://127.0.0.1:5000/scan。这样scheduler 容器就直接使用宿主机的网络栈127.0.0.1就是宿主机而 scanner 容器的端口5000是映射到宿主机的自然能通。这个方案比折腾--add-host或自定义 bridge 网络简单得多也更符合生产环境习惯。很多“Docker 入门教程”不会提这个细节因为它们默认你用的是 Docker Desktop。4.3 扫描器超时nmap在容器里无法获取 root 权限的终极解法nmap -sSSYN 扫描需要 raw socket 权限在 Docker 容器里默认是被禁止的所以你可能会看到nmap返回空结果或权限错误。网上教程教你怎么加--cap-addNET_RAW但这治标不治本且有安全风险。Pentagi 的解法是放弃-sS改用-sTTCP Connect 扫描它不需要 root 权限且在绝大多数内网环境中效果等同。修改scanner/app.py中的subprocess.run命令result subprocess.run( [nmap, -sT, -sV, -p, ports, -oX, -, target], # 将 -sS 改为 -sT ... )-sT的原理是完成三次握手虽然比-sS稍慢但胜在稳定、无需特权、兼容性无敌。在红队实战中你很少会因为用了-sT而漏掉一个端口却很可能因为加了--cap-add而被客户的 SOC 告警。这是一个典型的“工程师思维” vs “红队思维”的权衡前者追求技术完美后者追求结果可靠。Pentagi 的所有设计都向后者倾斜。4.4 Agent 调度死锁如何避免 Neo4j 事务在长循环中被阻塞在scheduler.py的run_cycle方法里如果你把while True:循环取消注释并且扫描目标很多就可能遇到 Neo4j 事务超时。原因是session.run()默认开启一个事务如果循环里有大量MERGE操作事务会一直 hold 住直到超时默认 60 秒。解决方案不是加大超时而是显式地控制事务生命周期。修改update_asset_with_scan_result方法def update_asset_with_scan_result(self, asset_id, scan_result): with self.driver.session() as session: # 第一步更新资产时间单独一个短事务 session.run( MATCH (a:Asset {id:

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价