omarandClaude Opus 5 eab1db2c3f
release / aarch64_cortex-a53 (push) Successful in 3m19s
release / x86_64 (push) Successful in 3m14s
release / apk aarch64_cortex-a53 (push) Failing after 1m4s
release / apk x86_64 (push) Failing after 1m3s
release / release (push) Successful in 8s
release / release apk (push) Successful in 5s
fix(ci/apk): second defconfig pass — deselect the SDK's per-kmod default m
Turning ALL/ALL_KMODS/ALL_NONSHARED off (22d7161c0) provably worked — run 59
logs all three as `is not set` after defconfig — and changed the kmod count by
exactly zero, 1078 both times. The kmods never came from ALL_KMODS.

They come from the SDK itself. target/sdk/Makefile generates the SDK's
Config-build.in by running convert-config.pl over the BUILDBOT's .config, in
which ALL_KMODS=y had already expanded into one `CONFIG_PACKAGE_kmod-*=m` line
per module. convert-config.pl turns every `CONFIG_X=<val>` line into a symbol
with an unconditional `default <val>`; its `next if /^(# )?CONFIG_PACKAGE/`
filter sits in the `else` branch, which a line containing `=` never reaches.
The SDK therefore ships ~1078 verbatim blocks of `config PACKAGE_kmod-x /
tristate / default m`, none of which consult ALL_KMODS.

Fix: a second pass. The names only exist after kconfig has expanded the tree,
so after the first defconfig rewrite every selected kmod to `is not set` and
re-run defconfig. Two documented kconfig rules make this exact:
  - an explicit value in .config beats a `default` (same rule that kept our
    `# CONFIG_ALL* is not set` lines alive in run 59) -> the ~1078 stay off;
  - `select` is OR-ed in after the user value, so shater-core's
    `DEPENDS:=+kmod-nft-tproxy +kmod-nft-socket` brings those (and their
    transitive kmods) back on their own.

Also correct the tripwire message, which still blamed CONFIG_ALL_KMODS: it now
prints the ALL* state AND the first few surviving kmods, so the two failure
modes are distinguishable at a glance.

Verified: bash -n on the file and on the extracted INNER heredoc body; the
rewrite simulated against a run-59-shaped .config (1078 -> 0 selected, our 4
packages, LOCALMIRROR and the ALL* lines untouched).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 01:16:05 +03:00
2026-06-25 16:36:07 +08:00
2026-06-25 17:38:53 +08:00
2026-06-25 17:39:02 +08:00
2026-02-27 14:58:06 +08:00
2026-06-25 17:38:01 +08:00
2025-04-29 20:45:19 +08:00
2023-12-29 18:00:40 +08:00
2023-12-29 18:00:40 +08:00
2026-02-26 14:13:32 +08:00
2026-06-25 19:47:32 +08:00
2026-07-08 00:34:26 +08:00

shater

A self-hosted internet-control appliance for OpenWrt routers. One box turns a home or office network into a transparent VPN gateway, a network-wide ad/tracker/malware blocker, per-device parental control, and a live traffic dashboard — all local, all configured from a rich built-in web panel.

The primary README is Russian — README.md. This is a condensed English mirror.

License: GPL-3.0 targets: x86_64 · aarch64_cortex-a53

What it is

shater is a network proxy stack for OpenWrt / ImmortalWrt / BananaWRT routers (Banana Pi BPI-R3, BPI-R4 and compatible). It transparently routes all LAN traffic through a proxy (split by domain/geo/client), filters DNS, gathers statistics, and is managed from a built-in web panel.

The engine is a fork of sing-box via sing-box-lx, compiled into a single Go binary shaterd together with the control plane, DNS filter, stats aggregator and the web panel itself. Broad protocol set: VLESS/VMess/Trojan/Shadowsocks, Reality/XTLS, WireGuard, AmneziaWG 2.0, Hysteria2, TUIC, XHTTP, MASQUE/CONNECT-IP.

A thin LuCI launcher (mini-dashboard + "Open panel" button) hands the browser a single-use token into the standalone SPA the daemon serves on its own port (default :8088).

Highlights

  • Transparent TPROXY data plane (TCP + UDP), SNI/Host/QUIC sniffing, no DNS leaks.
  • First-match routing by source / destination / list / geo / client → outbound / selector / chain / direct / block; node groups with balancer/observatory; multi-hop chains; per-rule egress.
  • Fail-closed kill-switch (dead group → block, never a silent direct leak); own inet shater nft table; atomic apply with nft -c validation and commit-confirm auto-rollback.
  • DNS filtering & blocklists with flexible sources (inline / file / url / geosite), compiled .srs matcher; Block-DoH/DoT to stop filter bypass.
  • Subscriptions (Clash / sing-box / Xray-JSON) and manual nodes; node health board.
  • Per-device control (proxy/blocklist toggles, exit country, per-device block/allow, schedules) and per-domain/client/device statistics from in-process DNS events.

Full list with MVP/T1/T2 tags — docs-shater/FEATURES.md.

Install

Two signed feeds. Pick by the router's OpenWrt version. Verbatim commands and the manual .ipk/.apk install are in docs-shater/INSTALL.md.

opkg (OpenWrt 24.10):

wget -O /etc/opkg/keys/5ac4b177689cb8e0 \
  https://git.qomar.pw/omar/shater/releases/download/latest/shater-feed.pub
echo "src/gz shater https://git.qomar.pw/omar/shater/releases/download/latest" \
  >> /etc/opkg/customfeeds.conf
opkg update && opkg install luci-app-shater   # -> shater-core -> shaterd

apk (OpenWrt / ImmortalWrt / BananaWRT 25.12+):

wget -O /etc/apk/keys/shater-apk.pem \
  "https://git.qomar.pw/omar/shater/releases/download/apk-latest-$(cat /etc/apk/arch)/shater-apk.pem"
echo "https://git.qomar.pw/omar/shater/releases/download/apk-latest-$(cat /etc/apk/arch)/packages.adb" \
  > /etc/apk/repositories.d/shater.list
apk update && apk add luci-app-shater         # -> shater-core -> shaterd

shater ships inert (globals off) so install never breaks connectivity. After configuring nodes/rules: uci set shater.globals.enabled=1 && uci commit shater, then shaterd apply and shaterd confirm.

Build from source

scripts/build-shaterd.sh [VERSION] [--fast] builds the SPA (Vite), embeds it via //go:embed, cross-builds musl-static {amd64, arm64} and UPX-packs the artifact into openwrt/shaterd/files/. Details in docs-shater/INSTALL.md.

Repository layout

Path What
shater/ Go control plane, DNS filter, stats aggregator, engine host
panel/ Admin SPA (Vite + React + TS) and its Go server
openwrt/ Packages: shaterd, shater-core, luci-app-shater, byedpi
docs-shater/ Product documentation
scripts/, ci/, .gitea/workflows/ Build script, feed/release scripts, CI
SPECS/, docs-lx/ Engine-fork constitution/specs and feature-config reference
docs/, mkdocs.yml Upstream sing-box docs (mkdocs) — kept as-is
adapter/ cmd/ dns/ route/ option/ protocol/ transport/ … sing-box-lx engine tree

CI, upstream & license

CI (.gitea/workflows/release.yml) builds all 4 packages and publishes signed feeds: opkg (usign, key 5ac4b177689cb8e0) and apk (EC key shater-apk.pem). A vX.Y.Z tag → versioned release; workflow_dispatch → rolling latest.

The engine is the sing-box-lx fork — a thin downstream of upstream sing-box that lives by rebase, never merge; its constitution is SPECS/CONSTITUTION.md. Licensed under GPL-3.0, like upstream sing-box. Unofficial fork, not affiliated with SagerNet.

S
Description
OpenWrt XRAY management plugin � passwall-class, but cleaner. Design + code.
Readme
56 MiB
2026-07-28 07:50:40 -04:00
Languages
Go 77.7%
TypeScript 12.4%
PureBasic 4.2%
Shell 2.5%
CSS 2.1%
Other 1%