Files
shater/docs-shater/FEATURES.md
T
omarandClaude Opus 5 a0de597d69
test / go + panel tests (push) Successful in 4m56s
feat(dns): intercept by default, and bootstrap node addresses off the tunnel
The posture was inverted. A client using the DHCP-supplied resolver — the router
itself — was NOT intercepted: dnsmasq answered and forwarded to the ISP in the
clear, so the filter, the blocklists, the per-device rules and BlockDoH were all
inert for exactly the clients that did nothing wrong. A client that hardcoded
8.8.8.8 to route around us WAS intercepted, by the catch-all. Meanwhile the
docs promised no DNS leaks. The default now matches the promise.

Turning it on crosses a threshold that was already dangerous for anyone with two
resolvers. Above one transport, a node's domain server address stops being
resolved by the transport directly and goes through the client DNS plane
instead — so a blocklist entry, a block_doh NXDOMAIN or any dns_rule can answer
your own node's hostname, and one sloppy line in an ad list stops being an ad
that got through and becomes a tunnel that never comes up.

So the fix is gated on having two or more transports, not on the intercept
toggle: resolver_default plus resolver_fallback always reached that threshold,
long before this change. When no endpoint_resolver is configured the plane now
carries a bootstrap server — the default resolver cloned with its detour
dropped, keeping its type, so a DoH default stays DoH and only the tunnel hop
goes. An explicit endpoint_resolver still wins.

This is not a restore of the previous behaviour and the comment says so: at one
transport the dialer used the default resolver WITH its detour, so a lone
DoH-through-the-tunnel resolver was already a bootstrap loop. It is strictly
better than what came before.

Existing installs keep whatever they set — the config file is a conffile and is
never replaced — and an explicit dns_intercept '0' survives the render-parse
round trip, which a default-true bool otherwise makes easy to lose.

The no-resolver warning stays, and no default resolver is shipped to silence it:
a placeholder would remove the sentence without moving a single query, and the
panel would then say a resolver was configured while nothing was filtered. Its
wording is corrected instead — .lan keeps working through the built-in local
transport, which the old text denied.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 04:54:15 +03:00

6.8 KiB
Raw 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.
  • [T1] Hysteria2, TUIC, ShadowTLS, XHTTP, MASQUE/CONNECT-IP (Cloudflare WARP).
  • [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] 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.
  • [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.)