Port-Scanner — verstehen & abwehren (defensiv, legal)

Dieses Dokument erklärt, wie Scanner/Bots grundsätzlich arbeiten und wie du dich verantwortungsvoll und praktisch dagegen schützt. Es enthält Erklärungen, Pseudocode (nur zum Lernen, nicht ausführbar als Angriff) und ein defensives Python‑Skript, das Webserver‑Logs analysiert — kein Angriffscode.

Führe niemals Scans gegen fremde Systeme ohne ausdrückliche Erlaubnis aus. Scans können als Angriff gewertet werden und rechtliche Konsequenzen haben.


Einleitung (Kurz)

Scanner-Bots (Portscanner, Exploit-Scanner, Credential-Stuffing-Bots) durchsuchen das Internet automatisiert nach offenen Diensten und bekannten Schwachstellen. Du kannst nur wirksam schützen, wenn du verstehst, wie diese Bots arbeiten — darum ist dieses Howto gedacht: Lernen\u2014Erkennen\u2014Abwehren.


1) Wie ein typischer Port-Scanner / Bot arbeitet (konzeptionell)

  1. Zielerfassung – IP-Range, Listen aus DynDNS, Zufalls-IP, oder von früheren Scans.
  2. Portliste – Standardports (21,22,23,25,80,443,3306,3389) oder ganze Bereiche.
  3. Verbindungsversuch – TCP-SYN/Connect oder UDP-Probe; Ergebnis: open/closed/filtered.
  4. Banner-Fingerprinting – lieferbare Banners (HTTP, SSH) werden gelesen, Versionen abgeglichen.
  5. Korrelation / C&C – Ergebnisse werden gesammelt und an Command&Control gesendet oder lokal ausgewertet.
  6. (Optional) Exploitation – bei Fund einer verwundbaren Version wird ein Exploit nachgeladen.

Pseudocode (nur zur Veranschaulichung)

for each ip in target_list:
    for each port in port_list:
        result = attempt_tcp_connect(ip, port, timeout=1s)
        if result == CONNECTED:
            banner = read_banner_if_any()
            record_open_port(ip, port, banner)
        else:
            record_closed_or_filtered(ip, port)
send_results_to_controller()


2) Was das für dich bedeutet (Risiken)

  • Schnelle Entdeckung: Scanner finden neue öffentliche Hosts in Minuten.
  • Brute‑Force & Credential‑Stuffing: Zugangsdaten werden massiv ausprobiert.
  • Exploit‑Scanner: Suchen nach bekannten Plugin-/CMS‑Lücken.
  • Offene Dienste (SMB/MySQL/etc.): Führen oft schnell zur Kompromittierung.
  • Missbrauch deines Hosts: Spam, Proxy, Botnet‑Teilnahme.

3) Defensive Praxis — wie du absicherst (Schritt für Schritt)

A. Überlege zuerst: Muss das wirklich öffentlich sein?

  • Wenn möglich: nur interne Nutzung, VPN oder SSH‑Tunnel.

B. Minimale Angriffsfläche

  • Nur benötigte Ports forwarden (meist: 443, evtl. SSH auf non‑standard Port).
  • Keine Admin-/DB‑Tools (phpMyAdmin, Webmin, File‑Manager) offen.

C. Firewall & Rate‑Limiting

  • Beispiel UFW (Ubuntu/Debian):
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 443/tcp
# SSH nur bei Bedarf und nur aus bestimmten IPs
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp comment 'SSH from office'
sudo ufw enable
  • Router‑NAT: Port‑Forward nur auf exakte Host‑IP (keine DMZ), nur einzelne Ports.

D. Fail2Ban / Log‑Basierte Blocks

  • Installiere fail2ban, schreibe Filter für SSH, Apache‑auth und häufige 404‑Patterns.

E. WordPress‑Härte (oder jede Web‑App)

  • Starke Passwörter + 2FA.
  • Regelmäßige Updates (Core, Plugins, Themes).
  • Keine File‑Manager Plugins, keine unbekannten Plugins/Themes.
  • Admin‑Bereiche nur per IP‑Whitelist oder über VPN erreichbar.

F. HTTPS / Zertifikate

  • Nutze Let’s Encrypt oder valide Zertifikate.
  • Entferne oder ersetze abgelaufene/unsichere Zertifikate.

G. Monitoring & Alerts

  • Überwache auth.log, access.log, error.log.
  • Setze Alerts bei ungewöhnlich vielen Anfragen oder hoher Fehlerrate.

H. Backups & Notfallplan

  • Regelmäßige Offline‑Backups der Website + DB.
  • Plan: Router‑Portforwarding abschalten, SSH‑Keys rotieren, Site offline nehmen.

4) Praktisches, defensives Beispiel: Log‑Analyzer (Python)

  • Zweck: Arbeitet nur lokal. Liest Webserver‑Access‑Log und markiert auffällige IPs (viele Requests in kurzer Zeit, hohe Fehlerquote).
  • Führe es nur gegen eigene Logs aus.

#!/usr/bin/env python3
"""
detect_scans.py
Defensiver Log-Analyzer:
- liest Apache/Nginx access.log
- zählt pro IP Requests in einem Zeitfenster
- meldet IPs die Schwellenwerte überschreiten

Usage:
  python3 detect_scans.py /path/to/access.log
"""
import sys
import re
from collections import defaultdict, deque
from datetime import datetime, timedelta

# Konfiguration
TIME_WINDOW_SECONDS = 60
REQUEST_THRESHOLD = 100
ERROR_RATIO_THRESHOLD = 0.5   # wenn >50% 4xx/5xx dann auffällig

logline_regex = re.compile(r'(?P<ip>\d+\.\d+\.\d+\.\d+) - - \[(?P<time>[^]]+)\] "(?P<method>\S+) (?P<path>\S+) .*" (?P<status>\d{3})')

def parse_time(timestr):
    # Beispiel: 24/Sep/2025:13:18:11 +0000
    return datetime.strptime(timestr.split()[0], "%d/%b/%Y:%H:%M:%S")

def analyze(logpath):
    ip_window = defaultdict(lambda: deque())
    ip_counts = defaultdict(int)
    ip_errors = defaultdict(int)

    with open(logpath, 'r', errors='ignore') as f:
        for line in f:
            m = logline_regex.search(line)
            if not m:
                continue
            ip = m.group('ip')
            t = parse_time(m.group('time'))
            status = int(m.group('status'))

            q = ip_window[ip]
            q.append(t)
            cutoff = t - timedelta(seconds=TIME_WINDOW_SECONDS)
            while q and q[0] < cutoff:
                q.popleft()
            count = len(q)
            ip_counts[ip] = max(ip_counts[ip], count)
            if status >= 400:
                ip_errors[ip] += 1

    suspicious = []
    for ip, max_count in ip_counts.items():
        errors = ip_errors.get(ip, 0)
        error_ratio = errors / max_count if max_count else 0
        if max_count >= REQUEST_THRESHOLD or error_ratio >= ERROR_RATIO_THRESHOLD:
            suspicious.append((ip, max_count, errors, error_ratio))

    suspicious.sort(key=lambda x: (-x[1], -x[2]))
    if not suspicious:
        print("Keine auffälligen IPs gefunden.")
    else:
        print("Auffällige IPs (ip, max_requests_in_window, error_count, error_ratio):")
        for ip, cnt, errs, ratio in suspicious:
            print(f"{ip}\t{cnt}\t{errs}\t{ratio:.2f}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: detect_scans.py /path/to/access.log")
        sys.exit(1)
    analyze(sys.argv[1])


5) Verantwortliches Testen — wie du lernen kannst (legal)

  • Richte dir ein isoliertes Lab ein (VMs, Docker, internes Testnetz). Scanne nur dort.
  • Nutze nmap lokal gegen deine VMs, nicht gegen fremde Hosts.
  • Lerne Logs zu lesen, Test‑Exploits nur gegen deine Testinstanzen.

6) Quick‑Checkliste für DynDNS + Portforwarding

Vor Freischaltung:

  • DNS & Erreichbarkeit

– Prüfe, ob DynDNS (no-ip) wirklich nötig ist — reicht VPN/SSH-Tunnel?
– Reserviere eine dedizierte Subdomain nur für diesen Host (nicht mehrere Dienste auf einer Adresse).

  • Netzwerk & Router

– Deaktiviere UPnP auf Router; richte Port‑Forwarding manuell ein.
– Leite nur exakt benötigte Ports weiter (z. B. nur 443). Keine DB-/SMB-Ports.
– Setze Port‑Forwarding auf die feste lokale IP des Servers (DHCP-Reservierung).

  • Zugang & Authentifizierung

– Erzeuge starke SSH‑Keys; deaktiviere Passwort‑Login.
– Verwende ein anderes als Standard‑SSH‑Port (Security by obscurity nur ergänzend).
– Erstelle separate Benutzerkonten mit minimalen Rechten für Webserver-Dateien.

  • System & Dienste

– Deaktiviere oder entferne unnötige Services (phpMyAdmin, Mailhog, SMB, etc.).
– Stelle sicher, dass MAMP/Apache/PHP aktuell sind.
– Entferne unsichere Plugins (insbesondere File‑Manager) aus WordPress.

  • Firewall & Monitoring

– Konfiguriere Host‑Firewall (ufw/ipfw) mit Default-Deny und expliziten Allow-Regeln.
– Richte Fail2Ban für SSH/HTTP ein.
– Lege Logging‑Standorte fest (access.log, error.log, auth.log) und prüfe Berechtigungen.

  • Backup & Notfallplan

– Erstelle Offline-Backups von Webroot und DB; verifiziere Wiederherstellung.
– Lege Notfall-Schritte fest (Router‑Portforwarding deaktivieren, SSH‑Key rotieren, Site vom Netz nehmen).

Nach Freischaltung:

  • Kurzfristig (erste 24–72 Stunden)

– Überwache Logs (Zugriffe, 4xx/5xx, Auth‑Fails) in Echtzeit.
– Prüfe auf verdächtige Anmeldungen; blocke IPs mit Fail2Ban manuell falls nötig.
– Führe einen schnellen Portscan von außen (nur auf deine IP) durch, um offene Ports zu verifizieren.

  • Wöchentlich (laufende Betreuung)

– Prüfe WordPress‑Core/Plugins/Themes auf Updates; entferne inaktive Plugins.
– Überprüfe Cronjobs, LaunchAgents/Daemons und crontabs auf unbekannte Einträge.
– Kontrolliere Backup‑Integrität und Logs auf wiederkehrende Auffälligkeiten.

  • Wenn etwas Auffälliges entdeckt wird

– Sofort: Router‑Portforwarding ausschalten und Backup‑Snapshot anfertigen.
– SSH‑Keys und Passwörter rotieren; Admin‑Accounts prüfen und ggf. deaktivieren.
– Führe forensische Sicherung durch (logs, webroot, cron, /etc, user‑homes) und untersuche Zeitstempel.
– Erstelle einen Post‑Mortem‑Report und überlege Migration auf gehärteten VPS falls wiederholte Angriffe auftreten.

7) Schlusswort

Verstehen wie Scanner arbeiten ist zentral — aber bitte immer verantwortungsvoll. Dieses Dokument ist dafür gedacht, dir das nötige Verständnis und praktische Tools zur Erkennung zu geben, damit du (oder deine Kunden) sicherer im Netz unterwegs sind.

— Ende —

Verstehen wie Scanner arbeiten ist zentral — aber bitte immer verantwortungsvoll. Dieses Dokument ist dafür gedacht, dir das nötige Verständnis und praktische Tools zur Erkennung zu geben, damit du (oder deine Kunden) sicherer im Netz unterwegs sind.

— Ende —