Files
mesh-configs/skills/devops/security-audit-hardening/SKILL.md
T

6.0 KiB
Raw Blame History

name, description, version, author, platforms
name description version author platforms
security-audit-hardening Linux-Server-Sicherheitsaudit mit automatischer Härtung – SSH, fail2ban, UFW, Angriffserkennung 1.0.0 Agent A (netcup VPS Deployer)
linux

Security Audit & Hardening

Schnelles Sicherheitsaudit für Linux-VPS mit Sofortmaßnahmen gegen Bruteforce-Angriffe.

Audit-Befehl (alles auf einmal)

echo "=== OFFENE PORTS ===" && ss -tlnp | awk '{print $4,$NF}' | sort -u
echo "=== UFW ===" && ufw status verbose
echo "=== SSH ===" && grep -E "^PermitRootLogin|^PasswordAuthentication|^PubkeyAuthentication|^Port" /etc/ssh/sshd_config
echo "=== FAIL2BAN ===" && systemctl status fail2ban 2>/dev/null | head -3
echo "=== SSH-ANGRIFFE ===" && grep -c "Failed password" /var/log/auth.log 2>/dev/null
echo "=== AKTIVE ANGREIFER ===" && grep "Failed password" /var/log/auth.log 2>/dev/null | tail -5 | awk '{print $NF}' | sort -u

Sofortmaßnahmen (in dieser Reihenfolge)

1. Aktuelle Angreifer blockieren

# IPs aus Auth-Log extrahieren
ufw deny from <IP>

2. fail2ban installieren

apt-get install -y fail2ban
systemctl enable fail2ban
systemctl start fail2ban

3. fail2ban aggressiv konfigurieren

cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 7200
EOF
systemctl restart fail2ban

4. SSH härten

cat >> /etc/ssh/sshd_config << 'EOF'
MaxAuthTries 3
MaxSessions 2
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
EOF
sshd -t && systemctl reload sshd

⚠️ Pitfall: Nicht aussperren! Vor PasswordAuthentication no prüfen ob SSH-Keys existieren: cat /root/.ssh/authorized_keys. Wenn keine Keys → Passwort-Auth lassen, aber mit fail2ban + MaxAuthTries absichern.

🔥 Pitfall: fail2ban bannt eigene Mesh-/Agent-IPs! SSH/scp-Polling von Sub-Agenten aus (regelmäßige Key-Auth-Verbindungen zum Master) wird von fail2ban als „fehlgeschlagene Login-Versuche" gezählt und gebannt — besonders wenn eine once mal nicht matchen will. Symptom: „Connection refused" auf Port 22 NUR für genau eine IP, während Ping geht und andere Agenten noch funktionieren. Fix — eigene/vertraute IPs dauerhaft whitelisten in /etc/fail2ban/jail.local:

[sshd]
ignoreip = 172.24.34.142 172.24.20.26 172.24.178.202 172.24.92.162

Dann fail2ban-client reload + fail2ban-client set sshd unbanip <IP>. WICHTIG: nur EINE [sshd]-Sektion pflegen (eine doppelte, appendierte Sektion gilt separat — konsolidieren).

5. Webhook-/Mesh-Schnittstellen auf bekannte ZeroTier-Geräte isolieren

Prinzip (NUTZERWUNSCH 2026-08-03): Kein Subnetz-/16-Catch-all. Mesh-Ports nur für explizit bekannte ZeroTier-IPs freigeben, damit ein unbekanntes Gerät im Netz keine Dienste einschleusen kann. Inkl. Handy (Gerät, kein Agent).

# Bekannte ZT-Geräte einzeln freigeben (Ports: Webhook 8644, NFS 2049/111/20048, Ollama 11434)
for ip in 172.24.34.142 172.24.20.26 172.24.178.202 172.24.92.162; do
  ufw allow from $ip to any port 8644  proto tcp comment 'Webhook Mesh'
  ufw allow from $ip to any port 2049  proto tcp comment 'NFS Mesh'
  ufw allow from $ip to any port 111   proto tcp comment 'rpcbind'
  ufw allow from $ip to any port 111   proto udp comment 'rpcbind U'
  ufw allow from $ip to any port 20048 proto tcp comment 'nfs lockd'
  ufw allow from $ip to any port 11434 proto tcp comment 'Ollama Mesh'
done

Zuerst alte /16-Regeln löschen: ufw delete <nr> fragt interaktiv → mit yes | erzwingen. Verifikation: ufw status | grep '172.24.0.0/16' darf NICHTS zeigen; grep -oP '172\\.24\\.\\d+\\.\\d+' | sort -u darf nur die bekannten IPs listen.

🔒 NFS deaktivieren — SSH/scp für Agent-Tasks ist sicherer (2026-08-03). NFS (sec=sys) transferiert plaintext über TCP → Man-in-the-Middle-anfällig, und braucht Kernelmodule/FUSE, die auf Tegra-Hosts (Nintendo-Switch: Kernel 4.9.140-l4t → kein nfs/ kein fuse) fehlen. Entscheidung: alle Sub-Agenten nutzen SSH/scp mit Key-Auth (Ende-zu-Ende verschlüsselt), NFS-Server deaktiviert und NFS-Ports (2049/111/20048) aus UFW entfernt. Das schließt die NFS-Angriffsfläche komplett. Details zum SSH/scp-Polling: siehe Skill multi-agent-mesh (Kontext: Task-Polling über SSH/scp).

⚠️ Pitfall: Nach VPN/Netz-Wechsel (WireGuard→ZeroTier) hängen UFW-Regeln oft noch an alten Subnetzen (z.B. 10.8.0.0/24). Immer prüfen, welches Netzwerk jetzt real aktiv ist.

6. Automatische Sicherheitsupdates

apt-get install -y unattended-upgrades
dpkg-reconfigure -f noninteractive unattended-upgrades

Audit-Ergebnis bewerten

Signal Risiko
SSH PasswordAuthentication yes 🔴 Bruteforce möglich
SSH PermitRootLogin yes 🔴 Root direkt angreifbar
Kein fail2ban 🔴 Keine Ratenbegrenzung
Webhook-Port öffentlich 🟡 API für jeden erreichbar
>100 Failed Passwords 🔴 Aktiver Angriff
UFW default deny 🟢 korrekt

Verhalten bei aktivem Angriff

  1. Nicht in Panik verfallen — SSH mit Passwort + fail2ban hält 99% der Angriffe ab
  2. Angreifer-IPs per ufw deny dauerhaft sperren
  3. fail2ban-Status prüfen: fail2ban-client status sshd
  4. Auth-Log monitoren: tail -f /var/log/auth.log | grep Failed

JIT SSH-Portal (nächste Stufe: SSH schließen, 2FA-Freischaltung)

Wenn der Server-SSH nicht dauerhaft offen sein soll: baue ein Just-In-Time-Portal — Flask + Telegram-2FA + temporäre UFW-Freischaltung (1h Auto-Close). Details + Reset-Rezept: references/jit-ssh-2fa-portal.md.

Kern-Pitfall: Ein End-to-End-Test des Portals überschreibt das echte Passwort (PW-Wechsel-Pflicht) — nach dem Test IMMER zurücksetzen, nie Test-Artefakte im laufenden System hinterlassen.

Niemals tun

  • ❌ SSH-Port ändern (security by obscurity, bringt nichts)
  • ❌ PermitRootLogin no ohne funktionierenden SSH-Key
  • ❌ PasswordAuthentication no ohne SSH-Key für ALLE User
  • ❌ UFW deaktivieren "weil's nicht funktioniert"