guard/TODO.md
loki5512344 aa615a1141
fix: XDP unsafe loader + Redis sync; enforce 250-line/4-file layout limits
- xdp: CString for if_nametoindex (was UB), real detach via prog fd
  (fabricated borrow_raw(-1) silently never detached), SAFETY comments,
  saturating expiry math; +5 unit tests
- redis: real pubsub reconnect with exponential backoff (was sleep+return);
  KEYS -> SCAN in heartbeat sweep
- ci: cargo test --all-features, repo-gates job — module size gate
  (scripts/check_module_size.sh, ratchet baseline) + default-secrets grep
- refactor src/ to <=250 LOC/file, <=4 .rs/dir without behavior change;
  thin bins (rampart.rs 330 -> 6 LOC), new app/, subnet/, intel/,
  profile/, prefix/, challenge/, filter/, probe/, inventory/, metrics/, node/
- docs: TODO v5.0 (status refresh, new rules, findings backlog),
  README quickstart now matches real binaries
- verify: fmt/clippy -D warnings/test --all-features (164 tests)/clang XDP green
2026-09-15 23:55:17 +02:00

262 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Rampart — Development TODO & Roadmap
> Живой документ. Философия: **KISS → DRY → SOLID → YAGNI**.
>
> v0.3.0-dev — big-bang редизайн: из Minecraft-специфичной защиты в **универсальную
> L3/L4/L7 платформу сетевой защиты**. MC-код, Java-плагины и dashboard удалены
> (доступны в git-истории до тега v0.2.0).
---
## 0. Принципы разработки
### KISS
- Не добавляй абстракцию до третьего повторения.
- **Функция ≤ 60 строк, файл ≤ 250 строк, ≤ 4 .rs-файлов на папку** (жёсткий лимит;
больше — декомпозиция или группировка доменами с ре-экспортами в mod.rs).
Гейт: `scripts/check_module_size.sh` + ratchet-базлайн `.module_size_baseline`
(легаси — WARN, новые нарушения — FAIL; после рефакторинга `--update-baseline`).
- Не используй generics где хватит `&str` и `Vec<u8>`.
### DRY
- Повтор > 2 раз → выноси, но лучше копипаста чем неправильная абстракция.
### SOLID (Rust)
- **S**: один файл = одна ответственность
- **O**: расширяй через трейты (`ProtocolHandler`, `Filter`, `StateStore`)
- **L**: `dyn Filter` — любая реализация без side effects
- **I**: маленькие трейты вместо одного God-trait
- **D**: core зависит от trait-ов, не от Redis/ClickHouse напрямую
### YAGNI
- Не пиши BGP до v0.6, WASM-плагины до стабилизации compile-time API.
- Не добавляй feature flag если фича не готова.
### Rust-специфичные
1. `unwrap()` — только в main() и тестах
2. `unsafe` — только в xdp/, комментарий `// SAFETY:` обязателен
3. `clone()` осознанно, профилируй hot path
4. Блокирующие операции → `spawn_blocking`
5. Логи: `tracing::info!` / `debug!` / `error!`
6. Метрики: register один раз при старте, инкремент в hot path
---
## 1. Целевая структура (v0.3)
```
guard/
├── Cargo.toml # ОДИН пакет rampart, features = ["protocol-http", ...]
├── scripts/ # check_module_size.sh (гейт 250/4), check_default_secrets.sh
├── src/
│ ├── bin/{rampart, rampart-manager, rampart-cli, rampart-tui}.rs # тонкие, логика в lib
│ ├── app/ # thin-main: runtime wiring, services (spawn-циклы)
│ ├── engine/ # listener, tunnel; challenge/ (pow+difficulty), subnet/ (tracker+monitor)
│ ├── filter/ # blacklist, rate_limit, geo — trait Filter
│ ├── traffic/ # hook + prefix/ (key+stats) + intel/ (ewma,detector,reputation) + profile/ (profiler,alert)
│ ├── store/ # redis (+ trait StateStore)
│ ├── manager/ # api/ (+ api/inventory/), auth/, sync/
│ ├── cli/ # команды; commands/node/ (status,drain,emergency)
│ ├── config/ # config + sections/{edge,platform,detect}
│ ├── tui/ # app/state/ui + metrics/ (prometheus,fetch)
│ ├── protocol/ # trait ProtocolHandler + registry; http/ под фичей
│ └── xdp/ # filter/ (attach,maps), probe/ (diagnostics/,stats,metrics), globals, noop
├── xdp/
│ ├── core/ # universal_filter.c + maps/stats/config/common.h + prefix_stats/syn_challenge
│ └── hooks/hook_api.h # контракт подключаемых BPF-протокол-хуков
├── tests/ # интеграционные (вне гейта 4-файлов: cargo требует 1 файл = 1 бинарь)
└── docs/ # kb/ (knowledge base) + research/ + ops-доки
```
## 1a. Статус после редизайна (2026-08-24)
| Что | Статус |
|-----|--------|
| plugins/ velocity+paper, dashboard/ | ✅ удалены (git-история) |
| crates/* → единый пакет `rampart` + src/bin | ✅ сделано |
| MC-код (handshake, death_code, varint, hostname-HMAC) | ✅ удалён полностью |
| PoW как универсальный hashcash (`engine/challenge.rs`) | ✅ сохранён |
| XDP: universal L3/L4 фильтр + hooks API | ✅ код готов, clang build OK |
| IPv6 баг в XDP (daddr→saddr) | ✅ исправлен |
| Knowledge Base docs/kb (attacks, defense-levels, practice) | ✅ написана, двуязычная |
| README + architecture.md под новую концепцию | ✅ переписаны |
| cargo build / clippy -D warnings / test | ✅ зелёные |
---
## 2. Ближайшие задачи (v0.3)
### Subnet-level detection (ботнет с ротацией IP) — ✅ готово (2026-08/09)
- [x] **XDP**: карта `prefix_stats` (LRU_HASH, ключ /24 v4 | /64 v6) — счётчики SYN/pps
per-префикс (xdp/core/prefix_stats.h, трафик-слой: src/traffic/prefix/).
- [x] **Detector**: превышение порога префиксом при IP под лимитом → флаг подсети
(src/traffic/intel/detector.rs, src/engine/subnet/).
- [x] **Мягкая эскалация**: monitor → strict_limit → challenge → block
(SubnetVerdict-лестница; блок /24 идёт через ban_cidr, не слепой hard-ban).
- [x] Блок подсети через `blacklist_map` (LPM trie) — `XdpFilter::ban_cidr`.
### Движок без протоколов — сделать полезным — ✅ готово
- [x] **Первый протокол-плагин**: `protocol-http` — HTTP/1.1 request-head анализ
(src/protocol/http/, tests/http_protocol.rs).
- [x] **TCP-proxy режим**: tunnel.rs + ProtocolHandler интегрированы в listener/app wiring.
- [x] **Fail-fast сообщение** при пустом registry (`ProtocolRegistry::primary()`).
### Подключение мёртвого интеллекта (правило: «мёртвый код = баг») — ✅ готово
- [x] Traffic Intel в hot path: AttackDetector/IpReputation → метрики + auto-ban
(src/traffic/hook.rs, src/engine/tunnel.rs, src/app/services.rs).
- [x] Blacklist: `clear_expired()` по таймеру (src/app/).
- [x] RateLimiter: TTL-эвикция idle bucket'ов.
### Безопасность — ✅ кроме ролей
- [x] Rate limiter на login endpoint manager API (per-IP, tests в api/auth.rs).
- [x] JWT: audience-валидация, secret ≥ 32 байт fail-fast (rampart-manager.rs).
- [ ] JWT-роли: сейчас единственный hardcoded `admin`; RBAC-ролей нет — либо убрать поле,
либо делать роли (решение отложить до второго потребителя).
- [x] Redis: `KEYS` → `SCAN` (scan_options), pubsub-подписчик — честный reconnect
с экспоненциальным backoff (src/store/redis.rs).
### XDP
- [x] Verifier-проверка на реальном ядре (live-тест 2026-09: два бага RST-challenge найдены и
исправлены, d6bcae5).
- [x] Rust loader (`src/xdp/filter/`): open/load/attach, patch глобалов G_* из config.toml
(src/xdp/globals.rs), CString-safe if_nametoindex, реальный detach по fd прогрессы.
- [ ] Ringbuf events → blacklist: `drain_events()` сейчас только логирует debug;
нужен матчинг события → `ban_ip` (перенести из «loader», боится ошибок в data path).
- [ ] Smoke-test attach в CI (VM runner с CAP_BPF) + netns+veth харнесс — вывод №7 из
конкурентного анализа, приоритет v0.4.
### Документация
- [x] docs/deployment.md, configuration.md, runbook.md — старых крейтов/MC не упоминают (grep чисто).
- [x] docs/kb/README.md — индекс KB со ссылками.
- [x] TUI (ratatui): live-метрики из Prometheus endpoint — готово (src/tui/, 564613b).
## 2a. Раунд 2026-09-15 — исправлено по итогам ревью
- **unsafe-баги XDP-лоадера** (src/xdp/filter/): `&str.as_ptr()` без NUL в `if_nametoindex` → `CString`;
фиктивный `borrow_raw(-1)`-fd в `unload()` → реальный detach по fd прогрессы с propagatable ошибкой;
`unsafe impl Send` получил `// SAFETY:`; `saturating_mul` в expiry. +5 юнит-тестов.
- **Redis**: fake-reconnect pubsub (sleep+return) → настоящий reconnect-loop с backoff;
`KEYS` → `SCAN` в heartbeat.
- **CI**: `cargo test --all-features` (раньше тесты фич не гонялись); job `repo-gates`:
гейт 250/4 + grep дефолтных секретов; Makefile `ci` обновлён.
- **README**: несуществующие `rampart-core`/`rampart config init` → реальные команды;
таблица компонентов/плагинов приведена к коду (http готов, minecraft удалён, добавлен rampart-tui).
- **Рефакторинг под новые лимиты 250/4** без изменения поведения: app/, challenge/, subnet/,
prefix/, intel/, profile/, commands/node/, api/inventory/, tui/metrics/, filter/, probe/;
bin-файлы тонкие (rampart.rs: 330 → 6 строк).
### Новые найденные проблемы (чинить в v0.4)
- [ ] `cargo check --no-default-features` сломан исторически: manager/sync и store ссылаются
на redis без `#[cfg(feature = "store-redis")]` — нарушение «features additive».
- [ ] `src/app/runtime.rs`: узкий `#[allow(clippy::exit)]` — паллиатив после переноса main-логики
в lib; правильно — возвращать exit-код из `run()` вместо `process::exit`.
- [ ] IPv6-банов в XDP-putи нет (`ban_cidr` bail'ит на v6) — IPv6-паритет (вывод №8).
## 3. Backlog
- [ ] protocol-gRPC plugin (после http)
- [ ] BPF hook #1 реальный: HTTP поверх XDP (rate-limit до userspace)
- [ ] GeoIP/ASN reputation (enum есть, реализации нет)
- [ ] Bloom filter для blacklist
- [ ] io_uring runtime (feature flag)
- [ ] ML anomaly detection (Isolation Forest)
- [ ] Fuzzing парсеров (`cargo-fuzz`)
- [ ] BGP Anycast (AS + /24)
---
## 3a. Бенчмарк-конкуренты: чем превзойти
> Все репо склонированы в `ref/` (gitignored). Анализ issues/PRs проведён 2026-08-24
> через gh по трекерам конкурентов. Ниже — выжимка «что у них болит и что берём».
### Карта конкурентов
| Проект | Что это | Похож на Rampart тем, что | Что взять |
|--------|---------|---------------------------|-----------|
| [eBPFsentinel](https://github.com/ebpfsentinel/ebpfsentinel) | Rust, один бинарник: firewall+IDS+DDoS через XDP/TC/uprobe | Ближайший аналог, та же архитектура | Rootless BPF token (kernel 6.9+); tail-call цепочки; MITRE-теги алертов; Swagger UI |
| [CrabShield](https://github.com/aleksgrim/crab-shield) | Rust + XDP, гибрид L7→L3 | «Умный юзерспейс, кара в ядре» | Static musl бинарник; reaper истекающих банов; (log-tailing НЕ брать — хрупко) |
| [lnvps_fw](https://github.com/LNVPS/api) | XDP+TC защита VDS | Прямо наша ниша | ⭐ SYN-proxy в XDP; port learning из TC egress; лестница PORT_FILTER→SYN_PROXY→SOURCE_BLOCK + spoof gate; netns+veth harness |
| [Oubliette](https://f0o.dev/projects/2026/04/oubliette/) | Linerate scrubber | Решает нашу боль с PoW | ⭐ RST-challenge: SYN-ACK с неверным ACK → спуф молчит, живой клиент шлёт RST → whitelist. Совместимо с любым клиентом |
| [Couic](https://github.com/fcsc-fr/couic) (CERT Франции) | XDP-фаервол + REST API | Наш manager API | Anti-lockout; теги+TTL записей; OpenAPI spec; синк инстансов; fail2ban-интеграция |
| [gamemann/XDP-Firewall](https://github.com/gamemann/XDP-Firewall) (~830★) | Классический C XDP-фаервол | Референс по XDP | Pinned maps для внешнего управления; их issues = карта граблей верификатора |
| [gen0sec/synapse](https://github.com/gen0sec/synapse) | NDR: eBPF + JA4-фингерпринты + ratatui TUI | TUI как наш план | JA4+/JA4T фингерпринтинг (бан по отпечатку); fallback-цепочка XDP→nftables→iptables |
### Топ-10 выводов из их issues/PRs (приоритет)
1. **Диагностика окружения при старте** — проверять ядро/BTF/driver NIC до загрузки,
человекочитаемый вердикт. ≈80% issues XDP-Firewall — про attach на неподдерживаемом
окружении (#70/#71/#9/#44). Печатать режим (native/generic) честно.
2. **Эскалационная лестница защиты** (lnvps_fw): pass-all steady state → PORT_FILTER →
SYN_PROXY (tail-call, keyed cookie, ротация секрета) → SOURCE_BLOCK только со spoof-gate.
3. **RST-challenge** (Oubliette) вместо мёртвого текстового PoW — универсально совместимо.
4. **REST API + OpenAPI + pinned maps**: динамические IP-списки без перекомпиляции —
самый частый feature request (#79/#77/#78 у gamemann); web-панель так и не сделана автором = свободная ниша.
5. **Anti-lockout + per-port баны**: слепой XDP_DROP по IP = self-lockout по SSH
(crab-shield docs). Whitelist обязателен, но не единственная защита.
6. **LRU во всех data-path maps** — иначе silent default-deny под атакой (netshield DD-003).
Per-src-IP rate limit не работает против spoofed flood 50–100 Mpps (gamemann #45) —
нужны per-port/per-subnet/flow агрегаты.
7. **netns+veth тестовый харнесс** + eBPF test_run тесты в CI (подтверждено в 2 проектах,
отсутствует у всех) — наше конкурентное преимущество в надёжности.
8. **IPv6-паритет с первого дня** + VLAN/QinQ парсинг (issue #75 висит годами).
9. **Rootless BPF token как опция**, fallback CAP_BPF для ядер 5.15+ — не повторять жёсткий
floor 6.9+ (ebpfsentinel отсёк enterprise) и не требовать root (crab-shield).
10. **События атак наружу с первого дня**: poll-and-persist, дедуп алертов на переходе
состояния (урок LNVPS #331 — отложили = дыра в продукте).
### Наши козыри (чем превзошли уже)
- Двуязыная Knowledge Base (docs/kb/) — educational killer-feature, нет ни у одного конкурента
- Один Rust-бинарник без C-зависимостей сборки (класс сегфолтов/libbpf-hell gamemann исключён)
- Честные бенчмарки: цифры только с отчётами, методология опубликована
- Модульный лимит ≤300 строк + no-dead-code политика в CI
---
## 4. Anti-Regression — правила приёмки
1. **No dead code**: каждый `pub` имеет вызова вне `#[cfg(test)]`.
2. **Config field = потребитель**: нет поля без использования.
3. **Метрика регистрируется → обновляется**: единственный writer на каждую метрику.
4. **Feature flag = сборка в CI**: `--all-features` зелёный, иначе фичи нет.
5. **По умолчанию безопасно**: нет дефолтных секретов; отсутствие обязательного env = fail-fast.
6. **Интеграционный тест на слой**: config parse, filter logic, registry fail-fast (есть);
новый слой = новый тест.
7. **Файл ≤ 250 строк, папка ≤ 4 .rs**: CI-гейт `scripts/check_module_size.sh`
(ratchet-базлайн `.module_size_baseline`: легаси — WARN, новые нарушения — FAIL).
8. **CI guardrails**: `cargo clippy --all-targets -- -D warnings`, `cargo test`,
clang-build xdp/core/universal_filter.c, grep на `changeme`.
9. **README/TODO не врут**: каждое число имеет ссылку на тест или отчёт.
## 5. Definition of Done
```
☐ cargo check / cargo test проходят
☐ cargo clippy --all-targets -- -D warnings — 0 warnings
☐ cargo fmt --check проходит
☐ Ни один файл не превышает 250 строк; ни в одной папке src/ больше 4 .rs-файлов
☐ Unit тесты покрывают happy path + 2+ error cases
☐ Нет мёртвого кода: pub без вызовов, конфиг-поле без потребителя, метрика без writer
☐ Нет дефолтных секретов
☐ README соответствует коду
☐ Документация обновлена
☐ CI зелёный
```
## 6. Anti-Patterns
```
❌ Тесты после кода. Пиши вместе.
❌ Файл > 250 строк или > 4 .rs в папке — сигнал декомпозировать/сгруппировать немедленно.
❌ TODO в коде без issue.
❌ Мёртвый код: pub без вызовов, конфиг-поле без потребителя, метрика без writer.
❌ «Бумажный слой»: фича описана, но не вызывается.
❌ Дефолтный секрет.
❌ Парсер за «один read» — TCP-поток приходит фрагментами.
❌ Feature flag, который не собирается в CI.
```
---
*Версия: 5.0 | Обновлён: 2026-09-15 (bug-fix раунд: XDP unsafe, Redis reconnect/SCAN, CI-гейты, лимиты 250/4)*