From ba6d9ca1d2991e51e296a7b4b7df388092ca9223 Mon Sep 17 00:00:00 2001 From: Ivan Razin Date: Fri, 3 Jul 2026 15:54:56 +0300 Subject: [PATCH] Add h2/http1.1 ALPN to tls hosts; make raw diag link self-authorize Host ALPN: ws/xhttp/trojan hosts now advertise ["h2","http/1.1"]; reality host gets [] (its ALPN comes from the reality stream). Diagnostics access: opening the diag path directly without the diag_key cookie previously 404'd, so a bookmarked link only worked after manually visiting //diag. Now the diag page 302-bounces unauthenticated hits through the SSO bridge, which validates the 3x-ui panel session and mints the cookie, then redirects back - so the link works once you're logged into the panel. API and asset sub-locations still 404 without the cookie (only the HTML page redirects, never XHR/asset requests). Verified end to end with nginx + the auth semantics of the installed 3x-ui v3.4.2: logged-in raw hit resolves to the page with no loop, anonymous hit lands on the panel login. Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 15 +++++++++------ x-ui-latest.sh | 18 ++++++++++-------- x-ui-patch.sh | 4 +++- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8390b1d..e534b4e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -42,12 +42,15 @@ effect on servers only after push to `main`. 10. Downloads a random fake cover site (`install_fake_site`) → `/var/www/html/` 11. Installs network diagnostics (`install_diagnostics`) → `/var/www/diagnostics/` + `mtr-backend` systemd service (hardened, dedicated user, localhost-only). - Access only via `//diag` (SSO bridge): nginx auth_request validates - the 3x-ui session against `GET /panel/` (with X-Requested-With header → - 401 instead of login redirect), then issues a path-scoped `diag_key` cookie and - redirects to the diag page; all diag locations 404 without that cookie. - The 3x-ui session cookie is Path-scoped to the panel base path, which is why - the bridge must live under the panel path + Access is gated by the 3x-ui panel session via an nginx SSO bridge at + `//diag`: auth_request validates the session against + `GET /panel/` (with X-Requested-With → 401 instead of a login + redirect), then issues a path-scoped `diag_key` cookie and redirects to the + diag page. Hitting the diag path directly without the cookie 302-bounces + through that bridge, so a bookmarked diag link "just works" once logged into + the panel (API/asset sub-locations stay 404 without the cookie). The 3x-ui + session cookie is Path-scoped to the panel base path, which is why the bridge + must live under the panel path 12. Tunes kernel/BBR (`tune_system`) 13. Sets up cron (`setup_cron`) — daily x-ui restart + nginx reload; monthly certbot renew with pre/post hooks stopping/starting nginx (certs are standalone-issued) diff --git a/x-ui-latest.sh b/x-ui-latest.sh index 94d1003..7583779 100644 --- a/x-ui-latest.sh +++ b/x-ui-latest.sh @@ -525,10 +525,12 @@ server { } # ── Network diagnostics page ───────────────────────────────────────────── - # Requires the diag cookie (issued by the SSO bridge above); re-setting it - # here extends the expiry on every visit + # No diag cookie yet → bounce through the SSO bridge, which checks the panel + # session and mints the cookie, so a bookmarked diag link "just works" once + # you're logged into the panel. (Only the HTML page redirects; the API/asset + # sub-locations below stay 404 without the cookie.) location ^~ ${diag_path} { - if (\$diag_auth = 0) { return 404; } + if (\$diag_auth = 0) { return 302 /${panel_path}/diag; } limit_req zone=diag_page burst=10 nodelay; limit_conn per_ip 5; alias /var/www/diagnostics/; @@ -949,12 +951,12 @@ VALUES ( -- rendered as the share-link endpoint at subscription time. -- REALITY keeps its own TLS params (security=same); the rest front through -- nginx at :443 with TLS. -INSERT INTO "hosts" ("inbound_id","sort_order","remark","address","port","security","fingerprint") +INSERT INTO "hosts" ("inbound_id","sort_order","remark","address","port","security","fingerprint","alpn") VALUES - ((SELECT id FROM inbounds WHERE tag='inbound-8443'), 0, 'reality', '${domain}', 443, 'same', ''), - ((SELECT id FROM inbounds WHERE tag='inbound-${ws_port}'), 0, 'ws', '${domain}', 443, 'tls', 'firefox'), - ((SELECT id FROM inbounds WHERE tag='inbound-/dev/shm/uds2023.sock,0666:0|'), 0, 'xhttp', '${domain}', 443, 'tls', 'firefox'), - ((SELECT id FROM inbounds WHERE tag='inbound-${trojan_port}'), 0, 'trojan', '${domain}', 443, 'tls', 'firefox'); + ((SELECT id FROM inbounds WHERE tag='inbound-8443'), 0, 'reality', '${domain}', 443, 'same', '', '[]'), + ((SELECT id FROM inbounds WHERE tag='inbound-${ws_port}'), 0, 'ws', '${domain}', 443, 'tls', 'firefox', '["h2","http/1.1"]'), + ((SELECT id FROM inbounds WHERE tag='inbound-/dev/shm/uds2023.sock,0666:0|'), 0, 'xhttp', '${domain}', 443, 'tls', 'firefox', '["h2","http/1.1"]'), + ((SELECT id FROM inbounds WHERE tag='inbound-${trojan_port}'), 0, 'trojan', '${domain}', 443, 'tls', 'firefox', '["h2","http/1.1"]'); EOF /usr/local/x-ui/x-ui setting \ diff --git a/x-ui-patch.sh b/x-ui-patch.sh index f9e19ee..c2a0f3b 100644 --- a/x-ui-patch.sh +++ b/x-ui-patch.sh @@ -392,8 +392,10 @@ server { proxy_intercept_errors off; } + # No diag cookie yet → bounce through the SSO bridge (checks panel session, + # mints the cookie) so a bookmarked diag link works once logged into the panel. location ^~ ${diag_path} { - if (\$diag_auth = 0) { return 404; } + if (\$diag_auth = 0) { return 302 /${panel_path}/diag; } limit_req zone=diag_page burst=10 nodelay; limit_conn per_ip 5; alias /var/www/diagnostics/;