自托管网络发现与搜索——你自己的 Shodan,运行在你自己的硬件上。
TCP/UDP 扫描 · 约 100 种协议探测 · TLS/JARM 指纹 · CVE 匹配 · 全文搜索 · 增量跟踪 · 告警
重要提示。 仅扫描你拥有或已获得书面授权的网络。UltraViolet 执行被动服务侦察——它不会利用漏洞。
| 使用场景 | 你能获得什么 |
|---|---|
| 边界与资产盘点 | 跨 CIDR 范围的开放端口与服务持续发现 |
| 基础设施搜索 | 对 HTTP 响应体、横幅、TLS、DNS 和 CVE 进行全文搜索 |
| 风险与合规 |
单租户、一套 Docker Compose 栈、完全掌控你的数据。
发现
SCAN_ALLOWED_CIDRS 限定范围,并带有主机与端口限制深度探测(约 100 种协议)
robots.txt、security.txt、技术栈数据丰富
CVE 与风险
运维
viewer / operator / admin)、JWT + 刷新令牌/metrics、可选的 Grafana 配置flowchart TB
Browser["Browser"]
FE["service-frontend<br/>React + nginx"]
API["uv-api<br/>REST · WS · metrics"]
PG[("PostgreSQL 16")]
SCAN["uv-scanner<br/>probe pipeline"]
Browser --> FE
FE -->|"/api"| API
FE -->|"/realtime"| API
API <--> PG
SCAN <--> PG
API -.->|LISTEN/NOTIFY| API发布版 UI 镜像将 /api/ 和 /realtime 代理到 uv-api——单一来源,无需针对每个 API URL 重新构建前端。
后端开发规则:CLAUDE.md。
环境要求: Go 1.25+、Docker Engine ≥ 24、约 4 GB 内存。生产镜像面向 Linux amd64。
新手路径——使用
service-env/docker-compose.registry.yml 拉取已发布镜像:
cd service-env
cp env.registry.example .env
# 设置 POSTGRES_PASSWORD、AUTH_JWT_SECRET、AUTH_BOOTSTRAP_PASSWORD
mkdir -p geoip catalog-seed
docker compose -f docker-compose.registry.yml pull
docker compose -f docker-compose.registry.yml up -d
# UI → http://localhost:3000
参见文档站点中的 Docker Registry。
API/扫描器镜像会复制 service-api/bin/ 中预构建的二进制文件(它们不会在 Docker 内部编译)。make dev 会在 docker compose … --build 之前运行 make -C service-api build-linux。
git clone https://github.com/yakushstanislav/UltraViolet.git
cd UltraViolet/service-env
cp .env.example .env
mkdir -p secrets
openssl rand -hex 32 > secrets/postgres_password
openssl rand -hex 32 > secrets/auth_jwt_secret
cd ..
make dev
| URL | 用途 |
|---|---|
| http://localhost:3000 | UI(通过 nginx /api/ 访问 API) |
| http://localhost:8080 | 直接访问 API |
开发引导账号: admin / admin(仅在 APP_ENV≠production 时有效)。
完整指南——VitePress 位于 service-documentation-frontend/docs/:
make docs-dev # → http://localhost:5173
在生产环境中,启用 docs 配置:
cd service-env && docker compose --profile docs up -d
# → http://localhost:${UV_DOCUMENTATION_PORT:-3002}
关键章节:安装 · 扫描 · API · 部署 · 离线安装。
make dev # build-linux → compose prod + dev override --build
后端代码变更后重新构建 Go 二进制文件(make -C service-api build-linux),然后重启或重新运行 make dev。
make dev-db # 仅在 :5432 上运行 PostgreSQL
cd service-api && make build
export LOGGER_NAME=uv-api LOGGER_DEBUG=true
export SERVER_ADDR=0.0.0.0 SERVER_PORT=8080
export METRICS_ADDR=0.0.0.0 METRICS_PORT=9090
export REALTIME_ADDR=0.0.0.0 REALTIME_PORT=8081
export POSTGRES_ADDR=localhost POSTGRES_PORT=5432
export POSTGRES_USERNAME=ultraviolet
export POSTGRES_PASSWORD="$(cat ../service-env/secrets/postgres_password)"
export POSTGRES_DATABASE=ultraviolet
export POSTGRES_SCHEMA_PATH="$(pwd)/deploy/migrations"
export AUTH_JWT_SECRET="$(cat ../service-env/secrets/auth_jwt_secret)"
./bin/uv-api
前端:cd service-frontend && npm run dev(Vite 将 /api 代理到 :8080,将 /realtime 代理到 :8081)。
cd service-env && make geoip-download # IPLocate MMDB → geoip/
make -C service-env cve-catalog-dump # CVE 数据导出(需要正在运行的 postgres)
make build && make lint && make frontend-build && make docs-build
目标平台: linux/amd64。在 Apple Silicon 上,为离线归档设置 DOCKER_PLATFORM=linux/amd64。
git tag v0.1.0
make release VERSION=v0.1.0
make release-promote VERSION=v0.1.0 # :latest——本地发布必需;GitHub Actions 会自动执行此操作
| 归档文件 | 内容 |
|---|---|
ultraviolet-vX.Y.Z.tar.gz | compose、脚本、.env.example(约 50 KB,在线) |
ultraviolet-vX.Y.Z-offline.tar.gz | + amd64 Docker 镜像 |
ultraviolet-vX.Y.Z-offline-full.tar.gz | + CVE 种子数据 + GeoIP MMDB |
在线安装: 解压 → cp .env.example .env → ./install.sh(从 registry 拉取)。
离线安装: ./install.sh(docker load,不拉取)。升级:保留 .env、secrets/ 和 Postgres 卷 → ./upgrade.sh。
变量:UV_REGISTRY(默认 docker.io/styakush)、DRY_RUN=1——本地冒烟构建,不推送。
# 在构建机器上
scp dist/ultraviolet-v0.1.0-offline.tar.gz user@host:~/
# 在服务器上(Docker ≥ 24,amd64)
tar xzf ultraviolet-v0.1.0-offline.tar.gz && cd ultraviolet-v0.1.0
cp .env.example .env
./install.sh
升级(保留数据):
docker compose -f docker-compose.yml down
# 备份 .env + secrets/,解压新归档,运行 ./upgrade.sh
保持目录名称(ultraviolet-v0.1.0)不变——postgres-data Docker 卷与其绑定。
secrets/ 中,切勿提交到 git。CORS_ALLOWED_ORIGINS 仅设置为真实的 UI 来源。SCAN_ALLOWED_CIDRS 以及主机/端口限制。AUTH_JWT_SECRET(install.sh 会拒绝占位符)。APP_ENV=production——uv-api 会拒绝 admin/admin 以及少于 8 个字符的密码。service-env/examples/nginx-tls.conf。AUDIT_TRUST_PROXY_HEADERS=true。service-env/scripts/backup.sh + cron;upgrade.sh 也会创建转储。:9090/metrics;通过 配置使用 Grafana。在外部 nginx 上终止 TLS——将 UI 仅绑定到回环地址:
# docker-compose.override.yml
services:
service-frontend:
ports:
- "127.0.0.1:3000:8080"
CORS_ALLOWED_ORIGINS=https://ultraviolet.example.com
AUDIT_TRUST_PROXY_HEADERS=true
子路径(/ultraviolet/):
VITE_BASE_PATH=/ultraviolet/ make frontend-build
# compose 中设置 UV_BASE_PATH=/ultraviolet/——必须与 VITE_BASE_PATH 一致
备份 cron(每日,14 天保留):
0 3 * * * cd /opt/ultraviolet/service-env && ./scripts/backup.sh && find backups -name 'uv-*.dump' -mtime +14 -delete
GeoIP 刷新(每月 1 日):
0 4 1 * * cd /opt/ultraviolet/service-env && ./scripts/geoip-refresh.sh >> /var/log/uv-geoip.log 2>&1
执行 POST /v1/auth/login 后,你将获得一个 access_token(Bearer)和 refresh_token(/v1/auth/refresh)。
| 角色 | 权限 |
|---|---|
viewer | 读取主机、搜索、CVE、仪表盘 |
operator | + 启动和管理扫描 |
admin | + 用户、审计、设置 |
GET /v1/me · GET /v1/version · GET /readyz(健康检查 + 版本 + 提交)。
参见 CONTRIBUTING.md。安全报告:SECURITY.md。 社区规范:CODE_OF_CONDUCT.md。
UltraViolet 以 MIT License 发布。
UltraViolet——发现你所拥有的,了解发生了什么变化,将其保留在你的网络中。
| 本地 NVD 匹配,外加 CISA KEV 和 EPSS——无云端依赖 |
| 隔离网络部署 | 离线归档,包含 Docker 镜像、CVE 种子数据和磁盘上的 GeoIP MMDB |
| 变更跟踪 | 扫描之间的增量、WebSocket 事件、保存搜索的告警 |
| 目录 | 用途 |
|---|
service-api/ | Go:uv-api(HTTP API、WebSocket、工作进程)+ uv-scanner(流水线) |
service-frontend/ | React 19 + Vite + RTK——扫描、主机、搜索、仪表盘 |
service-documentation-frontend/ | VitePress——用户与运维人员文档 |
service-env/ | docker-compose、密钥、install.sh / upgrade.sh / 备份 |
| Prometheus |
observabilityservice-env/scripts/geoip-refresh.sh,每月 cron 执行。