fix(wg): harden clusev-wg.sh — read EOF, awk ENVIRON, endpoint + wg.env guards (review)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat/v1-foundation
boban 2026-06-20 22:33:37 +02:00
parent dd964a2e8b
commit 8caa78b2b3
1 changed files with 29 additions and 13 deletions

View File

@ -95,6 +95,7 @@ cmd_down() {
next_free_ip() { next_free_ip() {
# shellcheck disable=SC1090 # shellcheck disable=SC1090
. "$WG_ENV" . "$WG_ENV"
[ -n "${WG_SUBNET:-}" ] || die "WG_SUBNET fehlt in ${WG_ENV} — Setup erneut ausfuehren."
local prefix="${WG_SUBNET%%/*}"; prefix="${prefix%.*}" # first three octets (SP1: /24) local prefix="${WG_SUBNET%%/*}"; prefix="${prefix%.*}" # first three octets (SP1: /24)
local used; used="$(awk -F= '/AllowedIPs/{gsub(/[ \t]/,"",$2);split($2,a,"/");print a[1]}' "$WG_CONF" 2>/dev/null || true)" local used; used="$(awk -F= '/AllowedIPs/{gsub(/[ \t]/,"",$2);split($2,a,"/");print a[1]}' "$WG_CONF" 2>/dev/null || true)"
used="$(printf '%s\n%s\n' "$used" "${WG_SERVER_IP:-}")" used="$(printf '%s\n%s\n' "$used" "${WG_SERVER_IP:-}")"
@ -112,6 +113,7 @@ cmd_add_peer() {
require_setup require_setup
# shellcheck disable=SC1090 # shellcheck disable=SC1090
. "$WG_ENV" . "$WG_ENV"
[ -n "${WG_SUBNET:-}" ] && [ -n "${WG_SERVER_PUBKEY:-}" ] && [ -n "${WG_ENDPOINT:-}" ] || die "wg.env unvollstaendig — Setup erneut ausfuehren."
grep -qF "# clusev-peer: ${name}" "$WG_CONF" 2>/dev/null && die "Peer '${name}' existiert bereits." grep -qF "# clusev-peer: ${name}" "$WG_CONF" 2>/dev/null && die "Peer '${name}' existiert bereits."
local ip; ip="$(next_free_ip)" || die "Kein freier Adressraum im Subnetz ${WG_SUBNET}." local ip; ip="$(next_free_ip)" || die "Kein freier Adressraum im Subnetz ${WG_SUBNET}."
local cpriv cpub local cpriv cpub
@ -155,13 +157,13 @@ cmd_remove_peer() {
local name="${1:-}"; [ -n "$name" ] || die "Name fehlt: clusev wg remove-peer <name>" local name="${1:-}"; [ -n "$name" ] || die "Name fehlt: clusev wg remove-peer <name>"
require_setup require_setup
local pub local pub
pub="$(awk -v n="# clusev-peer: ${name}" '$0==n{f=1;next} f&&/PublicKey/{gsub(/[ \t]/,"");sub(/PublicKey=/,"");print;exit}' "$WG_CONF")" pub="$(WANT="# clusev-peer: ${name}" awk '$0==ENVIRON["WANT"]{f=1;next} f&&/PublicKey/{gsub(/[ \t]/,"");sub(/PublicKey=/,"");print;exit}' "$WG_CONF")"
[ -n "$pub" ] || die "Peer '${name}' nicht gefunden." [ -n "$pub" ] || die "Peer '${name}' nicht gefunden."
wg set "$WG_IF" peer "$pub" remove 2>/dev/null || true wg set "$WG_IF" peer "$pub" remove 2>/dev/null || true
# drop the block from the marker comment up to (and including) the trailing blank line # drop the block from the marker comment up to (and including) the trailing blank line
local tmp; tmp="$(mktemp)" local tmp; tmp="$(mktemp)"
awk -v n="# clusev-peer: ${name}" ' WANT="# clusev-peer: ${name}" awk '
$0==n {drop=1; next} $0==ENVIRON["WANT"] {drop=1; next}
drop && /^[[:space:]]*$/ {drop=0; next} drop && /^[[:space:]]*$/ {drop=0; next}
drop {next} drop {next}
{print} {print}
@ -188,26 +190,40 @@ cmd_setup() {
have wg || die "wireguard-tools nicht installiert (erwartet via install.sh)." have wg || die "wireguard-tools nicht installiert (erwartet via install.sh)."
if [ -f "$WG_CONF" ]; then if [ -f "$WG_CONF" ]; then
warn "${WG_CONF} existiert bereits — bestehende Peers gingen bei Neukonfiguration verloren." warn "${WG_CONF} existiert bereits — bestehende Peers gingen bei Neukonfiguration verloren."
read -rp " Trotzdem neu konfigurieren? [reconfigure/abort] (abort): " ans read -rp " Trotzdem neu konfigurieren? [reconfigure/abort] (abort): " ans || ans=abort
[ "${ans:-abort}" = "reconfigure" ] || die "Abgebrochen — bestehende Konfiguration unberuehrt." [ "${ans:-abort}" = "reconfigure" ] || die "Abgebrochen — bestehende Konfiguration unberuehrt."
fi fi
local subnet default_subnet="10.99.0.0/24" local subnet default_subnet="10.99.0.0/24"
while :; do while :; do
read -rp " WG-Subnetz (privates /24, darf NICHT mit LAN/VPN kollidieren) [${default_subnet}]: " subnet if ! read -rp " WG-Subnetz (privates /24, darf NICHT mit LAN/VPN kollidieren) [${default_subnet}]: " subnet; then
subnet="$default_subnet" # closed stdin → take the default once
fi
subnet="${subnet:-$default_subnet}" subnet="${subnet:-$default_subnet}"
if subnet_collides "$subnet"; then warn "Subnetz ${subnet} ueberschneidet eine bestehende Route/Adresse — bitte ein anderes waehlen."; continue; fi if subnet_collides "$subnet"; then
warn "Subnetz ${subnet} ueberschneidet eine bestehende Route/Adresse — bitte ein anderes waehlen."
[ -t 0 ] || die "Subnetz-Kollision und keine interaktive Eingabe moeglich (stdin geschlossen)."
continue
fi
break break
done done
local server_ip default_ip port endpoint default_ep peer1 local server_ip default_ip port endpoint peer1
default_ip="$(subnet_first_ip "$subnet")" default_ip="$(subnet_first_ip "$subnet")"
read -rp " Server-Tunnel-IP [${default_ip}]: " server_ip; server_ip="${server_ip:-$default_ip}" read -rp " Server-Tunnel-IP [${default_ip}]: " server_ip || true; server_ip="${server_ip:-$default_ip}"
read -rp " Listen-Port (UDP) [51820]: " port; port="${port:-51820}" read -rp " Listen-Port (UDP) [51820]: " port || true; port="${port:-51820}"
default_ep="$(detect_endpoint_ip):${port}" local ep; ep="$(detect_endpoint_ip)"
info "Hinweis: hinter NAT/Cloud-LB ist die erkannte IP evtl. NICHT die Waehl-Adresse der Clients — vor 'clusev wg up' pruefen." if [ -n "$ep" ]; then
read -rp " Oeffentlicher Endpoint (IP oder DNS:Port) [${default_ep}]: " endpoint; endpoint="${endpoint:-$default_ep}" local default_ep="${ep}:${port}"
read -rp " Name des ersten Peers [client-1]: " peer1; peer1="${peer1:-client-1}" info "Hinweis: hinter NAT/Cloud-LB ist die erkannte IP evtl. NICHT die Waehl-Adresse der Clients — vor 'clusev wg up' pruefen."
read -rp " Oeffentlicher Endpoint (IP oder DNS:Port) [${default_ep}]: " endpoint || true
endpoint="${endpoint:-$default_ep}"
else
warn "Oeffentliche IP konnte nicht erkannt werden — bitte Endpoint manuell angeben."
read -rp " Oeffentlicher Endpoint (IP oder DNS:Port, erforderlich): " endpoint || true
fi
[ -n "$endpoint" ] || die "Endpoint erforderlich."
read -rp " Name des ersten Peers [client-1]: " peer1 || true; peer1="${peer1:-client-1}"
umask 077; mkdir -p "$WG_DIR" "$STATE_DIR" umask 077; mkdir -p "$WG_DIR" "$STATE_DIR"
local srv_priv srv_pub prefix local srv_priv srv_pub prefix