ToluGuy/heimdall-vscanner
GitHub: ToluGuy/heimdall-vscanner
Heimdall 是一款采用服务器-Agent 架构的分布式局域网漏洞评估扫描器,通过统一仪表盘调度 Nmap、Nikto 和 NSE 实现内网资产的自动化安全巡检。
Stars: 0 | Forks: 0
# Heimdall V-Scanner
专为内部办公网络使用的分布式漏洞评估扫描器。Heimdall 通过中央服务器和多个远程 agent 协调扫描任务,提供统一的仪表盘,以全面了解整个局域网内的网络漏洞。
## 架构
Heimdall 采用服务器-agent 模型:
- **后端服务器** — 一个 FastAPI 应用程序,负责管理任务队列、agent 注册、调度和扫描结果。由 PostgreSQL 提供支持。
- **远程扫描器** (`scanner.py`) — 与后端一起在中央服务器上运行。处理针对无法直接运行 agent 的目标(如防火墙、交换机和打印机)的无代理远程扫描。
- **Agent** (`agent/agent.py`) — 运行在网络上的任何端点。轮询服务器获取任务,并从该机器的网络位置执行扫描。
- **本地扫描器** (`agent/local_scanner.py`) — 适用于任何端点的完全独立扫描工具。运行自己的本地 Web UI,不需要中央服务器,并将结果保留在当前会话的内存中。
- **仪表盘** — 由后端提供的 Web 界面,用于创建任务、监控 agent、查看扫描结果、管理调度和生成报告。
## 法律声明
Heimdall V-Scanner 采用 [MIT 许可证](LICENSE)授权。
此工具仅限在您拥有或获得**明确书面授权**测试的网络和系统上使用。未经授权的扫描在大多数司法管辖区都是非法的。使用本软件即表示您同意 [DISCLAIMER.md](DISCLAIMER.md) 中的条款。
## 扫描工具
Heimdall 会自动将三个工具链接在一起:
- **Nmap** — 端口发现和服务检测。每次扫描首先运行此工具。
- **Nikto** — Web 漏洞扫描。当 Nmap 发现开放的 Web 端口时自动触发。
- **NSE (Nmap Scripting Engine)** — 针对非 Web 服务(SSH、SMB、RDP、数据库等)的漏洞脚本扫描。
仪表盘使用通俗易懂的语言表示扫描类型。内部名称(在 API 和数据库中使用)显示在括号中供参考。
## 扫描类型
| 仪表盘标签 | 内部名称 | 描述 |
|-----------------|---------------|-------------|
| 端口扫描 | `nmap_scan` | 发现开放端口;自动对发现的任何 Web 端口运行快速的 Web 扫描(轻量级 profile)。要运行彻底的 Web 扫描,请显式创建 Web 扫描任务。 |
| Web 扫描 | `nikto_scan` | 针对特定端口的独立 Web 漏洞扫描 |
| 漏洞扫描 | `nse_scan` | 针对非 Web 服务的基于脚本的漏洞检查;排除 Web 端口 |
## 扫描 Profiles
| Profile | Nmap 标志 | Web 扫描标志 | 漏洞脚本 | 描述 |
|---------|-----------|----------------|--------------|-------------|
| Light | `-F` | `-Tuning 1` | `safe` | 前 100 个端口,快速,非侵入式 |
| Standard | `-sV` | default | `vuln` | 前 1000 个端口,包含服务检测 |
| Full | `-sV -O -p-` | `-Tuning x6` | `vuln,exploit` ⚠️ | 所有端口,深度扫描 — exploit 脚本具有侵入性 |
## 快速安装(Linux 服务器)
安装程序会处理一切:依赖项、数据库、环境配置和 systemd 服务。
```
git clone https://github.com/ToluGuy/heimdall-vscanner.git
cd heimdall-vscanner
chmod +x install.sh
./install.sh
```
请使用具有 sudo 权限的普通用户运行,不要使用 root 用户。
安装程序将执行以下操作:
- 安装系统软件包(nmap、nikto、postgresql、python3-venv)
- 创建 Python 虚拟环境并安装依赖项
- 提示输入仪表盘凭据和数据库设置,然后写入 `.env`
- 设置 PostgreSQL 数据库、用户和所有必需的权限
- 自动运行所有 schema 迁移
- 安装并可选择启动 `vapt-server` 和 `vapt-scanner` systemd 服务
- 如果 UFW 处于活动状态,则在其中开放端口 8000
## 更新
发布新版本时,请运行更新程序而不是重新安装:
```
git pull
chmod +x update.sh
./update.sh
```
更新程序会拉取最新的代码,更新 Python 依赖项,运行所有新的数据库迁移,并重启服务。您的 `.env`、现有扫描数据和 agent 注册信息都将被保留。在服务重启期间,仪表盘将不可用几秒钟。
如果您是在没有 git 的情况下安装的(手动下载),请手动替换项目文件,然后运行 `./update.sh` 来处理依赖项、迁移和重启。
## 手动设置
如果您不想使用安装程序:
### 1. 克隆仓库
```
git clone https://github.com/ToluGuy/heimdall-vscanner.git
cd heimdall-vscanner
```
### 2. 安装系统依赖
```
sudo apt install nmap nikto postgresql python3-venv python3-pip
```
### 3. 创建并激活虚拟环境
```
python3 -m venv venv
source venv/bin/activate
```
### 4. 安装 Python 依赖项
```
pip install -r requirements.txt
```
### 5. 设置 PostgreSQL
```
sudo -u postgres psql
```
```
CREATE DATABASE vapt;
CREATE USER vapt_user WITH PASSWORD 'your-password';
GRANT ALL PRIVILEGES ON DATABASE vapt TO vapt_user;
ALTER DATABASE vapt OWNER TO vapt_user;
GRANT ALL ON SCHEMA public TO vapt_user;
\q
```
### 6. 配置环境变量
在项目根目录下创建一个 `.env` 文件:
```
DASHBOARD_USERNAME=admin
DASHBOARD_PASSWORD=your-strong-password
DB_HOST=localhost
DB_PORT=5432
DB_NAME=vapt
DB_USER=vapt_user
DB_PASSWORD=your-password
```
### 7. 运行数据库迁移
```
python3 -c "
from backend.app.db import engine, Base
from backend.app.models import Agent, Job, Result, DiscoverySweep, Schedule, Host, Setting
Base.metadata.create_all(bind=engine)
"
```
如果是从早期版本升级,还需运行以下 SQL 语句:
```
ALTER TABLE results ADD COLUMN IF NOT EXISTS cleared BOOLEAN DEFAULT FALSE;
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS cleared BOOLEAN DEFAULT FALSE;
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS mode VARCHAR DEFAULT 'remote';
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS profile VARCHAR DEFAULT 'standard';
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS started_at TIMESTAMP;
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS completed_at TIMESTAMP;
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS next_run_at TIMESTAMP;
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS port INTEGER;
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS ports VARCHAR;
ALTER TABLE agents ADD COLUMN IF NOT EXISTS is_stale BOOLEAN DEFAULT FALSE;
CREATE TABLE IF NOT EXISTS schedules (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
type VARCHAR NOT NULL,
target VARCHAR NOT NULL,
mode VARCHAR DEFAULT 'remote',
profile VARCHAR DEFAULT 'standard',
priority VARCHAR DEFAULT 'medium',
ports VARCHAR,
interval_hours INTEGER NOT NULL,
paused BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT NOW(),
last_run_at TIMESTAMP,
next_run_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS settings (
key VARCHAR PRIMARY KEY,
value VARCHAR NOT NULL
);
GRANT ALL ON TABLE schedules TO vapt_user;
GRANT ALL ON TABLE settings TO vapt_user;
GRANT USAGE, SELECT ON SEQUENCE schedules_id_seq TO vapt_user;
```
`discovery_sweeps` 和 `hosts` 表会在启动时由 SQLAlchemy 自动创建。
### 8. 启动服务器
```
uvicorn backend.app.main:app --host 0.0.0.0 --port 8000
```
仪表盘可通过 `http://localhost:8000/dashboard` 访问。
## 部署(生产环境)
### 推荐设置
在您可用的任何 hypervisor(ESXi、Proxmox、VirtualBox 等)上使用专用的 Linux 虚拟机。后端服务器和远程扫描器均在此虚拟机上运行。Agent 单独在各个端点上运行。
**最低虚拟机规格:**
- 2 vCPU,2 GB 内存,20 GB 磁盘
- Ubuntu 22.04 或 24.04 LTS
- 办公局域网上的静态 IP
### ESXi 设置
1. 下载 Ubuntu 24.04 LTS 服务器 ISO
2. 在 ESXi 中,创建一个新虚拟机:2 vCPU,2 GB 内存,20 GB thin-provisioned 磁盘
3. 挂载 ISO,安装 Ubuntu 并启用 OpenSSH
4. 通过 netplan 设置静态 IP:
```
# /etc/netplan/00-installer-config.yaml
network:
version: 2
ethernets:
ens160:
addresses: [192.168.1.200/24]
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
```
```
sudo netplan apply
```
5. 通过 SSH 登录并运行安装程序。
### Systemd 服务
安装程序会自动设置两个服务:
```
# 状态
sudo systemctl status vapt-server
sudo systemctl status vapt-scanner
# 启动 / 停止 / 重启
sudo systemctl start vapt-server vapt-scanner
sudo systemctl restart vapt-server vapt-scanner
# 开机启用
sudo systemctl enable vapt-server vapt-scanner
# 实时日志
journalctl -u vapt-server -f
journalctl -u vapt-scanner -f
```
### 网络要求
必须从局域网能够访问服务器上的 8000 端口,以便 agent 和浏览器连接:
```
sudo ufw allow 8000/tcp
```
| 方向 | 来源 | 目标 | 端口 | 用途 |
|-----------|------|----|------|---------|
| 出站 | 服务器/扫描器 | 扫描目标 | any | Nmap, Nikto, NSE |
| 出站 | Agents | 服务器 | 8000 | 任务轮询、心跳、结果 |
| 入站 | 浏览器 | 服务器 | 8000 | 仪表盘访问 |
Agent 只需要对服务器上 8000 端口的出站访问权限。它们不需要可被入站访问。
## 仪表盘
通过 `/dashboard` 访问仪表盘。首次加载时,系统会提示您输入凭据。
在仪表盘中,您可以:
- **网络发现** — 以 CIDR 表示法扫描子网以查找活动主机;在分配扫描任务之前查看结果
- **计划任务** — 按可配置的时间间隔设置定期扫描;随时暂停、恢复或删除计划任务
- **创建任务** — 手动为任何 IP 提交扫描任务,并控制扫描类型、profile、模式和优先级
- **Agents** — 监控已注册的 agent、它们的在线/离线状态以及最后一次心跳;显示或隐藏过期 agent;恢复或忽略它们
- **任务** — 查看任务队列以及正在运行的任务的实时耗时计时器;按状态过滤;批量删除待处理和失败的任务
- **扫描结果** — 展开结果以查看端口表、漏洞发现和 Web 扫描发现;在当前结果和历史记录之间切换
- **洞察** — 分析仪表盘,显示一段时间内的扫描活动、风险分布以及逐台主机的详细信息
- **拓扑** — 交互式 D3 网络地图,显示所有发现的主机,按子网聚类,按风险级别着色
- **报告** — 为任何扫描结果生成可打印的 HTML 报告,可通过浏览器打印对话框导出为 PDF
- **导出** — 将扫描结果下载为结构化的 JSON,支持单个或批量导出
## AI 分析
Heimdall 可以使用您选择的 AI 提供商,自动为每个扫描结果生成风险评估和修复计划。在您的 `.env` 中添加以下内容:
```
AI_PROVIDER=anthropic # anthropic | openai | groq | ollama
AI_API_KEY=your-api-key
AI_MODEL= # optional — leave blank for the provider default
AI_BASE_URL= # only needed for ollama
AI_AUTO_ANALYSE=true # set to false to trigger analysis manually per result
```
| 提供商 | 默认模型 |
|----------|--------------|
| `anthropic` | claude-sonnet-4-5 |
| `openai` | gpt-4o-mini |
| `groq` | llama-3.3-70b-versatile |
| `ollama` | llama3 (本地) |
也可以在运行时从仪表盘的“设置”面板中开启/关闭 AI 分析,而无需重启服务器。
## Agents
有关 Linux 和 Windows 端点的完整 agent 设置说明,请参阅 [`agent/SETUP_GUIDE.md`](agent/SETUP_GUIDE.md)。
### 快速入门 — Linux
```
cd agent/
pip install requests python-dotenv
VAPT_AGENT_NAME=office-pc-1 \
VAPT_SERVER_URL=http://192.168.1.200:8000 \
VAPT_CAPABILITIES=nmap_scan,nikto_scan,nse_scan \
python3 agent.py
```
### 快速入门 — Windows
在 PowerShell 中以管理员身份运行 `agent/setup_agent.ps1`。它会自动处理 Python、Nmap、依赖项、配置和桌面快捷方式。
```
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\agent\setup_agent.ps1
```
### 本地扫描器(任何端点,不需要服务器)
```
python3 agent/local_scanner.py
```
在 `http://127.0.0.1:9731` 打开基于浏览器的扫描 UI。支持端口扫描和漏洞扫描。结果保存在当前会话的内存中,可以在关闭前导出为 JSON。
## 调度
计划任务从仪表盘创建并存储在数据库中。每个计划任务定义扫描类型、目标、profile、模式、优先级以及以小时为单位的重复间隔。调度器每 60 秒检查一次是否有到期的计划任务,并自动创建相应的扫描任务。
计划任务在创建时立即触发,然后按配置的间隔重复。恢复已暂停的计划任务需等待一个完整的间隔才会再次触发。
## 过期 Agent 清理
未在可配置阈值(默认为 24 小时)内发送心跳的 Agent 将被后台清理线程自动标记为过期。过期 agent 会从默认 agent 视图中隐藏,但可以通过“显示过期”开关显示。从那里可以恢复或永久忽略它们。
可以从仪表盘的“设置”面板调整阈值,或者在 `.env` 中设置 `STALE_AGENT_HOURS`。
## 优先级队列
任务支持三个优先级:`high`、`medium` 和 `low`。调度器总是首先选择符合条件且优先级最高的任务。在同一优先级内,特定 agent 的任务优先于任意 agent 的任务,并且旧任务会先于新任务被选中。每个 agent 最多同时处理 2 个并发任务。
## 项目结构
```
heimdall-vscanner/
├── agent/
│ ├── agent.py # Endpoint agent — polls server, runs scans locally
│ ├── local_scanner.py # Standalone scan tool with browser UI (no server needed)
│ ├── setup_agent.ps1 # Windows endpoint setup script
│ └── SETUP_GUIDE.md # Agent and local scanner setup guide
├── backend/
│ └── app/
│ ├── main.py # FastAPI server, all endpoints, dashboard HTML
│ ├── models.py # SQLAlchemy database models
│ ├── schemas.py # Pydantic request/response schemas
│ ├── db.py # Database connection and session
│ ├── logger.py # Logging configuration
│ └── ai_analysis.py # AI-powered scan analysis (optional)
├── tools/
│ ├── check_db.py # Database health check
│ ├── reset_stuck_jobs.py # Unstick jobs that got stuck in 'running'
│ ├── purge_history.py # Permanently delete archived scan history
│ ├── reset_db.py # Wipe all scan data (dev/test use only)
│ ├── seed_test_jobs.py # Create test jobs against localhost
│ ├── test_connection.py # Verify agent-to-server connectivity
│ └── test_ports.py # Open netcat listeners for scan testing
├── scanner.py # Agentless remote scanner (runs on central server)
├── install.sh # Automated Linux installer
├── update.sh # Lightweight updater for new releases
├── vapt-server.service # Systemd service file — backend server
├── vapt-scanner.service # Systemd service file — remote scanner
├── requirements.txt
├── .env # Not committed — created by installer or manually
└── logs/ # Not committed — created at runtime
```
## 环境变量
### 服务器
| 变量 | 描述 | 默认值 |
|----------|-------------|---------|
| `DASHBOARD_USERNAME` | 仪表盘登录用户名 | `admin` |
| `DASHBOARD_PASSWORD` | 仪表盘登录密码 | `vapt-admin` |
| `DB_HOST` | PostgreSQL 主机 | `localhost` |
| `DB_PORT` | PostgreSQL 端口 | `5432` |
| `DB_NAME` | 数据库名称 | `vapt` |
| `DB_USER` | 数据库用户 | `vapt_user` |
| `DB_PASSWORD` | 数据库密码 | — |
| `STALE_AGENT_HOURS` | agent 被标记为过期前的小时数 | `24` |
| `AI_PROVIDER` | 用于扫描分析的 AI 提供商(`anthropic`、`openai`、`groq`、`ollama`) | — |
| `AI_API_KEY` | 所选 AI 提供商的 API 密钥 | — |
| `AI_MODEL` | 模型覆盖 — 留空则使用提供商默认值 | — |
| `AI_BASE_URL` | Ollama 的 Base URL(例如 `http://localhost:11434`) | — |
| `AI_AUTO_ANALYSE` | 每次扫描后自动运行 AI 分析 | `true` |
### Agent
| 变量 | 描述 | 默认值 |
|----------|-------------|---------|
| `VAPT_SERVER_URL` | 后端服务器的 URL | `http://127.0.0.1:8000` |
| `VAPT_AGENT_NAME` | 此 agent 实例的名称 | `agent-default` |
| `VAPT_CAPABILITIES` | 此 agent 处理的、以逗号分隔的扫描类型 | `nmap_scan,nikto_scan,nse_scan` |
| `VAPT_KEY_FILE` | 存储 agent 密钥的路径 | `{agent-name}_key.txt` |
## 故障排除
**服务器无法启动**
检查日志:`journalctl -u vapt-server -n 50`。最常见的原因是 `.env` 文件损坏或 PostgreSQL 未运行(`sudo systemctl status postgresql`)。
**Agent 在仪表盘中显示离线**
心跳超时为 30 秒。如果 agent 在该时间窗口内未发送心跳,则会显示为离线。请确认 agent 正在运行且能够访问服务器上的 8000 端口。
**计划任务因权限错误而失败**
`schedules` 表在创建时数据库用户没有写入权限。请以 postgres 超级用户身份运行:
```
GRANT ALL ON TABLE schedules TO vapt_user;
GRANT USAGE, SELECT ON SEQUENCE schedules_id_seq TO vapt_user;
```
**Web 扫描 (Nikto) 挂起**
由 Nikto 2.6.x 中的 CIRT.net 更新提示引起。扫描器会使用 `input="n\n"` 自动抑制它。如果扫描仍然挂起,请使用 `nikto -Version` 检查 Nikto 是否正确安装。
**漏洞扫描未返回任何结果**
如果目标在可发现的端口上没有运行非 Web 服务,这是正常的。漏洞扫描会特意跳过 Web 端口(80、443、8080、8443、8000、8888)— 请使用 Web 扫描进行 Web 表面测试。
**Agent 无法访问端口 8000**
检查服务器防火墙:`sudo ufw status`。如果处于活动状态,请运行 `sudo ufw allow 8000/tcp`。
**启动时出现 PostgreSQL 权限错误**
```
GRANT ALL ON SCHEMA public TO vapt_user;
ALTER DATABASE vapt OWNER TO vapt_user;
```
**AI 分析未显示**
检查 `.env` 中是否设置了 `AI_PROVIDER` 和 `AI_API_KEY`,并确认服务器已重启。您也可以在仪表盘中点击任何结果上的“分析”来手动触发分析。验证在“设置”面板中是否已启用该设置。
**更新弄坏了某些东西**
每次更新只会增加列 — 它永远不会删除或修改现有列。如果更新后出现异常,请检查 `journalctl -u vapt-server -n 50` 以查看启动错误,并将您的 `.env` 与上面的环境变量表进行比较,看看是否有任何新的必需值。
标签:AV绕过, CTI, FastAPI, Nmap, 分布式架构, 插件系统, 测试用例, 网络安全, 虚拟驱动器, 逆向工具, 隐私保护