Skip to content

Commit 52d3bc5

Browse files
committed
release: v1.5.0
Promotes v1.5.0-beta.1 to stable. Ships the beta's backend features — quality-aware NodeCircle rotation (best mode + max_latency/min_speed filters + smart-skip), background auto speed-checks, the unified reachability-gated speed test (avg after warm-up + peak), login lockout and opt-in GeoIP flags (DB migrations 019-022) — alongside a UI-framework refresh and network hardening. UI framework: Tailwind v3 -> v4 (CSS-first @theme) on the TailAdmin palette while keeping PiTun's variable structure; light-theme contrast fixed page by page. tailwind.config.ts is gone (config is now CSS). Localisation: a Russian sweep across pages that lacked useT (GeoData, Balancers, Diagnostics, Logs, Login, routing/rule editors, ...), keeping technical terms in English. Routing self-loop protection: state read, apply and the gateway probe refuse a default route that points at the box's own IP; the Network page flags it in red. Install/deploy scripts add an IP==GATEWAY guard, check ports 53/5353, remove the native systemd-resolved and make resolv.conf a static PiTun-owned file so hostname resolution stays reliable; 03-deploy.sh self-heals already-installed boxes. UX: sidebar reordered with thin separators, a scrollable nav that never exceeds the viewport, and distinct icons (Balancers off the Nodes glyph). "Speed All" reuses the background sweep so a large node set can't 504. Docs: README (EN+RU) feature list refreshed; Knowledge Base gains Speed Tests & Node Health, Host Network, Direct Connection, Updates and TLS Fragment sections and updated Node Circles / Subscriptions / Security, all bilingual. No new migrations beyond the beta's 019-022; schema unchanged since v1.5.0-beta.1. Relevant backend suites (network, autocheck, speedtest, nodecircle, auth, dns, system) pass; frontend build + 82 tests green.
1 parent 532417f commit 52d3bc5

70 files changed

Lines changed: 2235 additions & 1868 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,52 @@ All notable user-facing changes to PiTun. Full per-release detail lives in the
44
[GitHub Releases](https://github.com/DaveBugg/PiTun/releases); this file is the
55
committed summary.
66

7+
## v1.5.0 — 2026-08-05
8+
9+
Promotes v1.5.0-beta.1 to stable and lands a UI-framework refresh, a full
10+
Russian translation sweep, and hardening against the "gateway points at itself"
11+
install footgun. Everything from the beta — quality-aware NodeCircle rotation,
12+
background auto speed-checks, the unified reachability-gated speed test, login
13+
lockout and opt-in GeoIP flags (DB migrations 019–022) — ships here.
14+
15+
### Added
16+
17+
- **Routing self-loop protection (Settings → Network).** State read, apply and
18+
the gateway probe now detect and refuse a default route that points at the
19+
box's own IP — the "a new device set its PiTun gateway to itself" footgun.
20+
The Network page flags it in red and blocks re-applying a self-referential
21+
gateway; the install/deploy scripts add an `IP == GATEWAY` guard so the loop
22+
can't be baked in at first boot.
23+
- **Knowledge Base + README refresh.** New KB sections (Speed Tests & Node
24+
Health, Host Network, Direct Connection, Updates, TLS Fragment) plus updated
25+
Node Circles / Subscriptions / Security sections, all bilingual EN/RU; the
26+
README feature list and version pins were brought up to date.
27+
28+
### Changed
29+
30+
- **UI framework: Tailwind v3 → v4** (CSS-first `@theme`) with the TailAdmin
31+
palette as the base, keeping PiTun's variable structure. Light-theme contrast
32+
fixed page by page.
33+
- **Russian localisation sweep.** Pages that lacked `useT` (GeoData, Balancers,
34+
Diagnostics, Logs, Login, routing / rule editors, …) are now translated, with
35+
technical terms kept in English.
36+
- **Sidebar** reordered into logical groups with thin separators, a scrollable
37+
nav that never exceeds the viewport, and distinct icons (Balancers no longer
38+
shares the Nodes glyph).
39+
- **Install / deploy DNS hardening.** `02-install-stack.sh`, `03-deploy.sh` and
40+
`setup-vm.sh` now check ports 53 / 5353, remove the native `systemd-resolved`,
41+
and make `/etc/resolv.conf` a static PiTun-owned file so the box's own name
42+
resolution (hostname) stays reliable; `03-deploy.sh` self-heals already-
43+
installed boxes on the next deploy.
44+
45+
### Fixed
46+
47+
- **"Speed All" no longer 504s** — it reuses the background auto-check sweep
48+
(one-off, forced scope "all"), so a large node set can't time out at the
49+
reverse proxy; the sweep order now checks the newest nodes first.
50+
- A latent `warn: command not found` (`set -e` crash path) in
51+
`02-install-stack.sh`.
52+
753
## v1.5.0-beta.1 — 2026-08-04
854

955
**Beta.** Smarter node-circle rotation driven by real speed data, an automatic

README.md

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,16 @@ Frontend is a single-page React app served by nginx.
278278
- QUIC (UDP/443) blocking — forces TCP fallback for protocols TPROXY
279279
can intercept
280280
- Tunnel chaining — VLESS-inside-WireGuard, etc.
281+
- **Recursive multi-hop chains**`config_gen` follows `chain_node_id`
282+
transitively, wiring every hop (exit → mid → entry) with cycle
283+
detection and a depth cap (WireGuard is exit-hop only)
281284
- **Proxy Chains** (multi-panel, two-hop VLESS+Reality across two
282285
x-ui panels with independent channels per chain; managed clients
283286
+ per-channel delete + live healthcheck)
287+
- **TLS ClientHello fragmentation (anti-DPI)** — a Settings toggle
288+
splits the outgoing ClientHello across several packets so a DPI box
289+
can't match the SNI in a single read; entirely client-side, tunable
290+
packet mode / length / interval, off by default (needs bundled xray 26.x)
284291
- Kill switch — drop all forwarded traffic if xray crashes
285292

286293
**Routing**
@@ -295,38 +302,64 @@ Frontend is a single-page React app served by nginx.
295302
gambling, "Work" set routes corp domains direct). Assign devices
296303
individually or in bulk; per-set rules apply first, then fall through
297304
to global rules. DHCP-resistant (MAC-based via dedicated per-set
298-
loopback TPROXY ports + xray `inboundTag` matching)
305+
loopback TPROXY ports + xray `inboundTag` matching). Set-aware
306+
**export/import** — pick scopes, resolve conflicts, import into
307+
Global / an existing / a new set
308+
- **Route Explainer** — paste a domain, URL or IP and see which rule
309+
wins and whether it exits proxied, direct or blocked
299310

300311
**Health & resilience**
301312
- Background liveness probe with two-tier auto-failover: if the failed
302313
node belongs to an enabled NodeCircle, the failover handler delegates
303314
recovery to the circle (which skips dead siblings via pre-ping +
304315
retry); otherwise it walks a configurable fallback list
305-
- Speed test per node via short-lived isolated xray instance
316+
- **Unified speed test** — gates on reachability first (Google /
317+
Cloudflare 204 with a retry, so a dead node fails in ~1s instead of
318+
grinding every fallback), then measures the **average after warm-up
319+
plus the peak**; streams live, persists both numbers, and flags a
320+
reading older than 6h as stale
321+
- **Automatic background speed checks** — sweep a chosen scope (all /
322+
a subscription / a group / specific nodes) on an interval so `best` /
323+
`min_speed` and the UI stay fresh without manual testing; sequential,
324+
staleness-guarded, with per-node error isolation
325+
- One-tap **reachability check** — confirms a node actually carries
326+
traffic to the internet (204 through the live tunnel), separate from
327+
raw link speed
306328
- Naive sidecar supervisor — auto-restarts crashed Naive containers
307329
with a sliding-window rate limiter
308330
- Recent Events feed on Dashboard surfaces failovers, sidecar
309331
restarts, geo updates, circle rotations
310332

311333
**Balancing & rotation**
312334
- Balancer groups (xray's `leastPing` or `random` strategies)
313-
- Node Circles — automatically rotate the active node on a schedule,
314-
seamlessly via xray's gRPC API (no dropped connections); each
315-
candidate is TCP-pinged with a single retry before switching, so
316-
dead siblings are skipped without a connection blip
335+
- Node Circles — schedule seamless active-node rotation via xray's gRPC
336+
API (no dropped connections). A **`best`** mode plus **`max_latency_ms`**
337+
and **`min_speed_mbps`** candidate filters pick from real speed data
338+
(never-tested nodes get the benefit of the doubt), and a **smart-skip**
339+
keeps a scheduled rotation from moving off a healthy, low-latency node
340+
— manual "rotate now" always rotates
317341

318342
**Subscriptions**
319343
- Periodic refresh from VLESS / VMess / Trojan / SS / Hysteria2 /
320344
Clash YAML / xray JSON subscription URLs
321-
- Per-subscription User-Agent (v2ray, clash, sing-box, happ, …),
322-
optional regex filter, configurable interval
345+
- **User-Agent templates** — an editable table (add / edit / delete)
346+
replacing the old hardcoded presets; each row carries a UA string and
347+
optional custom request headers, with catalogue export / import
348+
- Optional **GeoIP country flags** on imported node names (`🇳🇱 vless-nl`)
349+
— opt-in and licence-clean (drop a MaxMind `GeoLite2-Country.mmdb`
350+
next to the geo data; absent it's a silent no-op)
351+
- Optional regex filter, configurable interval
323352

324353
**Devices & DNS**
325354
- LAN discovery via `arp-scan`, OUI vendor lookup
326355
- Per-device routing policy (default / always-include / always-bypass)
327356
- Per-domain DNS rules (plain, DoH, DoT)
328357
- FakeDNS pool for sniffing-friendly geoip resolution
329358
- DNS query log with stats
359+
- **Host network controls** — change the box's own gateway / DNS from
360+
Settings → Network with an auto-backup + one-click rollback; warns on
361+
a routing self-loop (gateway pointing at the box itself) or a
362+
double-hop through another PiTun
330363

331364
**Servers & deployments**
332365
- Inventory of remote VPS hosts (host, SSH credentials, tags) separate
@@ -336,22 +369,35 @@ Frontend is a single-page React app served by nginx.
336369
- One-click auto-deploy over SSH for **NaiveProxy**, **WireGuard**,
337370
**x-ui** (3x-ui / x-ui-pro) — live log streaming, status badges,
338371
cascade-clean on uninstall
372+
- **Per-page Direct switch** — every server / panel / chain SSH
373+
operation runs *through the active node* by default (the same tunnel
374+
the LAN uses); a Direct toggle flips one operation back to a straight
375+
dial for reaching a box while the active node is down
339376
- Dedicated **X-ui Panels** page — full inbound + client management
340377
(6 wired presets covering Reality / TLS / domain modes), live
341378
healthcheck (panel API, xray, nginx, UFW, TLS cert, disk, mem),
342379
cache↔panel sync for hand-added clients, random / custom
343380
fakesite rotation
381+
- **SNI / REALITY-dest scanner** in the node form — probe a candidate
382+
host for TLS 1.3 + HTTP/2 before saving it as the masquerade target
344383

345384
**Operations**
346385
- One-click GeoIP / GeoSite refresh — three switchable upstream
347386
profiles: Loyalsoldier (CN-focused community list), runetfreedom
348387
(Russian-internet curated list), v2fly (vanilla baseline)
388+
- **In-UI self-update** — Settings → Updates checks GitHub (through the
389+
active node, so a throttled direct route isn't a blocker), shows
390+
what's new and applies it with live progress via a host-side agent
349391
- Full-fidelity JSON Export/Import for Nodes and Servers — versioned
350392
bundle envelope, append/replace modes, optional secret redaction
351393
(separate from URI/subscription import which is single-node only)
352394
- Plain-text URI export (`.txt`, one `vless://…` per line) — share
353395
your node list with any v2rayN-compatible client; symmetric
354-
`Import` button auto-detects URI list vs JSON bundle
396+
`Import` button auto-detects URI list vs JSON bundle. Single-node URI
397+
export straight from a node card too
398+
- **Login lockout** — five consecutive failed logins lock an account
399+
for 15 minutes (HTTP 429 + `Retry-After`); the primary LAN-only
400+
brute-force guard
355401
- Built-in diagnostics page (DNS reachability, gateway, xray status,
356402
resource usage)
357403
- Streaming xray log viewer
@@ -411,30 +457,30 @@ curl -fsSL https://raw.githubusercontent.com/DaveBugg/PiTun/master/install.sh |
411457
> ```bash
412458
> curl -fsSL https://raw.githubusercontent.com/DaveBugg/PiTun/master/install.sh \
413459
> -o /tmp/pitun-install.sh
414-
> sudo bash /tmp/pitun-install.sh --version v1.3.0-beta.8
460+
> sudo bash /tmp/pitun-install.sh --version v1.4.12
415461
> ```
416462
>
417463
> **(B) Pipe with `bash -s --` separator** (the `-s --` is **required**):
418464
> ```bash
419465
> curl -fsSL https://raw.githubusercontent.com/DaveBugg/PiTun/master/install.sh \
420-
> | sudo bash -s -- --version v1.3.0-beta.8
466+
> | sudo bash -s -- --version v1.4.12
421467
> ```
422468
>
423469
> **(C) Environment variable** (no `-s --` voodoo needed):
424470
> ```bash
425471
> curl -fsSL https://raw.githubusercontent.com/DaveBugg/PiTun/master/install.sh \
426-
> | sudo PITUN_VERSION=v1.3.0-beta.8 bash
472+
> | sudo PITUN_VERSION=v1.4.12 bash
427473
> ```
428474
>
429-
>**Do NOT do this:** `curl ... | sudo bash --version v1.3.0-beta.8` — bash
475+
>**Do NOT do this:** `curl ... | sudo bash --version v1.4.12` — bash
430476
> swallows `--version` as its own flag (prints bash's version + exits)
431477
> before our installer ever runs. Common copy-paste trap.
432478
433479
Useful flags (work via any of the three forms above; examples use form B):
434480
435481
```bash
436-
# Pin a specific version (current: v1.3.0-beta.8)
437-
... | sudo bash -s -- --version v1.3.0-beta.8
482+
# Pin a specific version (example tag — see GitHub Releases for the latest)
483+
... | sudo bash -s -- --version v1.4.12
438484
439485
# Force rebuilding from source (no published release available, or
440486
# you're testing local changes). Slower, needs reliable internet

0 commit comments

Comments
 (0)