Upstream sing-box-lx already ships a docs/ mkdocs site; keep our project docs separate and unambiguous in docs-shater/ (parallels upstream's docs-lx/). Updated all references in README.md, CLAUDE.md, CONTEXT.md, ARCHITECTURE.md.
4.3 KiB
Architecture (v0.2)
One Go binary — a fork of sing-box-lx with our product embedded — runs the proxy engine, the control plane, the DNS filter, and the admin-panel web server in a single process. OpenWrt integration (a thin LuCI launcher + procd/system glue) wraps it. Config is UCI desired-state; the daemon renders and applies it; telemetry flows back to the panel.
Diagrams render on Gitea/GitHub.
1. Components & repository layout
flowchart TB
subgraph BIN["shaterd — one binary (fork of sing-box-lx)"]
ENG["sing-box engine (upstream tree)\nprotocols · Reality · AmneziaWG 2.0 · DNS · routing · stats"]
CTRL["shater/ control-plane\nUCI model · config gen · apply/rollback · nft/routing · reconcile"]
FILT["shater/ DNS filter + blocklists + per-device policy"]
STAT["shater/ stats aggregator (per-domain/client/device)"]
PANEL["panel/ admin web server + embedded SPA (own port, token auth)"]
end
subgraph WRT["OpenWrt glue (openwrt/)"]
LUCI["thin LuCI app — mini dashboard + Open-panel button"]
PROCD["procd init · hotplug · uci-defaults · fw4/routing"]
end
LUCI -->|"ubus: mint token"| PANEL
PROCD --> BIN
CTRL --> ENG
FILT --> ENG
ENG --> STAT
STAT --> PANEL
Overlay dirs (added on top of the upstream sing-box-lx tree, conflict-free):
shater/ (Go: control-plane, DNS filter, stats, engine host), panel/ (admin
SPA + its Go server), openwrt/ (LuCI thin app, procd/shater-core, Makefiles,
feed/CI), docs-shater/.
2. Auth handoff — LuCI → admin panel
sequenceDiagram
participant U as Browser (LuCI, authed)
participant L as LuCI (thin app)
participant D as shaterd (panel server, own port)
U->>L: click "Open panel"
L->>D: ubus mint_token (LuCI session ACL-checked)
D-->>L: short-lived one-time token
L-->>U: redirect https://router:PORT/?t=TOKEN
U->>D: GET /?t=TOKEN
D-->>U: validate + set session cookie, drop token
U->>D: SPA ⇄ panel API (session)
The panel never runs its own login; it trusts a token that only an authenticated, ACL-permitted LuCI session could have minted. Tokens are single-use and short-TTL.
3. Data plane — traffic path
flowchart LR
C["LAN client"] -->|"nft tproxy, mark → tproxy port"| IN["sing-box tproxy inbound (sniff SNI/Host/QUIC)"]
IN --> R{"route: rule match — src / dst / list / geo / client"}
R -->|"proxied"| OUT["outbound / selector (balancer, chain)"]
R -->|"direct"| DIR["direct (flow-offload on)"]
R -->|"blocked"| BLK["block"]
OUT --> NET["exit — VLESS/Reality/AmneziaWG2/Hysteria2/…"]
Reliability (ported from v0.1): own nft table inet shater + own marks/tables
(never touch fw4); atomic validate→stage→swap; commit-confirm rollback;
idempotent reconcile under flock; management-bypass always; fail-closed
kill-switch (dead group → block, not a silent direct leak).
4. DNS + filtering + stats
flowchart LR
C["client :53"] -->|"hijack"| DNS["sing-box DNS (in-process)"]
DNS --> FILT{"shater filter: blocklists + allowlist + per-device policy"}
FILT -->|"blocked"| NX["NXDOMAIN / 0.0.0.0"]
FILT -->|"allowed"| RES["resolvers (DoH/DoT/plain/FakeIP) + nftset for routing"]
DNS -->|"query events (engine observability)"| AGG["shater stats aggregator"]
AGG --> PANEL["panel: top domains · per-device · allowed/blocked · timeline"]
Because the engine's DNS runs in our process, every query (domain, client,
verdict, latency) is available to the stats aggregator without log-scraping —
this is the payoff of embedding. Blocklist matching uses an efficient compiled
matcher, not dnsmasq megalists (see DECISIONS.md D5). Per-device blocking =
engine route/DNS rule keyed by client, or nftset(device) × nftset(blocked-domain)
→ drop.
5. Config & apply flow
stateDiagram-v2
[*] --> Edit
Edit --> Render: UCI → sing-box config (our generator, engine types)
Render --> Validate: engine config check + nft -c
Validate --> KeepOld: fail
Validate --> Apply: ok (atomic swap: engine reload + nft/route reconcile)
Apply --> ConfirmWindow
ConfirmWindow --> Committed: confirmed
ConfirmWindow --> Rollback: timeout
Rollback --> LastGood
6. Roadmap tiers
See ROADMAP.md for the phased plan and FEATURES.md for the full feature list.