Files
omarandClaude Opus 5 32aac89139 docs: stop the docs promising a safety net that ships disarmed
Every install recipe walked the reader through `shaterd apply` + `shaterd
confirm` as if commit-confirm were armed. It is not: DefaultGlobals() never
seeds ConfirmTimeout, the shipped config carries confirm_timeout '0', and
ArmRollback returns at once on a non-positive timeout. A reader following the
README believed an apply that cut their SSH would undo itself. It would not.
README/README.en/INSTALL now arm it in the recipe and say what 0 means; the
apply-flow diagram gained the edge it always took on a stock box.

The boot armor was documented nowhere at all (`grep -rli armor --include=*.md`
returned zero) while shipping enabled and blocking LAN->WAN on every boot.
INSTALL 4 now says what it is, why SSH/LuCI stay up on purpose, every condition
under which it refuses to arm, and how to switch it off.

Also removed or corrected, each checked against the code, not inherited:

* MASQUE/CONNECT-IP is advertised in both READMEs and absent from parse,
  generate and model -- registry names it among the types deliberately left
  unregistered. Dropped, with the fork-vs-product distinction spelled out.
  The inverse too: Hysteria2/TUIC/XHTTP were tagged [T1] while shipped under
  with_quic/with_xhttp; ShadowTLS is generate+registry only, no parser.
* `direct (flow-offload on)` -- no offload/flowtable/flow_offloading anywhere
  in openwrt/, shater/ or panel/src. The product does not do this.
* shater-core deps were two releases stale in two places, one of which vouched
  for a config.buildinfo check that never covered kmod-tun. Ruling narrowed to
  what was actually checked.
* PORTING's "Full schema" -- the shipped config points at it -- was missing
  l3_tunnel and untunnelable_egress (UCI is their only path; the panel does not
  show them) and the blocklist/allowlist/device/alert sections, while listing a
  `config preset` that ReadUCI has no branch for.
* ARCHITECTURE had no L3 ingress and no kernel egress at all, though both are
  [MVP] and one creates an fw4 zone in the user's firewall config. New 3a.
* nftset-for-routing in the DNS diagram: that is the v0.1 mechanism, gone in v0.2.
* CONTEXT described a pre-Phase-1 repo and a 24.10.3 testbed. The testbed is
  ImmortalWrt 25.12.1 r37978-cd0a06bfd3fd (read off the box), which is not a
  detail: .apk does not install on 24.10 at all.
* The gate existed and no .md mentioned it. README/README.en/CONTEXT now do.
* release.yml's header still described publishing as either/or after the rolling
  pointer became unconditional. Comment only.
* Shipped /etc/config/shater: schema_version '1' against CurrentSchemaVersion=2;
  a pointer to a dns_filter line that was not in the globals block (added, '0');
  and `option sniff '1'` on the inbound -- an option the model deliberately does
  not have, which the first panel save would have silently washed out.
* lx-changelog pointed at a D25 heading that does not exist.
* ROADMAP 2b and 5 were done and unmarked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BHw89tdWddzhjUc4bAH4tS
2026-07-26 23:35:06 +03:00

9.4 KiB
Raw Permalink Blame History

Feature list

The full intended feature set for shater v0.2. Tags: [MVP] target the first usable release, [T1] next, [T2] later. Phases refer to ROADMAP.md.

Proxy engine & protocols (from the sing-box fork)

  • [MVP] VLESS, VMess, Trojan, Shadowsocks, WireGuard, Reality/XTLS.
  • [MVP] AmneziaWG 2.0 (I1–I5 CPS decoy packets) — a driving requirement.
  • [MVP] Hysteria2, TUIC (hysteria2:///hy2:///tuic://, shater/parse), XHTTP transport — all shipped: the router tag set carries with_quic and with_xhttp and shater/registry registers them (scripts/router-tags.sh, buildtags.Features).
  • [T1] ShadowTLS — half-built: shater/generate emits it and shater/registry registers it, but no parser produces one (there is no shadowtls:// share link and no subscription path), so a config cannot reach it today.
  • NOT SHIPPED MASQUE/CONNECT-IP (Cloudflare WARP). masque appears nowhere in shater/parse, shater/generate or shater/model, and shater/registry names it among the upstream types it deliberately does not register (~6 MB of binary and resident RAM). The engine fork can build it; this product does not.
  • [MVP] Transports: TCP/WS/gRPC/HTTPUpgrade/H2/QUIC as upstream provides.

Transparent proxying & routing

  • [MVP] TPROXY transparent proxy for multiple LAN interfaces (TCP + UDP), SNI/ Host/QUIC sniffing.
  • [MVP] L3 ingress for ICMP (globals.l3_tunnel, opt-in, default off): LAN ping travels THROUGH the tunnel instead of being dropped or answered by a forged local reply. The engine opens a dedicated TUN (shater-l3, gVisor stack, auto_route off); nft marks LAN icmp/icmpv6 only and a scoped ip rule routes it in — the TPROXY plane and the main routing table stay untouched (D25). Carried only by L3-capable egresses (WireGuard/AmneziaWG, direct); ICMP routed to vless/vmess/… is honestly dropped, never faked. Ceiling is upstream sing-tun's: ICMP echo only — Windows tracert works, IPv6 traceroute shows just the destination; ESP/AH/GRE/IGMP stay with the untunnelable policy (D17) unless untunnelable_egress carries them (D26).
  • [MVP] Kernel egress for untunnelable protocols (globals.untunnelable_egress, opt-in, default empty): names an existing interface/tunnel egress, and IPsec (ESP/AH), PPTP/GRE, SCTP — everything that is neither TCP nor UDP, plus ICMP when the L3 ingress is off — is routed out that egress's device by the KERNEL with kernel NAT, reusing the egress's own fwmark/table from addEgressRouting; the proxy never sees a byte, which is why every protocol works (D26). What that buys depends on the device: a WireGuard interface really is a tunnel, a second WAN is just another uplink whose real address the destination sees. It does not revive multicast IPTV, and UDP-based VPNs (WireGuard, OpenVPN-UDP, IPsec NAT-T) never needed it — they follow the routing rules as before. The untunnelable policy (D17) keeps only the failure case: a route that did not come up.
  • [MVP] First-match routing rules by source (IP/CIDR/MAC/interface/zone), destination, port, proto → target (outbound/selector/chain/direct/block) + egress. A rule names its destination through a rule-set only — a reusable named list (inline domains/CIDRs, a local or remote file, or a geosite/geoip category) that is compiled once into a .srs and shared by every rule that references it. Domain entries take full: (exact), suffix: / a leading dot (host + subdomains), keyword: (substring) and regexp:; a bare entry means host + subdomains.
  • [MVP] Node groups with balancer/observatory (least-ping/failover/round-robin).
  • [T1] Multi-hop chains (L1→Ln); per-rule egress selection; egress via any interface/tunnel (e.g. an AmneziaWG tunnel).
  • [T2] Per-destination latency-based routing; auto route-optimization.

Subscriptions & nodes

  • [MVP] Subscriptions (VLESS/VMess/Trojan/SS/WG/AmneziaWG), Clash/sing-box/ Xray-JSON formats, per-sub update interval + manual + on-boot; HAPP-style fetch (UA/HWID/headers); stable per-node identity (fingerprint reconcile) across refreshes; quota/expiry from subscription-userinfo.
  • [MVP] Manual nodes: paste share-link(s), file import, or a wg-quick/ AmneziaWG .conf.
  • [T1] Node health test (TCP + real proxy-path HTTP probe, exit-IP), "test all", QR export.

DNS, filtering & blocking (a core value layer)

  • [MVP] :53 hijack, in-process sing-box DNS; per-domain resolver selection; DoH/DoT/plain resolvers; fake-IP as a resolver TYPE (config resolver type=fakeip + pool — there is no global "FakeIP mode"); no DNS leaks. Routing is decided by in-engine rule-sets — the v0.1 dnsmasq→nftset population mechanism does not exist in v0.2 (see generate/dns.go). The hijack covers the queries a client sends to the router itself — the address DHCP hands out — because globals.dns_intercept is ON by default (D24). With it off, those queries go to dnsmasq and out to the ISP in the clear, so the well-behaved client leaks while the one that hard-codes 8.8.8.8 does not. .lan and the private PTR zones are preserved through dnsmasq either way. Two things the promise does NOT cover, both by design: while the engine is DOWN the holding plane hooks forward only, so dnsmasq still answers router-addressed :53 unfiltered (client traffic and DNS to external resolvers stay blocked); and with no config resolver at all there is no DNS plane to filter with — queries fall through to the system resolver and generate says so.
  • [MVP] Client DoT/DoH blocking (stop devices bypassing the filter).
  • [MVP] Blocklists with flexible sources: inline (type your own) / file / url (auto-update) / geosite category (only when geodata present). A url list may be a hosts file, a plain domain list or an AdBlock-style ||domain^ list — the formats StevenBlack/OISD/AdGuard/hagezi actually publish — and is compiled to a local .srs on the router; a URL already serving .srs/ .json is used directly. Response NXDOMAIN or 0.0.0.0; allowlist overrides.
  • [MVP] Efficient matching for large lists: compiled succinct-set matcher (.srs, zlib) with dedup, refreshed on update_interval — not dnsmasq megalists (see DECISIONS.md D5). A compiled list costs ~1% of the source text on disk (StevenBlack ≈ 150k domains → ~80 KiB) and nothing at steady state. Ceiling: 200k domains per url list, set by the RAM the one-off compile needs on the target hardware (~116 MiB peak at 150k, linear; 512 MB total). Larger lists are refused with a message pointing at geosite categories, which are pre-compiled upstream and cost no memory to build. Subdomain-collapse and a bloom prefilter are NOT implemented.
  • [T1] Safe-search enforcement; category-based blocking bundles.

Per-device control & parental

  • [T1] Devices page: auto-discover (dhcp.leases + ip neigh), name devices, live status/traffic.
  • [T1] Per-device toggles: proxy on/off, blocklists on/off, exit country/node.
  • [T1] Per-device domain block/allow (block a site for one device or everyone).
  • [T2] Schedules: time-windowed rules (bedtime, school hours) per device/group.
  • [T2] Per-device data quotas.

Statistics & visibility (a core value layer)

  • [T1] Per-domain stats: top queried/blocked domains, allowed-vs-blocked, per-device breakdown, timelines — fed by the engine's in-process DNS events.
  • [MVP] Per-client / per-node / per-rule traffic (bytes), from nft counters + engine stats.
  • [T1] Live query log (streaming) with one-click block/allow.
  • [T2] Connection inspector; Sankey/leaderboard views; geo-map of exits.

Reliability ("железно")

  • [MVP] Fail-closed kill-switch (dead group → block, never silent direct leak); IPv6 dropped when disabled.
  • [MVP] Atomic apply with engine + nft -c validation. Commit-confirm auto-rollback to last-good is built and works, but it is opt-in and ships OFF: DefaultGlobals() leaves ConfirmTimeout at 0, the shipped /etc/config/shater says confirm_timeout '0', and apply.ArmRollback returns at once on a non-positive timeout. Until an operator sets a window, an apply on a stock box has no net under it — and shaterd apply says so.
  • [MVP] Idempotent reconcile from hotplug/boot under flock; restart engine only on real config change; management-bypass (SSH/LuCI/LAN) always exempt.
  • [MVP] Own nft table inet shater + own marks/tables; never touch fw4.

UI — thin LuCI + full admin panel

  • [MVP] Thin LuCI app: pretty mini-dashboard (status + throughput) + "Open panel" button with short-lived token handoff (see ARCHITECTURE.md §2).
  • [MVP] Admin panel (SPA, own port, embedded in the binary): overview, node/subscription management, routing rules, apply/rollback, DNS/blocklists.
  • [T1] Rich stats dashboards, devices page, live query log, config diff/history.
  • [T2] Named profiles/scenes; WAN-mode profiles (conditional overrides, e.g. SIM uplink → different egress); backup/restore; i18n (EN + RU).

Ops & distribution

  • [MVP] Single signed binary; signed apk feed on Gitea (EC key dist/shater-apk.pem); one-line install; named-package apk upgrade.
  • [T1] Upstream-rebase cadence (track sing-box-lx tags) with a smoke suite.
  • [T2] Multi-router fleet management; REST/gRPC external API; Telegram bot. (apk packaging landed and is now the only lane — D22.)