Skip to content

v0.8.21 — accounting, revocation and core-crash fixes, upstream node v0.5.7, mtg v2.3.0

Choose a tag to compare

@Free-Guy-IR Free-Guy-IR released this 03 Nov 19:17

Release commit 347da49466514ccc2ef0a2384a46d8111c45fed3 on main. Previous release: v0.8.20-degraded-start
(2d8e11f3). This release carries the 545 commits in v0.8.20-degraded-start..v0.8.21; every one is listed by
git log v0.8.20-degraded-start..v0.8.21. NodeVersion 0.6.21. One patch step after v0.8.20.

Before the fleet rollout: dd-mode MTProto media check (DEPLOY)

The mtg pin now carries upstream 63049fa39c43 "preserve the sign of Telegram DC ids". A dd (plain) MTProto client that
asks for media DC -N now reaches Telegram as -N instead of N. This changes what every dd stream sends. Before the
image goes to the whole fleet, one node must pass a real-traffic check through a dd link: open a chat with photos,
videos and files that are not cached, and confirm they load. Only then roll out to the rest.

Pins

  • mtg: github.com/9seconds/mtg/v2 v2.3.0, replaced by Free-Guy-IR/mtg main 1563871b36dd518970490c8d018bdd2325d75e31
    (7fa5c6c3). That is upstream release v2.3.0 merged with the fork's fixes (950d39a9, pin 7f8c04762e3b) plus one
    fork commit that rejects a connection whose remote address has no TCP IP instead of panicking. The upstream v2.3.0
    commits it carries (transient accept errors, Linux accept(2) retry, socket-option drop logging, ordinary stop, v2
    network constructor, signed DC ids) are listed in docs/upstream-parity.md, "mtg v2.3.0 commits in the pin".
  • sing-box: SINGBOX_COMMIT 5a7c1f1a31cd11998ad249f00216f3a7add47d2b, Free-Guy-IR/sing-box main, still
    v1.13.21 (347da494, after 899005e1b8bf in 007bae8b and v1.13.21 in d189e942). It brings the vision close
    fix and three verbatim sing-vmess ports: the vision reshape split under the 8171-byte limit (upstream 40a1d62fd3a9),
    no zero-length end-of-stream chunk on an empty write (upstream 2a5002728353) and the reader port (upstream
    31ec11e8790c). sing-quic stays v0.6.5.
  • xray: XRAY_COMMIT d2758a023cd7, built against golang.org/x/net 0.60.0; Dockerfile.xray, which shipped an
    unpatched core, is removed (60ecdcac).
  • Go toolchain 1.26.10 in go.mod, CI and the image builders (410815f6).

Upstream PasarGuard node parity

  • v0.5.7: grpc 1.84.0 -> 1.85.0 (PasarGuard#122, bdd91efe, with the RED for Stop hanging behind a GracefulStop that waits on an
    orphaned handler, b45a71b5) and gopsutil 4.26.9 -> 4.26.10 (PasarGuard#121, 62059d0a). Waivers settled in b08ecee0; the
    indirect-module refresh 81af68e and the version bump 739eab9 stay recorded as pending.
  • PasarGuard#112: WireGuard canonical public keys and IPv6 NODE_HOST (74e9aaa4), and the counter-dip rule for the WireGuard
    tracker only (ee73b4f7).
  • PasarGuard#114: Shadowsocks 2022 inbounds stay multi-user when they start empty (3d18e70f).
  • PasarGuard#115: keep-alive refreshes on every call from the owning panel (c2e15f29).
  • PasarGuard#116: a core start can outlive the Start request (58a47bd8).
  • PasarGuard#90: configurable WireGuard server interface MTU (f9c4f05b).
  • The node v0.5.5 items, including the upstream grpc, gopsutil, x/sys, x/net and x/crypto bumps, recorded in
    docs/upstream-parity.md. go-chi moves to 5.5.0.
  • Not ported: node v0.5.6 MASQUE (PasarGuard#96, 88d5e75) and its version bump 675bdaa stay pending in
    .github/upstream-waivers.txt under NODE-SYNC-055, until 2026-11-20.

MTProto

  • Each instance's serve loop is supervised: an accept error cannot silence it, a panicking loop marks only its instance
    dead, one dead instance no longer stops the node, and state is reported per instance (a8f6b6a2, 09d06836,
    5a50d944).
  • A panic in mtg or in a node callback no longer takes the node down (15c04808).
  • A revoked user's open sessions are closed, including a stream begun before the revoke (dde62226, 90fd4897); a
    removal without a usable secret revokes by identity (63e33176); a stream context with no Close raises one alarm per
    instance (bf7eb766, F-V7-S7).
  • Accounting is handed to the next backend on every Start, force-closed middle-proxy relays bill what they write after
    Shutdown, concurrent Shutdowns hand over once, and Restart is refused after shutdown (472d2d7d, 217ea7c5,
    f7e3c7d5, 3a3157b6). Goroutine leaks on Start and the Restart listener swap are fixed (a6a82378, 0e84d610,
    4e434845).

Xray

  • A revoked or removed user's live connections and UDP flows are cut and new ones refused; a replaced account is revoked
    and only inbounds that held the user are touched (fdde3199, 6d56a6d4, 529d4067, f115e999, 7e97beea).
  • Health restarts wait for user syncs, never outlive shutdown, probe the core a sync installed and keep what a cancelled
    sync staged (82733dfc, a7c46ccf, 982bc47c, c2ed9854, 26bba5a8).
  • The config is serialised from a snapshot (797adcf0); per-user stats registration is atomic (df13041b);
    unchanged users are left alone during sync and the last entry for a user wins within a batch (40006fe1, 5a3c2ba0).
  • X-Forwarded-For is honoured only behind sockopt.trustedXForwardedFor and only from XRAY_TRUSTED_FORWARDER_CIDRS,
    which refuses IPv4-mapped entries (a170e667, c1e32b6c, a104cfb5); a pinned CA needs a server name (e1b77af8).
  • Core crash and race fixes carried at the pin: QUIC sniffer, WebSocket early data, SS2022 invalid destination, DNS
    names over 255 bytes, HTTP 1xx, tunnel inbound on a unix socket, WireGuard gVisor tun and outbound Close race, routing
    API race, XHTTP client races, singbridge datagram release (099f105f, d0b86f11, e9a433d0, 78ea868e, 448b373e,
    2d0272ec, 89e6a8e0, b7498bbc, a60ba6f2, 4c7f0a6d, 0abd7251); route picks no longer wait on rule updates
    (14cf5056); an empty hysteria auth is never installed (8882fc25).

L2TP accounting

  • Every session's bytes are billed once across restarts, renegotiations, reused pids, late ip-down and reboots: the
    session identity and final record are written atomically, watermarks survive a grace period and unreadable state, the
    fallback window is decided on boot time, and a missing run directory is an incomplete listing (b193386f,
    cf7f5008, ae0bc187, 5cd061b5, 4d3ff097, 28600993, 387d80cf, 7a39c000, 4f6bb0e9 and the rest of the
    fix(l2tp) series). ip-up/ip-down are replaced atomically and keep every character of a record value (6ae0fb84,
    9166cb5a). User syncs are refused after shutdown (db096a71).

Stats, WireGuard, OpenVPN, sing-box

  • Uplink is bytes received from the client on every protocol; node-level and per-inbound traffic are kept apart; a
    dipped counter rebases only its direction, and a restarted counter counts from zero with unread bytes carried
    (68d40f03, 61979286, 17dfdf50, e55fd11e, 83932cb0).
  • WireGuard accounts every peer byte through removals, replacements, Start and interface hand-over, and removes the peer
    when a user loses access (774fa21a, 054d4aca, a2c63c2d, cbb63a06).
  • OpenVPN drains final counters, settles sessions after the management loop exits, revokes a user without an OpenVPN
    block, and indexes users by email so bulk updates stay linear (143c2532, 8ab5dc8f, 514460a4, c3ff1c3b).
  • sing-box: health restarts wait for user syncs, a closed stats client returns an error instead of crashing, and an empty
    hysteria2 password is never installed (aa2131db, 7067a349, 8db51e50).

Controller, RPC and REST

  • The API key is checked before grpc-go reads the request, and an invalid or nil API_KEY fails fast (d489663a,
    88162e25).
  • User syncs are serialised with every core lifecycle change; a queued SyncUser fans out to every backend; a down primary
    is isolated from the extra backends; backend management requires the current client; the keep-alive watchdog is
    serialised with Start, and panel keepalive pings are accepted (af180e20, ee207282, 673524b5, de3493fb,
    40248f2c, 7192af88).

Build, CI and supply chain

  • install_core.sh and base images pinned and shipped geo data verified (b30c3e46); every patched xray file guarded
    in the image build (11d549d0, 8fbae98f); govulncheck refuses unproven patch application (1df3a918, 703eeaf2);
    tracked executables and files over 5 MB are refused (8c24aa4b and follow-ups).
  • Upstream Drift CI fails on unported upstream commits and releases; every unported upstream commit carries a reasoned
    waiver in .github/upstream-waivers.txt (the drift series).

Known, tracked

No production defect was found in v0.8.20-degraded-start..v0.8.21. These items are tracked, with an owner and a date:

  • D-a1: backend/singbox/inbound_ledger_lock_test.go calls t.Fatalf from a spawned goroutine (test-only). Due 2026-11-05.
  • OBS-a5: L2TP double bill at the 0.6.20 -> 0.6.21 upgrade when /run/pg-l2tp or the PID namespace outlives the
    container (bare metal, systemd, pid: host, bind-mounted /run/pg-l2tp). Not reachable in the stock image. The fix,
    a persistent upgrade marker under /var/lib/pg-node, goes into v0.8.22; deploy gate G3c, before node 70 is upgraded.
  • N4-E2: the 4f0bbc51 WireGuard test checks only aggregate bytes, so a per-user misattribution would pass
    (billing-relevant). Due 2026-11-10.
  • S3-W1..W6: weak tests in a5757d79, 6519b862, 84feaa37, ca520191, 09049248, cb1f730b. Due 2026-11-10.
  • N4-E1, N4-E3..E7: L2TP lock tests without useHostSeam (45f5b25e, 5e86ff90); 10c22bd4 does not prove Read is
    parked; ac063346/4f3a2302 rely on a 300 ms sleep; 5d015b5e/619015fd bounded under-bill awaits an owner decision;
    7044833b window-close and finals-without-identity assertions; ac29f67d pending-* cases and 9e9bd59c docs. Due 2026-11-10.
  • N5-E1..E5: 7b4e67fd, 0a3c68fa, 3a844f88, f1958fe6, 9fc13a1e not RED at their own commit; drift rule cases
    masked by rules 508/537; shadowsocks2022_test.go skips without an xray binary; 797adcf0 equivalence pin; parity doc
    count in f2e6adb0. Due 2026-11-10.
  • S2-N1..N8: Makefile install_xray curl pipe without pipefail (not in the image); 5cd6bc79 message; drift script
    paging and advisory rules; f7e3c7d5 log-line assertion; d66e5cf0/127455c7 timing windows; e9a433d0 message;
    a60ba6f2 PickRoute latency behind rule reloads; 5b8ac197 dot-name leftover on a failed link back. Due 2026-11-10.
  • S3-A1..A3: action tag pins, workflowgate @ref normalisation, no refusal of pull_request_target/workflow_run
    (hardening). Due 2026-11-10.
  • XRAY-TAGSCACHE: upstream xray-core TestTagsCache data race (Manager.AddHandler vs Manager.Select), reproduced on
    unpatched d2758a02; upstream report candidate. Due 2026-11-10.
  • GO-2026-6651: the govulncheck waiver expires 2026-11-30.
  • Upstream waivers: 24e2b122 (node v0.5.5) expires 2026-11-08, a3d2d2fe and 8d0a7cf8 expire 2026-11-10; the Upstream
    Drift gate goes red after the first expiry unless each is ported or renewed.
  • F-VREM-2, F-V9-G2, F-VSB-1 (LOW, due 2026-11-20), and the dd-mode media check on one node before the fleet rollout.

Not in this release (next patch)

  • mtg 1ca247b and sing-box dbd00be87 are not in v0.8.21; they go into the next patch after their own test run.