Fix diagnostics 500: harden auth bridge + repair missing panel cert
Root cause: nginx auth_request returns a raw 500 to the browser whenever
the /__diag_auth subrequest to the panel returns anything other than
2xx/401/403. Two ways that happens:
- the panel's TLS cert is recorded in the DB (webCertFile) but the file
or symlink is missing on disk (e.g. dangling /root/cert symlink), so
the panel can't serve HTTPS and proxy_pass https:// yields a 502; or
- the panel returns a login 302 for the AJAX auth probe.
Either way the browser got a 500 on the diagnostics page.
- Both scripts: add proxy_intercept_errors on + an error_page in
/__diag_auth that coerces every non-allow status (3xx/4xx/5xx, incl.
401/403 so the server-level "=404" trap can't rewrite a genuine deny)
into a 401 -> @diag_denied, so the flow degrades to a panel-login
redirect instead of a 500. Verified with nginx 1.30.3 across
200/401/302/502 upstream backends: all return a clean 302.
- x-ui-patch.sh: the panel-HTTPS check now also treats a configured-but-
missing cert (-e follows symlinks) as needing repair, re-symlinking the
Let's Encrypt cert and re-running `x-ui cert`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2ed4984989
commit
88466b9b21
+9
-1
@@ -530,8 +530,16 @@ server {
|
|||||||
proxy_set_header X-Requested-With XMLHttpRequest;
|
proxy_set_header X-Requested-With XMLHttpRequest;
|
||||||
proxy_pass_request_body off;
|
proxy_pass_request_body off;
|
||||||
proxy_set_header Content-Length "";
|
proxy_set_header Content-Length "";
|
||||||
proxy_intercept_errors off;
|
# auth_request emits a raw 500 to the browser if the subrequest returns
|
||||||
|
# anything other than 2xx / 401 / 403 (a login 302, or a 502 when the
|
||||||
|
# panel's HTTPS cert is missing). Coerce every such status to a 401 deny
|
||||||
|
# so the main location redirects to the panel login instead of 500ing.
|
||||||
|
# 401/403 must be listed too, else the server-level "error_page 401 =404"
|
||||||
|
# hijacks a genuine deny into a 404 (which auth_request then 500s on).
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
error_page 300 301 302 303 304 305 307 308 400 401 402 403 404 405 500 501 502 503 504 =401 @diag_denied;
|
||||||
}
|
}
|
||||||
|
location @diag_denied { return 401; }
|
||||||
|
|
||||||
# ── Network diagnostics page ─────────────────────────────────────────────
|
# ── Network diagnostics page ─────────────────────────────────────────────
|
||||||
# No diag cookie yet → bounce through the SSO bridge, which checks the panel
|
# No diag cookie yet → bounce through the SSO bridge, which checks the panel
|
||||||
|
|||||||
+22
-5
@@ -78,8 +78,19 @@ printf " reality_domain = %s\n" "$reality_domain"
|
|||||||
# Mirror the main installer: symlink the Let's Encrypt cert into /root/cert and
|
# Mirror the main installer: symlink the Let's Encrypt cert into /root/cert and
|
||||||
# register it with `x-ui cert`.
|
# register it with `x-ui cert`.
|
||||||
web_cert=$(db "SELECT value FROM settings WHERE key='webCertFile';")
|
web_cert=$(db "SELECT value FROM settings WHERE key='webCertFile';")
|
||||||
if [[ -z "$web_cert" ]]; then
|
web_key=$( db "SELECT value FROM settings WHERE key='webKeyFile';")
|
||||||
blue "Panel has no TLS cert configured — enabling HTTPS..."
|
# The DB may reference a cert that no longer exists on disk (e.g. a dangling
|
||||||
|
# /root/cert symlink after a restore) — the panel then fails to serve HTTPS and
|
||||||
|
# every proxy_pass https:// (panel + diag bridge) breaks. "-e" follows symlinks,
|
||||||
|
# so a broken link reads as missing.
|
||||||
|
if [[ -z "$web_cert" || -z "$web_key" ]]; then
|
||||||
|
need_cert=1; blue "Panel has no TLS cert configured — enabling HTTPS..."
|
||||||
|
elif [[ ! -e "$web_cert" || ! -e "$web_key" ]]; then
|
||||||
|
need_cert=1; blue "Panel cert configured but missing on disk ($web_cert) — repairing..."
|
||||||
|
else
|
||||||
|
need_cert=0; blue "Panel TLS cert present: $web_cert"
|
||||||
|
fi
|
||||||
|
if [[ $need_cert -eq 1 ]]; then
|
||||||
if [[ -d "/etc/letsencrypt/live/${domain}" ]]; then
|
if [[ -d "/etc/letsencrypt/live/${domain}" ]]; then
|
||||||
mkdir -p "/root/cert/${domain}"
|
mkdir -p "/root/cert/${domain}"
|
||||||
chmod 755 /root/cert/* 2>/dev/null || true
|
chmod 755 /root/cert/* 2>/dev/null || true
|
||||||
@@ -97,8 +108,6 @@ if [[ -z "$web_cert" ]]; then
|
|||||||
else
|
else
|
||||||
red "No Let's Encrypt cert for ${domain} at /etc/letsencrypt/live/${domain} — cannot enable panel HTTPS."
|
red "No Let's Encrypt cert for ${domain} at /etc/letsencrypt/live/${domain} — cannot enable panel HTTPS."
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
blue "Panel TLS cert already configured."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── detect xhttp_path ─────────────────────────────────────────────────────────
|
# ── detect xhttp_path ─────────────────────────────────────────────────────────
|
||||||
@@ -428,8 +437,16 @@ server {
|
|||||||
proxy_set_header X-Requested-With XMLHttpRequest;
|
proxy_set_header X-Requested-With XMLHttpRequest;
|
||||||
proxy_pass_request_body off;
|
proxy_pass_request_body off;
|
||||||
proxy_set_header Content-Length "";
|
proxy_set_header Content-Length "";
|
||||||
proxy_intercept_errors off;
|
# auth_request emits a raw 500 to the browser if the subrequest returns
|
||||||
|
# anything other than 2xx / 401 / 403 (a login 302, or a 502 when the
|
||||||
|
# panel's HTTPS cert is missing). Coerce every such status to a 401 deny
|
||||||
|
# so the main location redirects to the panel login instead of 500ing.
|
||||||
|
# 401/403 must be listed too, else the server-level "error_page 401 =404"
|
||||||
|
# hijacks a genuine deny into a 404 (which auth_request then 500s on).
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
error_page 300 301 302 303 304 305 307 308 400 401 402 403 404 405 500 501 502 503 504 =401 @diag_denied;
|
||||||
}
|
}
|
||||||
|
location @diag_denied { return 401; }
|
||||||
|
|
||||||
# No diag cookie yet → bounce through the SSO bridge (checks panel session,
|
# 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.
|
# mints the cookie) so a bookmarked diag link works once logged into the panel.
|
||||||
|
|||||||
Reference in New Issue
Block a user