
자체 호스팅 네트워크 탐색 및 검색 엔진으로, 지속적인 포트 스캔, 약 100개 서비스에 대한 심층 프로토콜 프로빙, 로컬 CVE 매칭, 그리고 인프라 인벤토리 및 위험 모니터링을 위한 전문 검색을 제공합니다.
<div align="center">
# UltraViolet
**자체 호스팅 네트워크 탐색 및 검색 — 자신의 하드웨어에서 실행하는 나만의 Shodan.**
TCP/UDP 스캐닝 · 약 100개 프로토콜 프로브 · TLS/JARM 지문 · CVE 매칭 · 전문 검색 · 델타 추적 · 알림
<br/>
[](service-api/)
[](service-frontend/)
[](service-env/)
[](service-env/)
[](.github/workflows/ci.yml)
[](LICENSE)
[빠른 시작](#-quick-start) ·
[기능](#-features) ·
[아키텍처](#-architecture) ·
[문서](#-documentation) ·
[프로덕션 체크리스트](#-production-checklist)
</div>
---
> **중요.** 소유한 네트워크 또는 **서면 승인**을 받은 네트워크만 스캔하세요. UltraViolet은 수동적 서비스 정찰만 수행하며 취약점을 악용하지 않습니다.
## 왜 UltraViolet인가
| 사용 사례 | 제공 기능 |
|----------|--------------|
| 경계 및 인벤토리 | CIDR 범위 전체에서 열린 포트와 서비스의 지속적 발견 |
| 인프라 검색 | HTTP 본문, 배너, TLS, DNS, CVE에 대한 전문 검색 |
| 위험 및 규정 준수 | 로컬 NVD 매칭 + CISA KEV 및 EPSS — 클라우드 의존성 없음 |
| 에어갭 배포 | Docker 이미지, CVE 시드, GeoIP MMDB를 디스크에 포함한 오프라인 아카이브 |
| 변경 추적 | 스캔 간 델타, WebSocket 이벤트, 저장된 검색에 대한 알림 |
단일 테넌트, 하나의 Docker Compose 스택, 데이터에 대한 완전한 통제권.
## ✨ 기능
**탐색**
- **masscan** 또는 **zmap**을 탐색 엔진으로 사용하는 TCP connect 스캐너
- 구성 가능한 포트에 대한 UDP 프로브
- 호스트 및 포트 제한과 함께 `SCAN_ALLOWED_CIDRS`로 범위 제한
**심층 프로브(약 100개 프로토콜)**
- 웹: HTTP/HTTPS, HTTP/3, GraphQL, favicon 해시, `robots.txt`, `security.txt`, 기술 스택
- TLS: 인증서 체인, JARM, JA3S/JA4S, 구성 등급
- 메일 및 디렉터리: SMTP, POP3/IMAP, LDAP, IPMI
- 데이터베이스 및 메시지 큐: MySQL, PostgreSQL, MongoDB, Redis, Kafka, MQTT, NATS, AMQP…
- ICS/SCADA: Modbus, BACnet, DNP3, IEC 104, S7Comm, ENIP, OPC UA…
- IoT 및 미디어: ONVIF, RTSP, Chromecast, AirPlay, UPnP…
- 전체 목록은 [프로토콜 문서](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs/probes/service-protocols.md) 참조
**보강**
- 역방향 DNS, GeoIP(MMDB), ASN
- 선택적 순방향 DNS 및 CT 로그 탐색
**CVE 및 위험**
- 백그라운드 동기화 및 지문 기반 매칭을 지원하는 로컬 NVD 미러
- CISA KEV 및 FIRST EPSS
**운영**
- RBAC(`viewer` / `operator` / `admin`), JWT + 리프레시 토큰
- 스캔 일정, 일시 중지/재개, 워커 재시작 후 고아 작업 회수
- Prometheus `/metrics`, 선택적 Grafana 프로필
- 감사 로그, 속도 제한, 보존 정책
## 🏗 아키텍처
```mermaid
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별 프론트엔드 재빌드 불필요.
| 디렉터리 | 용도 |
|-----------|---------|
| [`service-api/`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-api) | Go: `uv-api`(HTTP API, WebSocket, 워커) + `uv-scanner`(파이프라인) |
| [`service-frontend/`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-frontend) | React 19 + Vite + RTK — 스캔, 호스트, 검색, 대시보드 |
| [`service-documentation-frontend/`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend) | VitePress — 사용자 및 운영자 문서 |
| [`service-env/`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-env) | docker-compose, secrets, `install.sh` / `upgrade.sh` / 백업 |
백엔드 개발 규칙: [`CLAUDE.md`](https://github.com/yakushstanislav/ultraviolet/blob/master/CLAUDE.md).
## 🚀 빠른 시작
**요구 사항:** Go 1.25+, Docker Engine ≥ 24, 약 4GB RAM. 프로덕션 이미지는 Linux **amd64**를 대상으로 합니다.
### Docker Hub에서 실행(소스 빌드 불필요)
초보자용 경로 — 게시된 이미지를 [`service-env/docker-compose.registry.yml`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-env/docker-compose.registry.yml)로 가져옵니다:
```bash
cd service-env
cp env.registry.example .env
# set 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](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs/deployment/docker-registry.md)를 참조하세요.
### 소스에서 개발하기
API/스캐너 이미지는 `service-api/bin/`에서 사전 빌드된 바이너리를 복사합니다(Docker 내부에서 **컴파일되지 않음**). `make dev`는 `docker compose … --build` 전에 `make -C service-api build-linux`를 실행합니다.
```bash
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 직접 접근 |
| http://localhost:9090/metrics | Prometheus |
**개발 부트스트랩:** `admin` / `admin`(`APP_ENV≠production`인 경우에만).
## 📖 문서
전체 가이드 — [`service-documentation-frontend/docs/`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs)의 VitePress:
```bash
make docs-dev # → http://localhost:5173
```
프로덕션에서는 `docs` 프로필을 활성화하세요:
```bash
cd service-env && docker compose --profile docs up -d
# → http://localhost:${UV_DOCUMENTATION_PORT:-3002}
```
주요 섹션: [설치](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs/getting-started/installation.md) · [스캐닝](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs/scanning) · [API](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs/api/overview.md) · [배포](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs/deployment/docker-compose.md) · [오프라인 설치](https://github.com/yakushstanislav/ultraviolet/blob/master/service-documentation-frontend/docs/deployment/offline-install.md).
## 🛠 개발
### 전체 Docker
```bash
make dev # build-linux → compose prod + dev override --build
```
백엔드 변경 후 Go 바이너리를 다시 빌드하고(`make -C service-api build-linux`), 재시작하거나 `make dev`를 다시 실행하세요.
### 하이브리드 모드(더 빠른 백엔드 반복)
```bash
make dev-db # PostgreSQL only on :5432
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`로 프록시).
### GeoIP 및 CVE
```bash
cd service-env && make geoip-download # IPLocate MMDB → geoip/
make -C service-env cve-catalog-dump # CVE dump (requires running postgres)
```
### Docker 없이 빌드
```bash
make build && make lint && make frontend-build && make docs-build
```
## 📦 릴리스 및 설치
**대상 플랫폼:** `linux/amd64`. Apple Silicon에서는 오프라인 아카이브를 위해 `DOCKER_PLATFORM=linux/amd64`를 설정하세요.
```bash
git tag v0.1.0
make release VERSION=v0.1.0
make release-promote VERSION=v0.1.0 # :latest — required for local releases; GitHub Actions does this automatically
```
| 아카이브 | 내용 |
|---------|----------|
| `ultraviolet-vX.Y.Z.tar.gz` | compose, 스크립트, `.env.example`(약 50KB, 온라인) |
| `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`(레지스트리에서 풀).
**오프라인:** `./install.sh`(`docker load`, 풀 없음). 업그레이드: `.env`, `secrets/`, Postgres 볼륨을 유지한 채 → `./upgrade.sh`.
변수: `UV_REGISTRY`(기본값 `docker.io/styakush`), `DRY_RUN=1` — 푸시 없는 로컬 스모크 빌드.
<details>
<summary><strong>오프라인 설치 — 단계별 안내</strong></summary>
```bash
# from the build machine
scp dist/ultraviolet-v0.1.0-offline.tar.gz user@host:~/
# on the server (Docker ≥ 24, amd64)
tar xzf ultraviolet-v0.1.0-offline.tar.gz && cd ultraviolet-v0.1.0
cp .env.example .env
./install.sh
```
업그레이드(데이터 보존):
```bash
docker compose -f docker-compose.yml down
# back up .env + secrets/, extract the new archive, run ./upgrade.sh
```
디렉터리 이름(`ultraviolet-v0.1.0`)을 변경하지 마세요 — `postgres-data` Docker 볼륨이 이 이름에 연결되어 있습니다.
</details>
## ✅ 프로덕션 체크리스트
1. 시크릿은 `secrets/`에 저장하고 절대 git에 커밋하지 마세요.
2. `CORS_ALLOWED_ORIGINS`를 실제 UI 오리진으로만 설정하세요.
3. `SCAN_ALLOWED_CIDRS`와 호스트/포트 제한을 구성하세요.
4. 부트스트랩 비밀번호와 `AUTH_JWT_SECRET`을 변경하세요(`install.sh`는 플레이스홀더를 거부합니다).
5. `APP_ENV=production`으로 설정하세요 — uv-api는 `admin/admin` 및 8자 미만의 비밀번호를 거부합니다.
6. 리버스 프록시에서 TLS를 종료하세요 — 예: [`service-env/examples/nginx-tls.conf`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-env/examples/nginx-tls.conf).
7. 프록시 뒤에서 실행하는 경우: `AUDIT_TRUST_PROXY_HEADERS=true`로 설정하세요.
8. PostgreSQL을 백업하세요: [`service-env/scripts/backup.sh`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-env/scripts/backup.sh) + cron; `upgrade.sh`도 덤프를 생성합니다.
9. 메트릭은 `:9090/metrics`에서 확인; Grafana는 `observability` 프로필로 실행.
10. GeoIP를 갱신하세요: [`service-env/scripts/geoip-refresh.sh`](https://github.com/yakushstanislav/ultraviolet/blob/master/service-env/scripts/geoip-refresh.sh)를 매월 cron으로 실행.
<details>
<summary><strong>HTTPS, 하위 경로 배포, 백업 cron</strong></summary>
**외부 nginx에서 TLS 종료** — UI를 루프백에만 바인딩:
```yaml
# docker-compose.override.yml
services:
service-frontend:
ports:
- "127.0.0.1:3000:8080"
```
```bash
CORS_ALLOWED_ORIGINS=https://ultraviolet.example.com
AUDIT_TRUST_PROXY_HEADERS=true
```
**하위 경로**(`/ultraviolet/`):
```bash
VITE_BASE_PATH=/ultraviolet/ make frontend-build
# UV_BASE_PATH=/ultraviolet/ in compose — must match VITE_BASE_PATH
```
**백업 cron**(매일, 14일 보존):
```cron
0 3 * * * cd /opt/ultraviolet/service-env && ./scripts/backup.sh && find backups -name 'uv-*.dump' -mtime +14 -delete
```
**GeoIP 갱신**(매월 1일):
```cron
0 4 1 * * cd /opt/ultraviolet/service-env && ./scripts/geoip-refresh.sh >> /var/log/uv-geoip.log 2>&1
```
</details>
## 🔐 API 및 RBAC
`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](https://github.com/yakushstanislav/ultraviolet/blob/master/CONTRIBUTING.md)를 참조하세요. 보안 신고: [SECURITY.md](https://github.com/yakushstanislav/ultraviolet/blob/master/SECURITY.md).
커뮤니티 표준: [CODE_OF_CONDUCT.md](https://github.com/yakushstanislav/ultraviolet/blob/master/CODE_OF_CONDUCT.md).
## 📄 라이선스
UltraViolet은 [MIT 라이선스](https://github.com/yakushstanislav/ultraviolet/blob/master/LICENSE)로 배포됩니다.
---
<p align="center">
<sub>UltraViolet — 소유한 것을 발견하고, 변경된 것을 이해하며, 네트워크 안에서 유지하세요.</sub>
</p>