From 906822b42b912f2aaf211cb9e10d6b892f9c2a7f Mon Sep 17 00:00:00 2001 From: Ivan Razin Date: Mon, 6 Jul 2026 10:25:01 +0300 Subject: [PATCH] Fix MTR failing under systemd: grant CAP_NET_RAW via ambient capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mtr ran fine as the mtr-backend user in a shell but failed under the systemd service with: mtr-packet: Failure to open IPv4 sockets: Permission denied Cause: the unit sets NoNewPrivileges=yes, which strips file capabilities, and AmbientCapabilities/CapabilityBoundingSet were empty — so mtr-packet (the helper that opens the raw ICMP socket) had no CAP_NET_RAW. Interactive runs worked because they had no NoNewPrivileges. - Grant CAP_NET_RAW the systemd-native way (AmbientCapabilities + CapabilityBoundingSet), which survives NoNewPrivileges. Fixed in both the full installer and the patch service unit. - setcap now also targets mtr-packet, not just mtr. - Add proxy_intercept_errors off to the diag /api/mtr location: the server-level "proxy_intercept_errors on" was rewriting a backend 500 into an HTML 404, which broke the frontend's response.json() and left the client IP stuck on "detecting…". Co-Authored-By: Claude Opus 4.8 --- x-ui-latest.sh | 16 +++++++++++++--- x-ui-patch.sh | 14 +++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/x-ui-latest.sh b/x-ui-latest.sh index ab84d3c..4a09a64 100644 --- a/x-ui-latest.sh +++ b/x-ui-latest.sh @@ -575,6 +575,10 @@ server { proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_read_timeout 120s; proxy_send_timeout 120s; + # Let the backend's JSON error bodies through; the server-level + # "proxy_intercept_errors on" would otherwise rewrite a 500 into an HTML + # 404 and break the frontend's response.json() parse. + proxy_intercept_errors off; } # ── LibreSpeed upload sink ─────────────────────────────────────────────── @@ -1068,7 +1072,9 @@ install_diagnostics() { chmod 755 "${backend_script}" # Grant mtr raw socket capability (runs as restricted user, no root needed) - command -v setcap &>/dev/null && setcap cap_net_raw+ep "$(command -v mtr)" 2>/dev/null || true + # mtr-packet is the helper that actually opens the raw socket + command -v setcap &>/dev/null && setcap cap_net_raw+ep "$(command -v mtr)" 2>/dev/null || true + command -v setcap &>/dev/null && setcap cap_net_raw+ep "$(command -v mtr-packet)" 2>/dev/null || true # Dedicated system user for mtr-backend id mtr-backend &>/dev/null || \ @@ -1101,8 +1107,12 @@ MemoryDenyWriteExecute=yes RestrictRealtime=yes RestrictSUIDSGID=yes RemoveIPC=yes -AmbientCapabilities= -CapabilityBoundingSet= +# mtr-packet opens raw ICMP sockets. NoNewPrivileges=yes strips the file +# capability off the mtr binary, so grant CAP_NET_RAW the systemd-native way +# (ambient caps survive NoNewPrivileges). Empty here = mtr fails with +# "Failure to open IPv4 sockets: Permission denied". +AmbientCapabilities=CAP_NET_RAW +CapabilityBoundingSet=CAP_NET_RAW StandardOutput=journal StandardError=journal SyslogIdentifier=mtr-backend diff --git a/x-ui-patch.sh b/x-ui-patch.sh index a7e3277..dc506e8 100644 --- a/x-ui-patch.sh +++ b/x-ui-patch.sh @@ -488,6 +488,10 @@ server { proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_read_timeout 120s; proxy_send_timeout 120s; + # Let the backend's JSON error bodies through; the server-level + # "proxy_intercept_errors on" would otherwise rewrite a 500 into an HTML + # 404 and break the frontend's response.json() parse. + proxy_intercept_errors off; } location ^~ ${diag_path}api/st/up { if (\$diag_auth = 0) { return 404; } @@ -614,7 +618,9 @@ id mtr-backend &>/dev/null || \ useradd --system --no-create-home --shell /usr/sbin/nologin mtr-backend if command -v setcap &>/dev/null; then - setcap cap_net_raw+ep "$(command -v mtr)" 2>/dev/null || true + # mtr-packet is the helper that actually opens the raw socket + setcap cap_net_raw+ep "$(command -v mtr)" 2>/dev/null || true + setcap cap_net_raw+ep "$(command -v mtr-packet)" 2>/dev/null || true fi cat > /etc/systemd/system/mtr-backend.service <