feat: реализовать EvoFirewall V1 control plane
API, UI, Linux/MikroTik agents, IP lists, политики, stats, CI и интеграция с auth-portal/EvoBGP. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+6
-3
@@ -1,5 +1,8 @@
|
||||
# Документация EvoFirewall
|
||||
|
||||
- Интеграция с auth-portal — TODO (`docs/integrate-auth-portal.md`)
|
||||
- Интеграция с EvoBGP (prefix source) — TODO (`docs/integrate-evobgp.md`)
|
||||
- UI design contract — TODO (surface `frame`, kit `reui-kit/`)
|
||||
- [Архитектура](architecture.md)
|
||||
- [Auth-portal](integrate-auth-portal.md)
|
||||
- [EvoBGP](integrate-evobgp.md)
|
||||
- [Agents](agents.md)
|
||||
- [UI design contract](ui-design-contract.md)
|
||||
- [OpenAPI](openapi.yaml)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Agents
|
||||
|
||||
## Linux
|
||||
|
||||
```bash
|
||||
curl -fsSL https://<cp>/v1/agent/install.sh | \
|
||||
EVOFW_CP_URL=https://<cp> \
|
||||
EVOFW_SEED=<seed> \
|
||||
EVOFW_CLIENT_NAME="web-01" \
|
||||
bash
|
||||
```
|
||||
|
||||
Файлы: `/etc/evofw/agent.conf`, `/usr/local/sbin/evofw-firewall.sh`, timer `evofw-firewall.timer` (default 1min).
|
||||
|
||||
Backend auto-detect: nft → ipset → iptables.
|
||||
|
||||
Whitelist: nft chain policy drop + allow set. Blacklist: policy accept + deny set.
|
||||
|
||||
## MikroTik
|
||||
|
||||
Скачайте `/v1/agent/mikrotik-install.rsc`, задайте globals `EvofwCpUrl`, `EvofwSeed`, `EvofwName`, import. Scheduler каждую минуту тянет policy. Настройте filter на address-list `EVOFW_DENY` / `EVOFW_ALLOW`.
|
||||
|
||||
## Force sync
|
||||
|
||||
```bash
|
||||
sudo rm -f /var/lib/evofw/last_hash
|
||||
sudo /usr/local/sbin/evofw-firewall.sh
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# Архитектура EvoFirewall
|
||||
|
||||
Централизованный control plane для firewall-агентов (Linux nft/ipset, MikroTik address-list).
|
||||
|
||||
## Компоненты
|
||||
|
||||
| Компонент | Путь | Роль |
|
||||
|-----------|------|------|
|
||||
| Web SPA | `apps/web` | ReUI Frame, TanStack Router/Query |
|
||||
| API | `apps/api` | Fastify 5, JWT + agent tokens |
|
||||
| DB | `packages/db` | Drizzle + SQLite WAL |
|
||||
| Shared | `packages/shared` | Zod-контракты, RBAC helpers |
|
||||
| UI | `packages/ui` | shadcn primitives `@evofw/ui` |
|
||||
| Agents | `apps/api/src/agent-scripts` | install.sh, sync, MikroTik RSC |
|
||||
|
||||
## Потоки
|
||||
|
||||
1. **Enroll** — `POST /v1/agent/enroll` + `X-EvoFW-Seed` → pending agent
|
||||
2. **Approve** — UI/API → status approved
|
||||
3. **Policy** — `GET /v1/agent/policy` → deny/allow CIDRs + mode + hash
|
||||
4. **Apply** — agent пишет kernel rules, `POST /v1/agent/apply-report` + stats sample
|
||||
5. **Lists refresh** — cron каждые 5 мин (json_url / domains / evobgp_community)
|
||||
|
||||
## Политика
|
||||
|
||||
- `blacklist` — default accept, apply deny set
|
||||
- `whitelist` — default drop, apply allow set (+ lo/established на Linux)
|
||||
- Overrides и clone-from бампят `policy_generation`
|
||||
|
||||
## Auth
|
||||
|
||||
- Portal SSO app id **`fw`**, permissions `fw:*`
|
||||
- Agent bearer token (sha256 hash в БД)
|
||||
@@ -0,0 +1,44 @@
|
||||
# Интеграция auth-portal ↔ EvoFirewall
|
||||
|
||||
App id: **`fw`**.
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
Browser → EvoFirewall UI (нет token)
|
||||
→ redirect AUTH_PORTAL_URL/?return_to=…/auth/callback
|
||||
→ login
|
||||
→ redirect return_to#access_token=…
|
||||
→ /auth/callback сохраняет token
|
||||
→ API Authorization: Bearer <JWT>
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
| Permission | UI |
|
||||
|------------|-----|
|
||||
| `fw:dashboard:read` | `/` |
|
||||
| `fw:agents:read` / `write` | `/agents` |
|
||||
| `fw:lists:read` / `write` | `/lists` |
|
||||
| `fw:policies:read` / `write` | `/rules`, overrides |
|
||||
| `fw:stats:read` | `/stats` |
|
||||
| `fw:settings:admin` | `/settings`, install-context |
|
||||
|
||||
## Env
|
||||
|
||||
```env
|
||||
AUTH_REQUIRED=true
|
||||
AUTH_JWT_SECRET=<тот же JWT_SECRET портала>
|
||||
AUTH_ISSUER=https://auth.shnt.top
|
||||
AUTH_PORTAL_URL=https://auth.shnt.top
|
||||
PUBLIC_BASE_URL=https://fw.example.com
|
||||
EVOFW_ENROLL_SEED=<hex/seed>
|
||||
```
|
||||
|
||||
```env
|
||||
# apps/web/.env.local
|
||||
VITE_AUTH_ENABLED=true
|
||||
VITE_AUTH_PORTAL_URL=https://auth.shnt.top
|
||||
```
|
||||
|
||||
В portal Admin → Apps выдайте app `fw` и нужные `fw:*`. URL в App Switcher: origin EvoFirewall.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Интеграция EvoBGP → EvoFirewall
|
||||
|
||||
EvoFirewall использует EvoBGP как **источник префиксов** для списков типа `evobgp_community`.
|
||||
|
||||
## Настройка
|
||||
|
||||
В UI Settings или `settings` table:
|
||||
|
||||
- `evobgp_api_url` — base URL EvoBGP API
|
||||
- `evobgp_api_token` — API key (viewer+)
|
||||
|
||||
При refresh списка:
|
||||
|
||||
1. `GET {api}/v1/directories/communities/{id}/prefixes` (если доступен)
|
||||
2. fallback `GET {api}/v1/lookup?q={community_id}`
|
||||
|
||||
## Список
|
||||
|
||||
Создайте IP list type `evobgp_community` с `config.community_id`. Cron / кнопка Refresh обновляет entries и бампит generation агентов.
|
||||
|
||||
Firewall-подсистема в EvoBGP **удалена** (hard cutover) — клиенты переустанавливаются на EvoFirewall agents.
|
||||
@@ -0,0 +1,80 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: EvoFirewall API
|
||||
version: 0.1.0
|
||||
description: Centralized firewall control plane
|
||||
paths:
|
||||
/health:
|
||||
get:
|
||||
summary: Liveness
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
/api/v1/dashboard:
|
||||
get:
|
||||
summary: Dashboard KPI
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Stats
|
||||
/api/v1/agents:
|
||||
get:
|
||||
summary: List agents
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Agents
|
||||
/api/v1/lists:
|
||||
get:
|
||||
summary: List IP lists
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Lists
|
||||
post:
|
||||
summary: Create IP list
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Created
|
||||
/api/v1/rules:
|
||||
get:
|
||||
summary: List policy rules
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Rules
|
||||
post:
|
||||
summary: Create policy rule
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Created
|
||||
/v1/agent/enroll:
|
||||
post:
|
||||
summary: Enroll agent (public + seed)
|
||||
responses:
|
||||
'201':
|
||||
description: Pending agent
|
||||
/v1/agent/policy:
|
||||
get:
|
||||
summary: Evaluated policy for agent
|
||||
security: [{ agentToken: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Policy
|
||||
/v1/agent/apply-report:
|
||||
post:
|
||||
summary: Apply report + packet stats
|
||||
security: [{ agentToken: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
agentToken:
|
||||
type: http
|
||||
scheme: bearer
|
||||
Reference in New Issue
Block a user