From 174c10505a03346675ffb245308435ecb65e413b Mon Sep 17 00:00:00 2001 From: duffyduck Date: Wed, 7 Oct 2026 13:34:44 +0200 Subject: [PATCH] Firewall-Check fuer den Dashboard-Port einbauen - firewall-check.sh (auch ./setup.sh firewall): prueft Listener, Container- Portweiterleitung (DNAT), ip_forward, firewalld, ufw/ufw-docker, iptables (INPUT, DOCKER-USER), natives nftables, CSF, Shorewall und lokalen HTTPS-Test - Legt fehlende Regeln an (Rueckfrage, --yes ohne, --check nur pruefen); Podman: podman network reload --all bei fehlender Weiterleitung - Erkennt "TCP offen, aber kein HTTPS" (conmon haelt Port nur reserviert) - setup.sh: kein firewall-cmd --reload mehr (loescht ggf. Container-Regeln), up ruft stattdessen den Firewall-Check auf - README: Abschnitt Firewall-Check Co-Authored-By: Claude Opus 5.5 (1M context) --- README.md | 36 ++++- firewall-check.sh | 332 ++++++++++++++++++++++++++++++++++++++++++++++ setup.sh | 27 ++-- 3 files changed, 380 insertions(+), 15 deletions(-) create mode 100755 firewall-check.sh diff --git a/README.md b/README.md index fc204c3..739f1c2 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Voraussetzungen: Docker **oder** Podman, ca. 8 GB RAM frei, ca. 10 GB Platz für Als root (`sudo ./setup.sh ...`) passt das Skript das System zusätzlich an: - `vm.max_map_count=262144` (dauerhaft in `/etc/sysctl.d/99-wazuh.conf`) -- firewalld: Port für das Dashboard freigeben +- Firewall-Check: Dashboard-Port prüfen und fehlende Regeln anlegen (siehe unten) - Podman: `podman-restart.service` aktivieren, damit der Stack nach einem Reboot startet Ohne root gibt es dafür nur Hinweise. Mit `WAZUH_SKIP_SYSCTL=1` bleibt der Kernel-Parameter @@ -147,6 +147,38 @@ Der erste Start dauert 1–3 Minuten, bis der Indexer bereit ist. erzeugt. Der Manager schreibt seine Agentless- und Localfile-Konfiguration beim Start aus `hosts.yml` neu (`manager/generate.py`). +## Dashboard nicht erreichbar? Firewall-Check + +```bash +sudo ./setup.sh firewall # = sudo ./firewall-check.sh (prüft, fragt vor Änderungen) +sudo ./setup.sh firewall --yes # fehlende Regeln ohne Rückfrage anlegen +./setup.sh firewall --check # nur prüfen +``` + +Geprüft wird der Dashboard-Port aus `.env` (anderer Port: `--port N`, Dienst ohne HTTPS: `--tcp`): + +| Prüfung | Automatische Behebung | +|---|---| +| Lauscht etwas auf dem Port (nicht nur auf 127.0.0.1)? | – | +| Container-Portweiterleitung (DNAT) vorhanden? | Podman: `podman network reload --all`. Docker: nur Hinweis, weil `systemctl restart docker` alle Container neu startet. | +| `net.ipv4.ip_forward` | einschalten (dauerhaft) | +| firewalld (Zone des Interfaces mit Default-Route) | Port freigeben, sofort und dauerhaft, **ohne** `--reload` | +| ufw, auch ufw-docker | `ufw allow` bzw. `ufw route allow` | +| iptables (INPUT-Policy, DOCKER-USER) | ACCEPT-Regel. Wird gespeichert, wenn netfilter-persistent oder iptables-services vorhanden ist. | +| natives nftables (eigene `input`-Kette mit drop) | `nft insert rule …` (dauerhaft selbst in nftables.conf eintragen) | +| CSF, Shorewall | erkennen, nur Hinweis | +| Lokaler HTTPS-Test (localhost und Server-IP) | – | + +**Typischer Fall „netstat zeigt den Port, aber nichts kommt an“:** Bei Podman hält `conmon` +den Port reserviert, auch wenn die Portweiterleitung fehlt. Das passiert z. B., wenn die +Firewall nach dem Container-Start neu geladen wurde (`firewall-cmd --reload`, Neustart von +iptables/nftables). Der Check erkennt das am fehlenden DNAT bzw. an „TCP offen, aber kein +HTTPS“ und lädt die Podman-Regeln neu. + +`./setup.sh up` ruft den Check nach dem Start automatisch auf, als root mit `--yes`. Sperren +außerhalb des Servers (Cloud-Firewall, Proxmox-Firewall, Netzwerk-Firewall) kann er nicht +sehen. Dafür von einem anderen Rechner testen: `curl -kI https://:443` + ## Wo finde ich die Daten im Dashboard? Per SSH geholte Logs und Agentless-Ergebnisse laufen **über den Manager**. Im Dashboard @@ -180,6 +212,8 @@ Ports 1514 und 1515 sind nicht nach außen veröffentlicht. Nur der Collector er | Pfad | Zweck | |---|---| | `hosts.yml` | Die einzige Stelle für Hosts und Optionen | +| `setup.sh` | Einrichtung und Betrieb (erkennt Docker/Podman) | +| `firewall-check.sh` | Erreichbarkeit des Dashboard-Ports prüfen und reparieren | | `docker-compose.yml` | Stack. Nach außen geht nur das Dashboard (`DASHBOARD_PORT`) | | `.env` | Version, Zeitzone, Passwörter (von `setup.sh` erzeugt, nicht committen) | | `ssh/` | `id_ed25519` (privater Schlüssel, nicht committen), `known_hosts` | diff --git a/firewall-check.sh b/firewall-check.sh new file mode 100755 index 0000000..7324780 --- /dev/null +++ b/firewall-check.sh @@ -0,0 +1,332 @@ +#!/bin/bash +# Prueft, warum ein veroeffentlichter Port (Standard: Dashboard-Port aus .env) von aussen +# nicht erreichbar ist, und legt auf Wunsch die fehlende Regel an. +# +# sudo ./firewall-check.sh pruefen, bei Problemen nachfragen +# sudo ./firewall-check.sh --yes pruefen und Regeln ohne Rueckfrage anlegen +# ./firewall-check.sh --check nur pruefen, nichts aendern +# ./firewall-check.sh --port 8443 anderen Port pruefen +# ./firewall-check.sh --port 8080 --tcp Dienst ohne HTTPS (nur TCP-Verbindung pruefen) +# +# Erkennt: firewalld (RHEL/Fedora), ufw (Ubuntu/Debian), iptables (legacy und nft), +# natives nftables, Docker-Ketten (DOCKER-USER, ufw-docker), Podman/netavark, CSF, Shorewall. +# Prueft ausserdem: lauscht etwas auf dem Port, Portweiterleitung (DNAT) des Containers +# vorhanden, net.ipv4.ip_forward, lokale Erreichbarkeit. +set -uo pipefail +cd "$(dirname "$0")" + +PORT="" +MODE=ask # ask | yes | check +TCP_ONLY=0 # 1 = keine HTTPS-Antwort erwarten +for a in "$@"; do + case "$a" in + --yes|-y) MODE=yes ;; + --check) MODE=check ;; + --tcp) TCP_ONLY=1 ;; + --port=*) PORT="${a#--port=}" ;; + --port) shift_next=1 ;; + -h|--help) sed -n '2,15p' "$0"; exit 0 ;; + *) if [ "${shift_next:-0}" = 1 ]; then PORT="$a"; shift_next=0; else echo "Unbekannte Option: $a" >&2; exit 2; fi ;; + esac +done +[ -n "$PORT" ] || PORT=$(grep '^DASHBOARD_PORT=' .env 2>/dev/null | cut -d= -f2-) +PORT=${PORT:-443} +[[ $PORT =~ ^[0-9]+$ ]] || { echo "Ungueltiger Port: $PORT" >&2; exit 2; } +[ "$MODE" = ask ] && [ ! -t 0 ] && MODE=check # ohne Terminal nie ungefragt aendern + +ok() { echo -e " \e[1;32mOK\e[0m $*"; } +bad() { echo -e " \e[1;31mPROBLEM\e[0m $*"; } +note() { echo -e " \e[1;33mHINWEIS\e[0m $*"; } +head_() { echo -e "\n\e[1m$*\e[0m"; } +have() { command -v "$1" >/dev/null 2>&1; } +is_root() { [ "$(id -u)" -eq 0 ]; } + +FIX_DESC=() +FIX_CMD=() +add_fix() { FIX_DESC+=("$1"); FIX_CMD+=("$2"); } +PROBLEMS=0 +problem() { bad "$*"; PROBLEMS=$((PROBLEMS + 1)); } + +echo -e "\e[1mFirewall-Check fuer TCP-Port $PORT\e[0m" +is_root || note "Nicht als root: iptables/nftables/ufw lassen sich nicht auslesen. Fuer den vollen Check: sudo $0" + +# --------------------------------------------------------------------------- +head_ "1. Lauscht etwas auf Port $PORT?" +LISTEN=$(ss -Hltnp "sport = :$PORT" 2>/dev/null) +if [ -z "$LISTEN" ]; then + problem "Nichts lauscht auf Port $PORT. Laeuft der Stack? (./setup.sh ps)" +else + ok "$(echo "$LISTEN" | awk '{print $4}' | sort -u | tr '\n' ' ')" + echo "$LISTEN" | grep -q 'users:' && echo " Prozess: $(echo "$LISTEN" | grep -o 'users:(([^)]*' | head -1 | cut -c9-)" + if echo "$LISTEN" | awk '{print $4}' | grep -qvE '^(127\.|\[::1\])'; then :; else + problem "Port lauscht nur auf localhost - in docker-compose.yml/.env den Port ohne 127.0.0.1 veroeffentlichen" + fi +fi + +# --------------------------------------------------------------------------- +head_ "2. Container und Portweiterleitung" +ENGINE=""; CPORT="" +for e in podman docker; do + have "$e" || continue + "$e" --version 2>/dev/null | grep -qi podman && [ "$e" = docker ] && continue # podman-docker-Wrapper + line=$("$e" ps --format '{{.Names}} {{.Ports}}' 2>/dev/null | grep -E ":$PORT->[0-9]+/tcp" | head -1) + if [ -n "$line" ]; then + ENGINE=$e + CPORT=$(echo "$line" | grep -oE ":$PORT->[0-9]+" | head -1 | cut -d'>' -f2) + ok "$e-Container ${line%% *} veroeffentlicht $PORT -> $CPORT" + break + fi +done +[ -z "$ENGINE" ] && note "Kein Docker/Podman-Container mit Port $PORT gefunden (anderer Dienst oder fehlende Rechte)" + +dnat_present() { + { iptables-save -t nat 2>/dev/null; ip6tables-save -t nat 2>/dev/null; nft list ruleset 2>/dev/null; } | + grep -E -- "(--dport|dport) $PORT\b" | grep -qi 'dnat' +} +if [ -n "$ENGINE" ] && is_root; then + if dnat_present; then + ok "Portweiterleitung (DNAT) fuer $PORT ist vorhanden" + elif [ "$ENGINE" = podman ] && podman info --format '{{.Host.NetworkBackend}}' 2>/dev/null | grep -q netavark; then + problem "Podman/netavark-Portweiterleitung fehlt - typisch nach 'firewall-cmd --reload' oder Firewall-Neustart" + add_fix "Podman-Netzregeln neu laden (podman network reload --all)" "podman network reload --all" + elif [ "$ENGINE" = docker ]; then + problem "Docker-Portweiterleitung fehlt - typisch nach Firewall-Neustart/-Reload ohne Docker-Neustart" + note "Behebung: systemctl restart docker (startet ALLE Container neu, daher nicht automatisch)" + fi +fi + +# --------------------------------------------------------------------------- +head_ "3. IP-Forwarding (fuer Container-Ports noetig)" +if [ "$(cat /proc/sys/net/ipv4/ip_forward 2>/dev/null)" = 1 ]; then + ok "net.ipv4.ip_forward = 1" +elif [ -n "$ENGINE" ]; then + problem "net.ipv4.ip_forward = 0 - weitergeleitete Pakete zum Container werden verworfen" + add_fix "IP-Forwarding einschalten (dauerhaft in /etc/sysctl.d/99-wazuh-forward.conf)" \ + "echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-wazuh-forward.conf && sysctl -q -w net.ipv4.ip_forward=1" +else + note "net.ipv4.ip_forward = 0 (nur fuer Container-Ports relevant)" +fi + +# --------------------------------------------------------------------------- +head_ "4. Firewalls" +FOUND_FW=0 + +# --- firewalld (RHEL, Fedora, CentOS, SUSE) --- +if have firewall-cmd && firewall-cmd --state >/dev/null 2>&1; then + FOUND_FW=1 + IFACE=$(ip route show default 2>/dev/null | awk '{for(i=1;i/dev/null || firewall-cmd --get-default-zone) + allowed=no + firewall-cmd --zone="$ZONE" --query-port="$PORT/tcp" >/dev/null 2>&1 && allowed=port + if [ "$allowed" = no ]; then + for svc in $(firewall-cmd --zone="$ZONE" --list-services 2>/dev/null); do + firewall-cmd --info-service="$svc" 2>/dev/null | grep -E '^\s+ports:' | grep -qw "$PORT/tcp" && { allowed="Dienst $svc"; break; } + done + fi + target=$(firewall-cmd --permanent --zone="$ZONE" --get-target 2>/dev/null) + [ "$allowed" = no ] && [ "$target" = ACCEPT ] && allowed="Zone-Target ACCEPT" + if [ "$allowed" = no ] && [ -n "$ENGINE" ] && is_root && + nft list chain inet firewalld filter_FORWARD 2>/dev/null | grep -q 'ct status dnat accept'; then + allowed="Container-Port: firewalld laesst per DNAT weitergeleitete Verbindungen durch" + fi + if [ "$allowed" != no ]; then + ok "firewalld aktiv, Zone '$ZONE' (Interface ${IFACE:-?}): $PORT/tcp erlaubt ($allowed)" + else + problem "firewalld aktiv, Zone '$ZONE' (Interface ${IFACE:-?}) erlaubt $PORT/tcp nicht" + # Runtime + permanent ohne --reload: ein Reload wuerde die Podman/Docker-Regeln loeschen + add_fix "firewalld: $PORT/tcp in Zone '$ZONE' freigeben (sofort + dauerhaft, ohne Reload)" \ + "firewall-cmd -q --zone='$ZONE' --add-port=$PORT/tcp && firewall-cmd -q --permanent --zone='$ZONE' --add-port=$PORT/tcp" + fi +elif have firewall-cmd; then + note "firewalld installiert, aber nicht aktiv" +fi + +# --- ufw (Ubuntu, Debian) --- +if have ufw && is_root && ufw status 2>/dev/null | grep -q '^Status: active'; then + FOUND_FW=1 + if ufw status verbose | grep -q 'Default:.*allow (incoming)'; then + ok "ufw aktiv, eingehend standardmaessig erlaubt" + elif ufw status | grep -qE "^$PORT(/tcp)?[[:space:]]+(ALLOW|LIMIT)"; then + ok "ufw aktiv, Regel fuer $PORT/tcp vorhanden" + else + problem "ufw aktiv und keine ALLOW-Regel fuer $PORT/tcp" + add_fix "ufw: $PORT/tcp erlauben" "ufw allow $PORT/tcp comment 'Wazuh Dashboard'" + fi + # ufw-docker: filtert Container-Verkehr ueber DOCKER-USER -> braucht "ufw route allow" + if [ -n "$CPORT" ] && iptables -S DOCKER-USER 2>/dev/null | grep -q 'ufw-user-forward'; then + if ufw status | grep -qE "^$CPORT/tcp.*ALLOW FWD"; then + ok "ufw-docker: Weiterleitung auf Container-Port $CPORT erlaubt" + else + problem "ufw-docker aktiv, Weiterleitung auf Container-Port $CPORT nicht erlaubt" + add_fix "ufw-docker: Weiterleitung auf Container-Port $CPORT erlauben" \ + "ufw route allow proto tcp from any to any port $CPORT" + fi + fi +elif have ufw && ! is_root; then + note "ufw installiert - Status nur als root lesbar" +fi + +# --- CSF (ConfigServer Firewall, cPanel/Plesk-Server) --- +if [ -f /etc/csf/csf.conf ]; then + FOUND_FW=1 + if grep -E '^TCP_IN\s*=' /etc/csf/csf.conf | grep -qE "[\",]$PORT[\",]"; then + ok "CSF: $PORT in TCP_IN" + else + problem "CSF installiert, $PORT fehlt in TCP_IN (/etc/csf/csf.conf)" + note "CSF selbst eintragen und 'csf -r' ausfuehren; danach Container-Regeln neu laden (Docker/Podman neu starten bzw. podman network reload --all)" + fi +fi + +# --- Shorewall --- +if have shorewall && shorewall status >/dev/null 2>&1; then + FOUND_FW=1 + note "Shorewall aktiv: Regel in /etc/shorewall/rules anlegen, z.B. 'ACCEPT net \$FW tcp $PORT', dann 'shorewall reload'" +fi + +# --- iptables (nur wenn kein Frontend die Regeln verwaltet) --- +if is_root && have iptables && [ "$FOUND_FW" = 0 ]; then + INPUT=$(iptables -S INPUT 2>/dev/null) + input_accepts() { + echo "$INPUT" | grep -E -- '-j ACCEPT' | grep -E -- "--dport $PORT\b|--dports [0-9,:]*\b$PORT\b" | grep -qv -- '-s ' + } + if echo "$INPUT" | grep -qE '^-P INPUT (DROP|REJECT)' || echo "$INPUT" | grep -qE '^-A INPUT -j (DROP|REJECT)'; then + FOUND_FW=1 + if input_accepts; then + ok "iptables INPUT: restriktiv, aber $PORT/tcp erlaubt" + else + problem "iptables INPUT verwirft standardmaessig und hat keine ACCEPT-Regel fuer $PORT/tcp" + add_fix "iptables: ACCEPT-Regel fuer $PORT/tcp in INPUT einfuegen" \ + "iptables -I INPUT -p tcp --dport $PORT -m conntrack --ctstate NEW -j ACCEPT" + fi + else + ok "iptables INPUT: kein generelles DROP/REJECT" + fi + # Eigene Sperren in DOCKER-USER (gelten fuer alle Container-Ports) + if [ "$ENGINE" = docker ] && iptables -S DOCKER-USER 2>/dev/null | grep -qE -- '-j (DROP|REJECT)'; then + FOUND_FW=1 + if iptables -S DOCKER-USER | grep -E -- '-j (ACCEPT|RETURN)' | grep -q -- "--ctorigdstport $PORT"; then + ok "DOCKER-USER: Sperrregeln vorhanden, $PORT ausgenommen" + else + problem "DOCKER-USER enthaelt DROP/REJECT-Regeln ohne Ausnahme fuer $PORT" + add_fix "DOCKER-USER: Ausnahme fuer Host-Port $PORT einfuegen" \ + "iptables -I DOCKER-USER -p tcp -m conntrack --ctorigdstport $PORT --ctdir ORIGINAL -j ACCEPT" + fi + fi +fi + +# --- natives nftables (eigene Tabellen, nicht firewalld/docker/netavark/iptables-nft) --- +if is_root && have nft && have python3; then + NFT_CHAINS=$(nft -j list ruleset 2>/dev/null | python3 -c ' +import json, sys +port = sys.argv[1] +own = {"firewalld", "netavark"} +iptables_compat = {"nat", "filter", "mangle", "raw", "security"} # von iptables-nft angelegt +try: + data = json.load(sys.stdin)["nftables"] +except Exception: + sys.exit(0) +chains, rules = {}, {} +for item in data: + if "chain" in item: + c = item["chain"] + if c.get("hook") != "input" or c.get("type") != "filter" or c["table"] in own: + continue + if c["family"] in ("ip", "ip6") and c["table"] in iptables_compat: + continue + if True: + chains[(c["family"], c["table"], c["name"])] = c.get("policy", "accept") + elif "rule" in item: + r = item["rule"] + rules.setdefault((r["family"], r["table"], r["chain"]), []).append(json.dumps(r["expr"])) +for key, policy in chains.items(): + body = rules.get(key, []) + has_drop = policy == "drop" or any(("\"drop\"" in e or "\"reject\"" in e) and "\"match\"" not in e for e in body) + allows = any("\"accept\"" in e and "\"dport\"" in e and (f": {port}}}" in e or f", {port}," in e or f"[{port}," in e or f", {port}]" in e) for e in body) + print(" ".join(key), "drop" if has_drop else "accept", "allow" if allows else "noallow") +' "$PORT") + while read -r fam tbl chain pol allow; do + [ -n "$fam" ] || continue + FOUND_FW=1 + if [ "$pol" = accept ]; then + ok "nftables $fam $tbl/$chain: verwirft nicht generell" + elif [ "$allow" = allow ]; then + ok "nftables $fam $tbl/$chain: $PORT/tcp erlaubt" + else + problem "nftables $fam $tbl/$chain verwirft eingehend und erlaubt $PORT/tcp nicht" + add_fix "nftables: '$PORT/tcp accept' am Anfang von $fam $tbl/$chain einfuegen" \ + "nft insert rule $fam $tbl $chain tcp dport $PORT accept" + NFT_PERSIST=1 + fi + done <<< "$NFT_CHAINS" +fi + +if [ "$FOUND_FW" = 0 ]; then + if is_root; then ok "Keine aktive Host-Firewall gefunden, die eingehend blockiert" + else note "Ohne root nicht vollstaendig pruefbar (iptables/nftables/ufw)"; fi +fi + +# --------------------------------------------------------------------------- +head_ "5. Lokaler Verbindungstest" +probe() { # probe HOST -> "HTTP " | "TCP offen" | leer + local code="" + have curl && code=$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' "https://$1:$PORT/" 2>/dev/null) + if [ -n "$code" ] && [ "$code" != 000 ]; then echo "HTTP $code"; return; fi + timeout 5 bash -c "exec 3<>/dev/tcp/$1/$PORT" 2>/dev/null && echo "TCP offen, aber keine HTTPS-Antwort" +} +MYIP=$(ip route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i}:$PORT" +note "Ausserdem moegliche Sperren ausserhalb dieses Servers: Cloud-Firewall/Security-Group, Hypervisor-Firewall (z.B. Proxmox), Netzwerk-Firewall/VLAN" + +# --------------------------------------------------------------------------- +head_ "Ergebnis" +if [ "${#FIX_CMD[@]}" -eq 0 ]; then + if [ "$PROBLEMS" -eq 0 ]; then ok "Keine Probleme auf diesem Server gefunden" + else note "$PROBLEMS Problem(e) gefunden, aber keine automatische Behebung moeglich (siehe oben)"; fi + exit $(( PROBLEMS > 0 )) +fi + +echo "Vorgeschlagene Aenderungen:" +for i in "${!FIX_CMD[@]}"; do + echo " $((i + 1)). ${FIX_DESC[$i]}" + echo " # ${FIX_CMD[$i]}" +done + +if [ "$MODE" = check ]; then + echo "Nur Pruefung (--check). Anwenden mit: sudo $0 --yes" + exit 1 +fi +is_root || { bad "Aenderungen brauchen root: sudo $0"; exit 1; } +if [ "$MODE" = ask ]; then + read -r -p "Aenderungen jetzt anwenden? [j/N] " answer + [[ $answer =~ ^[jJyY] ]] || { echo "Abgebrochen."; exit 1; } +fi + +rc=0 +for i in "${!FIX_CMD[@]}"; do + if bash -c "${FIX_CMD[$i]}"; then ok "${FIX_DESC[$i]}" + else bad "fehlgeschlagen: ${FIX_DESC[$i]}"; rc=1; fi +done +# iptables-Regeln dauerhaft speichern, sofern ein Speichermechanismus installiert ist +if printf '%s\n' "${FIX_CMD[@]}" | grep -q '^iptables '; then + if have netfilter-persistent; then netfilter-persistent save >/dev/null 2>&1 && ok "iptables-Regeln gespeichert (netfilter-persistent)" + elif [ -f /etc/sysconfig/iptables ] && have iptables-save; then iptables-save > /etc/sysconfig/iptables && ok "iptables-Regeln gespeichert (/etc/sysconfig/iptables)" + else note "iptables-Regel gilt bis zum Neustart. Dauerhaft z.B. mit iptables-persistent/iptables-services."; fi +fi +[ "${NFT_PERSIST:-0}" = 1 ] && note "nftables-Regel gilt bis zum Neustart. Dauerhaft: in /etc/nftables.conf (bzw. /etc/sysconfig/nftables.conf) eintragen." + +echo +echo "Erneute Pruefung:" +recheck=(--check --port "$PORT"); [ "$TCP_ONLY" = 1 ] && recheck+=(--tcp) +"$0" "${recheck[@]}" | grep -E 'PROBLEM|Keine Probleme|Problem\(e\)' || true +exit $rc diff --git a/setup.sh b/setup.sh index 63879d0..22f1267 100755 --- a/setup.sh +++ b/setup.sh @@ -4,7 +4,7 @@ # Compose-Werkzeug (docker compose, docker-compose, podman-compose, podman compose). # # ./setup.sh Erstinstallation (Passwoerter, Zertifikate, SSH-Key, Images) -# ./setup.sh up Stack starten (+ Kernel-Parameter, Firewall, Autostart als root) +# ./setup.sh up Stack starten (+ Kernel-Parameter, Firewall-Check, Autostart als root) # ./setup.sh down Stack stoppen # ./setup.sh ps | logs [dienst] # ./setup.sh host-script Skript zum Vorbereiten eines Zielhosts ausgeben @@ -16,6 +16,8 @@ # ./setup.sh apply hosts.yml uebernehmen (Manager + Collector neu starten) # ./setup.sh passwords Zugangsdaten anzeigen # ./setup.sh info Erkannte Umgebung anzeigen +# ./setup.sh firewall Erreichbarkeit des Dashboard-Ports pruefen, fehlende Regeln anlegen +# (--check nur pruefen, --yes ohne Rueckfrage, --port N) # # Mit Podman bitte als root ausfuehren (sudo ./setup.sh ...), siehe check_rootless. # Erkennung uebersteuern: CONTAINER_ENGINE=docker|podman ./setup.sh ... @@ -155,17 +157,12 @@ tune_kernel() { fi } -open_firewall() { - local port - port=$(env_get DASHBOARD_PORT) - command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1 || return 0 - if firewall-cmd --query-port="$port/tcp" >/dev/null 2>&1; then return 0; fi - if is_root; then - info "firewalld: oeffne Port $port/tcp fuer das Dashboard" - firewall-cmd -q --permanent --add-port="$port/tcp" && firewall-cmd -q --reload - else - warn "firewalld aktiv, Port $port/tcp nicht freigegeben: sudo firewall-cmd --permanent --add-port=$port/tcp && sudo firewall-cmd --reload" - fi +check_firewall() { + # Nach dem Start: Erreichbarkeit des Dashboard-Ports pruefen (firewalld, ufw, iptables, + # nftables, Container-Portweiterleitung) und als root fehlende Regeln anlegen. + # Wichtig: niemals "firewall-cmd --reload" - das loescht die Portregeln von Podman/Docker. + if is_root; then ./firewall-check.sh --yes || warn "Firewall-Check meldet Probleme (siehe oben)" + else ./firewall-check.sh --check || warn "Firewall-Check: fuer automatische Regeln 'sudo ./setup.sh firewall'"; fi } enable_autostart() { @@ -337,7 +334,8 @@ cmd_up() { tune_kernel compose up -d enable_autostart - open_firewall + sleep 5 # Portweiterleitung der Container steht erst nach dem Start + check_firewall info "Gestartet ($ENGINE). Dashboard in 1-3 Minuten: https://$(uname -n):$(env_get DASHBOARD_PORT)" } @@ -349,6 +347,7 @@ case "$CMD" in ps) detect_runtime; compose ps ;; logs) shift; detect_runtime; compose logs -f --tail=100 "$@" ;; info) cmd_info ;; + firewall) shift; ./firewall-check.sh "$@" ;; host-script) shift; cmd_host_script "$@" ;; keyscan) detect_runtime; compose run --rm --no-deps sshpull.collector keyscan ;; test) detect_runtime; compose run --rm --no-deps sshpull.collector test ;; @@ -357,5 +356,5 @@ case "$CMD" in echo "Dashboard: admin / $(env_get INDEXER_PASSWORD)" echo "Wazuh-API: wazuh-wui / $(env_get API_PASSWORD)" ;; - *) sed -n '2,23p' "$0"; exit 2 ;; + *) sed -n '2,25p' "$0"; exit 2 ;; esac