From cee120cb232cb2d0d983a1bf652bbd73cf3e4d81 Mon Sep 17 00:00:00 2001 From: Local Dev Date: Wed, 23 Sep 2026 23:21:51 +0200 Subject: [PATCH] =?UTF-8?q?vpn=200.1.3=20=E2=86=92=200.1.4:=20an=20https:/?= =?UTF-8?q?/=20paste=20imports=20as=20a=20subscription?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Custom box validated for a vless:// prefix and rejected anything else, so a provider's subscription URL — the thing most people are handed — got "paste a vless:// URL first" with no hint that the Subscription card two sections down was what it wanted. Now an http(s):// paste in that box is detected and routed to the subscription importer, the placeholder says both are accepted, and the dropdown option reads "Custom — vless:// or subscription URL". Also renames the three bundled entries' status from "coming-soon" to "awaiting-key-issuer". The exits exist and are running xray; what is missing is a way to hand a client credentials without shipping a shared secret. DESIGN.md now records why that list stays empty, since this is the second time the shortcut looked attractive: a vless:// URL is the credential, so writing one into the tarball (immutable, mirrored) or onto a public Sia object (mutable but world-readable) are the same category of mistake. Per-session minting is the fix, because then no shared credential exists to leak. Parser verified against plain-text, standard-base64 and url-safe unpadded-base64 subscription bodies; an HTML error page correctly yields zero entries instead of a JSON parse crash. --- bundled-addons/vpn/DESIGN.md | 33 +++++++++++++++++++++++++++++ bundled-addons/vpn/addon.json | 2 +- bundled-addons/vpn/panel.html | 27 ++++++++++++++++++++--- bundled-addons/vpn/server-list.json | 8 +++---- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/bundled-addons/vpn/DESIGN.md b/bundled-addons/vpn/DESIGN.md index 3620490..8766e49 100644 --- a/bundled-addons/vpn/DESIGN.md +++ b/bundled-addons/vpn/DESIGN.md @@ -35,6 +35,39 @@ Anchors: - Exposes one POST endpoint the extension calls (below). - Talks to Aegis-side wallet signatures when a request claims to be paid. +### Why the bundled list ships with no credentials + +A `vless://` URL **is** the credential for its exit — UUID plus Reality +parameters is all a client needs. That leads to a rule worth stating +explicitly, because it has now been violated once and nearly a second +time in a different wrapper: + +> A shared exit credential must never be written anywhere immutable or +> world-readable. Not the addon tarball (signed, immutable, mirrored +> forever). Not a git commit (history is permanent). Not a Sia object +> (mutable, but still world-readable, and the addon source that names +> the URL is public). + +The first attempt baked the three URLs into `server-list.json` and +shipped it as `vpn-0.1.3.tar.gz`; that was rolled back, the tarball +deleted from Sia, and all three servers' UUID + Reality keypair + +shortId rotated. The second attempt was going to host the same JSON on +Sia and overlay it — rotatable and out of git, which is genuinely +better, but still publishing a secret. Both are the same category of +mistake. + +The distinction that actually matters is not *where* the shared +credential lives but *whether a shared credential exists at all*. With +per-session minting there is nothing to leak: each connect gets its own +UUID with a TTL, revocable on its own, attributable to one requester. +That is why the bundled entries sit at `awaiting-key-issuer` rather +than being filled in — the honest state, not a placeholder someone +should be tempted to complete. + +Working credentials for the three live exits are in the repo-root +`.keys/vpn-servers.json` (gitignored via `.gitignore:70 /.keys/`) for +operator testing via the panel's Custom box. They stay there. + ### `POST /api/vpn/new-client` Request body: diff --git a/bundled-addons/vpn/addon.json b/bundled-addons/vpn/addon.json index fc1064f..d1d8d70 100644 --- a/bundled-addons/vpn/addon.json +++ b/bundled-addons/vpn/addon.json @@ -1,7 +1,7 @@ { "id": "vpn", "name": "VPN", - "version": "0.1.3", + "version": "0.1.4", "description": "Route Theseus's traffic through a Silent Mode VPN endpoint. Runs sing-box locally, exits at one of our servers, and switches on with one click. Paste any vless:// URL to point it at your own endpoint instead.", "author": "Silent Mode", "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEyIDJMNCA1djdjMCA1IDMuNSA5LjIgOCAxMCA0LjUtLjggOC01IDgtMTBWNWwtOC0zeiIgZmlsbD0iIzBhYzE4ZSIvPjxwYXRoIGQ9Ik05IDEybDIgMiA0LTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=", diff --git a/bundled-addons/vpn/panel.html b/bundled-addons/vpn/panel.html index f7e90b1..3be1747 100644 --- a/bundled-addons/vpn/panel.html +++ b/bundled-addons/vpn/panel.html @@ -101,7 +101,7 @@ button.btn.small { padding: 4px 9px; font-size: 11.5px; }