Commit Graph

3 Commits

Author SHA1 Message Date
CyberMind
45e5f8aa84
fix(secubox-toolbox): persist AP iface IP via systemd-networkd (ref #482) (#484)
Sans ce fix, à chaque débranchement+rebranchement de la clé USB Wi-Fi,
l'iface perd son IP 10.99.0.1/24. dnsmasq répond "DHCP packet received
which has no address" et tous les clients VILLAGE3B restent en limbo.

## Implementation

- conf/ap-iface.network.j2 : template Jinja rendu vers
  /etc/systemd/network/10-secubox-toolbox-ap.network
- scripts/toolbox-up : rend + applique + recharge systemd-networkd
  (fallback ip-addr-replace si networkd indisponible)

Match=Name=<iface>, Address=<gateway>/24, ConfigureWithoutCarrier=yes
pour que l'IP s'applique AVANT que hostapd ne porte le radio.

## Bump

1.4.0 → 1.5.0-1~bookworm1

## Test E2E sur gk2 (2026-06-04)

- toolbox-up rendu le fichier depuis /etc/secubox/toolbox.toml ✓
- networkctl reload appliqué ✓
- ip addr show wlxa854b2428fbb → 10.99.0.1/24 OK ✓
- À tester : unplug → replug → vérifier IP réapparaît auto

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-06-05 06:27:48 +02:00
CyberMind
1606b4f9e2
feat(secubox-toolbox): Phase 1.5 — transparency banner + PDF/HTML report + DPI/SOC/Cookies metrics (ref #477) (#479)
* feat(secubox-toolbox): v1.2.0 — transparency banner + PDF report + HTML live + README (ref #477)

## Phase 1.5 ToolBoX features

### MITM transparency banner injection
- New mitmproxy addon `inject_banner.py` : injects <script> avant </body> sur
  toute response text/html, montre "Gondwana ToolBoX R2 inspection active" +
  SHA1 CA. Idempotent, fixed top, z-index max, closable.
- CSPN R2 requirement : user being inspected MUST see + verify CA fingerprint.

### CA fingerprint endpoints
- /api/v1/toolbox/ca/fingerprint : SHA1+SHA256+subject
- /api/v1/toolbox/client-status : captive_subnet, r2_consented, validated,
  ca_fingerprint_sha1, mac_hash, session_url — for banner JS.

### PDF + HTML live report
- /report/{token} : HMAC-signed PDF (24h TTL)
- /report/me : PDF for current client (derive mac via ARP)
- /report/me/html : live HTML report with auto-refresh 15s, embedded in
  captive portal. Same content as PDF but stylé P31 light skin.
- reports.py : full PDF rendering via fpdf2 (pure Python) :
  identifiant anonyme, métriques, apps détectées, score risque, indicateurs,
  apps cert-pinned protégées, URLs inspectées, recommandations, rétention,
  + section Support/Payment refs (Liberapay, support email, GitHub issues,
  contact pour audit/déploiement collectivité).
- splash + success templates : link "Télécharger mon rapport PDF" et
  référence à `/report/me/html` live.

### Bug fixes
- config.resolve_secret : now accepts 0640 (group read) — was rejecting any
  group/world perm. Fix needed for sel-rotatif sous secubox-toolbox group.
- Route order : /report/me et /report/me/html déclarés AVANT /report/{token}
  pour éviter le wildcard match qui retournait 404 "report not found".
- reports.render_pdf : safe word breaking pour URLs > 60 chars (évite
  fpdf2 FPDFException "Not enough horizontal space").
- ca-init : 0750 root:secubox-toolbox au lieu de 0700 root:root.
- postinst : idempotent perm fix pour /etc/secubox/secrets (parent 0750
  root:secubox-toolbox pour permettre traversée par le service user).

### Documentation
- README.md complet : mission, architecture E2E ASCII art, API routes,
  install, config TOML, garde-fous CSPN, sections rapport PDF, maintenance,
  WebUI admin, références bornes & branding VILLAGE3B.

### Tested E2E sur gk2 (2026-06-04)
- iPhone 10.99.0.214 télécharge /report/me → 200 OK (PDF 3KB, 2 pages)
- Token-based /report/{TOKEN} → 200 OK (PDF complete)
- /api/v1/toolbox/ca/fingerprint → 200 OK (SHA1 + SHA256 + subject)
- /api/v1/toolbox/client-status → 200 OK (all booleans + fingerprint)
- mitmproxy addon inject_banner loaded
- WebUI menu category=wall (Wall 🛡️) visible

### Pending tests
- iPhone test : navigate https://example.com → vérifier banner injection visible
  (cert pinning Apple/Signal/banking refuse OUR cert — that's BY DESIGN security)

Closes #477.

* feat(secubox-toolbox): v1.3.0-1.4.0 — DPI/Cookies/SOC integration + WebUI metrics (ref #477)

## 1.3.0 — local_store addon + report DPI/Cookies sections

### local_store.py mitmproxy addon
Captures ALL flows directly into toolbox.db without external module
dependencies (cookies.sock / dpi.sock / soc.sock / threat-analyst.sock
are Phase 2 wireups). Hooks :
- request → dpi (host, method, path, user_agent)
- response → cookies (set_cookie + cookie counts) and soc (suspicious patterns)
- tls_clienthello → ja4 (SNI, ALPN protocols, cipher count)

MAC hashed with daily-rotating sel for anonymization. Insert capped at 500
events/24h per MAC. SQLite already auto-purges after 24h.

### _aggregate_session enrichi
Reads per-MAC events from SQLite to compute :
- DPI : top hosts ranking + methods histogram + UA list
- Cookies : total set + total sent + per-URL detail
- SOC : indicators + risk_score (sum of weights)
- JA4 : unique SNIs + ALPN protocols

### Report renderers updated
- PDF (reports.py) : new sections DPI top hosts, Cookies trackers,
  SOC indicators, JA4 TLS fingerprints. All gracefully skipped if empty.
- HTML live (report-live.html.j2) : same sections + tables, P31 light skin.

### Bug fix
- success.html : "Statut session" button → /report/me/html (was /status JSON).

## 1.4.0 — WebUI admin metrics + per-client reports

### New API endpoints (admin)
- GET /admin/metrics : events_by_source 24h + clients_active + MITM stats
- GET /admin/clients/{mac_hash}/report : per-client PDF download
- GET /admin/clients/{mac_hash}/events : per-client recent event summary

### WebUI updated (www/toolbox/index.html)
- New cards : Live metrics 24h (dpi/cookies/soc/ja4/avatar counts + MITM stats)
- Clients table : Actions column with "PDF" download link + "Events" detail toggle
- Client detail panel (collapsible) : event summary per source + 30 recent events
  + PDF download button
- refreshAll() now polls /admin/metrics too

### DNS hijack VILLAGE3B aliases
dnsmasq-ap conf adds :
- village3b, village3b.local, village3b.lan, village3b.cabine → 10.99.0.1
- cabine, cabine.gondwana → 10.99.0.1
- portal, portal.local → 10.99.0.1
- toolbox, toolbox.local → 10.99.0.1
- gondwana, rapport → 10.99.0.1

nftables : DNAT priorité haute ip daddr 10.99.0.1 tcp dport 80 → :8088 portal
(so http://village3b works directly for ALL clients in captive subnet,
bypassing the mitmproxy redirect for the explicit portal URL).

## Live test E2E sur gk2 (2026-06-04 ~08:35)
- iPhone GET /report/me → 200 OK PDF download
- /admin/metrics → 200 with 1 DPI event captured (local_store working)
- /admin/clients/{mac}/report → PDF generated per client
- dig +short village3b @10.99.0.1 → 10.99.0.1 (all aliases)
- Splash served on Host: village3b → correct VILLAGE3B page

## Filed for follow-up
- #478 : Round Eye gadget integration (emoji cabine display polling /admin/metrics)

Ref #477.

* fix(secubox-toolbox): postinst adds secubox-toolbox to systemd-journal group (ref #477)

Without this, the API metrics endpoint can't read journalctl output and
MITM stats (connections/tls_pinned/unique_hosts) appear as 0 in the
WebUI, while the SQLite-based DPI/cookies/SOC/JA4 stats work fine
(those don't need journal access).

Live fix applied on gk2 — postinst now does it idempotently for fresh
installs and upgrades.

---------

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-06-04 08:39:13 +02:00
CyberMind
8701c8f989
feat(secubox-toolbox): Phase 1 ToolBoX — captive AP + MITM analyzer + CA distribution (ref #475) (#476)
* feat(secubox-toolbox): Phase 1 ToolBoX captive + MITM analyzer (ref #475)

Productionize le PoC captive portal (live sur gk2 depuis 2026-06-04) en
package Debian dédié `secubox-toolbox` 1.0.0 (parent #474).

Note rename: nom `secubox-portal` déjà pris par le portail d'auth JWT du
dashboard SecuBox → nomenclature `secubox-toolbox` cohérente avec la
framing user ("Module ToolBoX") + concept cabine numérique.

## Périmètre Phase 1

### Backend FastAPI (`secubox_toolbox/`)
- `models.py` — pydantic Config (ap/dhcp/portal/r2/addons/quarantine) + DTOs
- `config.py` — TOML loader + resolve_secret(file://)
- `mac.py` — IP→MAC via `ip neigh` + hash HMAC-SHA256 sel rotatif daily
- `nft.py` — wrappers nftables (add/del/is_validated/is_consented)
- `store.py` — SQLite (consents/clients/events/reports + purge auto)
- `reports.py` — HMAC token éphémère (Phase 4 = PDF complet)
- `ca.py` — gen self-signed CA + render iOS mobileconfig + Android DER
- `api.py` — 13 routes : splash, captive probes, /accept, /status,
  /ca/{mobileconfig,android.crt,install-help}, /report/{token},
  /admin/{config,clients}, /health
- `app.py` — Uvicorn entry + purge async loop

### Templates Jinja2 (`conf/`)
- `splash.html.j2` — page captive P31 light + bannière R2 consent
- `success.html.j2` — page post-validation
- `ca-help.html.j2` — tutoriel install par-OS (iOS/Android/Desktop)
- `ios.mobileconfig.j2` — Apple plist profile pour install CA
- `nft-toolbox.nft.j2` — règles nftables Jinja (table inet toolbox)
- `toolbox.toml` — config TOML par défaut

### mitmproxy addons (`mitmproxy_addons/`)
- `_common.py` — helpers fire-forget POST + MAC lookup
- `cookies.py` → POST /run/secubox/cookies.sock/inject
- `dpi.py` → POST /run/secubox/dpi.sock/classify
- `avatar.py` → POST /run/secubox/avatar.sock/fingerprint (UA + Client Hints)
- `ja4.py` → POST /run/secubox/threat-analyst.sock/ja4 (TLS ClientHello)
- `soc_relay.py` → POST /run/secubox/soc.sock/event (indicateurs basiques)

### Systemd / scripts
- `secubox-toolbox.service` — FastAPI portal (uvicorn 10.99.0.1:8088)
- `secubox-toolbox-mitm.service` — mitmdump transparent (10.99.0.1:8080)
  avec les 5 addons pré-chargés
- `scripts/toolbox-up` — render+apply nftables depuis TOML
- `scripts/ca-init` — gen CA self-signed 10y (idempotent)

### Packaging Debian
- `debian/control` — Architecture: all, deps complets (mitmproxy + nftables...)
- `debian/postinst` — crée user secubox-toolbox, sel rotatif daily, CA self-signed,
  enable services (sans start auto — opérateur doit configurer)
- `debian/conffiles` — /etc/secubox/toolbox.toml
- 2 services systemd installés (primary via dh_installsystemd, secondary manuellement)

### WebUI admin
- `/usr/share/secubox/www/toolbox/index.html` — dashboard P31 light avec
  carte Config (SSID, iface, DHCP, R2 toggle), Clients actifs, Liveness
  + auto-refresh 10s
- `menu.d/26-toolbox.json` — category=security, icône 📡

## Garde-fous respectés
- /etc/secubox parent 0755 (cf. #468) — ne touche QUE les sous-paths
- /run/secubox parent 1777 root:root (cf. #471) — ne touche jamais le parent
- secrets/toolbox-mac-salt chmod 0640 root:secubox-toolbox
- CA key chmod 0600
- SQLite store ([[feedback_prefer_sqlite]])
- R2 = opt-in explicite (CSPN), MAC hashing avec sel daily rotatif

## Build
- `dpkg-buildpackage -b` → secubox-toolbox_1.0.0-1~bookworm1_all.deb (~20 KB)
- 13 routes FastAPI valides
- syntax check Python OK pour 16 fichiers

## Hors périmètre Phase 1 (per #474 roadmap)
- SOC scoring/correlation → Phase 2
- OPAD auto-quarantine decision tree → Phase 3
- PDF report complet + ECH JA4 advanced → Phase 4
- Android APK CA profile signé → Phase 4

* fix(secubox-toolbox): menu category=wall + postinst CA perms (ref #475)

- menu.d/26-toolbox.json : category 'security' → 'wall' (per user feedback —
  use one of the 6 built-in CATEGORY_META standards : auth/wall/boot/mind/
  root/mesh ; ne pas générer de nouvelles catégories). ToolBoX fits in the
  Wall 🛡️ category alongside WAF/CrowdSec/IDS modules.

- debian/postinst : ajoute le fix de perms après le ca-init. Le script
  ca-init crée /etc/secubox/toolbox/ca/ en 0700 root:root par défaut
  (sécurité maximale) mais le service secubox-toolbox tourne sous l'user
  secubox-toolbox et ne peut donc pas lire le CA. On chown root:
  secubox-toolbox + chmod 0750 pour autoriser la lecture par le group.
  Sans ce fix : 500 sur /api/v1/toolbox/ca/mobileconfig (PermissionError).

---------

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-06-04 07:55:24 +02:00