From 7ff02c4e68235092cb9fc1753579bcaed47b5fd1 Mon Sep 17 00:00:00 2001 From: boban Date: Sun, 21 Jun 2026 00:49:55 +0200 Subject: [PATCH] feat(wg): set-endpoint/set-port/set-subnet host actions + serve-request branches --- docker/wg/clusev-wg.sh | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docker/wg/clusev-wg.sh b/docker/wg/clusev-wg.sh index 2e31ec2..49b387a 100755 --- a/docker/wg/clusev-wg.sh +++ b/docker/wg/clusev-wg.sh @@ -322,6 +322,10 @@ cmd_serve_request() { [ -n "$id" ] || return 0 action="$(printf '%s' "$json" | grep -oE '"action":"[a-z-]{1,24}"' | head -n1 | sed -E 's/.*:"//; s/"$//')" name="$(printf '%s' "$json" | grep -oE '"name":"[A-Za-z0-9._-]{1,64}"' | head -n1 | sed -E 's/.*:"//; s/"$//')" + local endpoint port subnet + endpoint="$(printf '%s' "$json" | grep -oE '"endpoint":"[A-Za-z0-9.:_-]{1,128}"' | head -n1 | sed -E 's/.*:"//; s/"$//')" + port="$(printf '%s' "$json" | grep -oE '"port":"[0-9]{1,5}"' | head -n1 | sed -E 's/.*:"//; s/"$//')" + subnet="$(printf '%s' "$json" | grep -oE '"subnet":"[0-9./]{1,18}"' | head -n1 | sed -E 's/.*:"//; s/"$//')" local ok=false msg='ok' config='' case "$action" in @@ -335,6 +339,9 @@ cmd_serve_request() { else msg='invalid-name'; fi ;; gate-up) if _gate_up_now >/dev/null 2>&1; then ok=true; else msg='gate-up-failed'; fi ;; gate-down) if cmd_down >/dev/null 2>&1; then ok=true; else msg='gate-down-failed'; fi ;; + set-endpoint) if [ -n "$endpoint" ] && _set_endpoint "$endpoint" >/dev/null 2>&1; then ok=true; else msg='set-endpoint-failed'; fi ;; + set-port) if [ -n "$port" ] && _set_port "$port" >/dev/null 2>&1; then ok=true; else msg='set-port-failed'; fi ;; + set-subnet) if [ -n "$subnet" ] && _set_subnet "$subnet" >/dev/null 2>&1; then ok=true; else msg='set-subnet-failed'; fi ;; *) msg='unknown-action' ;; esac @@ -350,6 +357,40 @@ cmd_serve_request() { # Emit run/wg-status.json (atomic temp+mv). Public, NO secrets. If WG isn't configured, emits # {"configured":false}. Run every few seconds by clusev-wg-collect.timer; the dashboard reads it. +# ── settings mutators (cores: no prints; errors to stderr; non-zero on fail) ────────────────── +_set_endpoint() { + local ep="$1"; require_setup + case "$ep" in *[!A-Za-z0-9.:_-]*|'') echo "bad endpoint" >&2; return 1 ;; esac + sed -i "s#^WG_ENDPOINT=.*#WG_ENDPOINT=${ep}#" "$WG_ENV" +} + +_set_port() { + local port="$1"; require_setup + case "$port" in ''|*[!0-9]*) echo "bad port" >&2; return 1 ;; esac + [ "$port" -ge 1 ] && [ "$port" -le 65535 ] || { echo "port out of range" >&2; return 1; } + sed -i "s#^ListenPort = .*#ListenPort = ${port}#" "$WG_CONF" + sed -i "s#^WG_PORT=.*#WG_PORT=${port}#" "$WG_ENV" + systemctl restart "wg-quick@${WG_IF}" || { echo "wg-quick restart failed" >&2; return 1; } +} + +_set_subnet() { + local subnet="$1"; require_setup + case "$subnet" in *[!0-9./]*|'') echo "bad subnet" >&2; return 1 ;; esac + printf '%s' "$subnet" | grep -qE '^[0-9]{1,3}(\.[0-9]{1,3}){3}/[0-9]{1,2}$' || { echo "bad subnet" >&2; return 1; } + subnet_collides "$subnet" && { echo "subnet collides with an existing route/address" >&2; return 1; } + local prefix server_ip + prefix="${subnet##*/}" + server_ip="$(subnet_first_ip "$subnet")" + sed -i "s#^Address = .*#Address = ${server_ip}/${prefix}#" "$WG_CONF" + sed -i "s#^WG_SUBNET=.*#WG_SUBNET=${subnet}#" "$WG_ENV" + sed -i "s#^WG_SERVER_IP=.*#WG_SERVER_IP=${server_ip}#" "$WG_ENV" + systemctl restart "wg-quick@${WG_IF}" || { echo "wg-quick restart failed" >&2; return 1; } +} + +cmd_set_endpoint() { need_root set-endpoint; local v="${1:-}"; [ -n "$v" ] || die "Endpoint fehlt."; _set_endpoint "$v" || die "Endpoint setzen fehlgeschlagen."; bold "Endpoint gesetzt: ${v}"; } +cmd_set_port() { need_root set-port; local v="${1:-}"; [ -n "$v" ] || die "Port fehlt."; _set_port "$v" || die "Port setzen fehlgeschlagen."; bold "Port gesetzt: ${v} (Clients muessen den Port aktualisieren)."; } +cmd_set_subnet() { need_root set-subnet; local v="${1:-}"; [ -n "$v" ] || die "Subnetz fehlt."; _set_subnet "$v" || die "Subnetz setzen fehlgeschlagen."; bold "Subnetz gesetzt: ${v} (bestehende Peers muessen neu angelegt werden)."; } + cmd_collect() { mkdir -p "$RUN_DIR" 2>/dev/null || true # Drop result + QR sidecars older than 60 s (they carry a private key; the app reads them once). @@ -415,6 +456,9 @@ clusev wg — WireGuard-Zugang (Host) clusev wg status Tunnel, Peers, Gate-Status anzeigen clusev wg add-peer neuen Client anlegen (+ QR-Code) clusev wg remove-peer Client entfernen + clusev wg set-endpoint oeffentlichen Endpoint aendern + clusev wg set-port Listen-Port aendern (Clients neu) + clusev wg set-subnet Subnetz aendern (Peers neu anlegen) SSH (22) und der WG-Port bleiben IMMER offen. 'clusev wg down' per SSH ist der Notausgang. EOF @@ -428,6 +472,9 @@ case "$cmd" in status) cmd_status "$@" ;; add-peer) cmd_add_peer "$@" ;; remove-peer) cmd_remove_peer "$@" ;; + set-endpoint) cmd_set_endpoint "$@" ;; + set-port) cmd_set_port "$@" ;; + set-subnet) cmd_set_subnet "$@" ;; gate-apply) need_root gate-apply; gate_apply ;; # called by clusev-wg-gate.service collect) cmd_collect ;; # called by clusev-wg-collect.timer (read-only; no root needed) serve-request) cmd_serve_request ;; # called by clusev-wg-request.service