Server stealth absicherung
Diese Anleitung beschreibt verschiedene Methoden, um einen Server im Internet zu "verstecken", vor Port-Scans und DDoS-Angriffen zu schützen und SSH maximal abzusichern – während die gewünschten Dienste weiterhin erreichbar bleiben.
Anpassbare Werte in dieser Anleitung:
luna→ Dein Benutzername226→ Dein SSH-Port7000,8000,9000→ Deine Port-Knocking-Sequenz100.64.0.x→ Deine VPN/NetBird-IPs
Teil 1: Grundkonzept – Was bedeutet "unsichtbar"?
Angriffsvektoren verstehen
Bevor wir den Server schützen, müssen wir verstehen, wie Angreifer vorgehen:
| Phase | Angreifer-Aktion | Unser Ziel |
|---|---|---|
| 1. Reconnaissance | Port-Scans (Nmap, Masscan, Shodan) | Keine offenen Ports zeigen |
| 2. Enumeration | Banner-Grabbing, Versionserkennung | Keine Informationen preisgeben |
| 3. Exploitation | Brute-Force, CVE-Exploits | Angriffe blockieren/verlangsamen |
| 4. DDoS | Traffic-Flut, Ressourcenerschöpfung | Traffic filtern, Rate-Limiting |
Stealth-Stufen
Stufe 0: Standard-Server
├── Alle Ports antworten (REJECT)
├── Banner zeigen Versionen
└── SSH auf Port 22 offen
→ Innerhalb von Minuten in Shodan/Censys
Stufe 1: Basis-Härtung
├── Nicht benötigte Ports geschlossen
├── SSH auf nicht-standard Port
└── Fail2ban aktiv
→ Reduziert automatisierte Angriffe
Stufe 2: Stealth-Modus
├── DROP statt REJECT (keine Antwort)
├── Keine ICMP-Antworten
├── Banner entfernt/gefälscht
└── Anti-Scan-Regeln
→ Erscheint für Portscanner als offline
Stufe 3: Maximale Stealth
├── SSH nur via VPN/Knocking
├── Alle Ports unsichtbar
├── Dienste via Reverse Proxy
└── DDoS-Schutz aktiv
→ Praktisch unsichtbar, nur Dienste erreichbar
Teil 2: Firewall-Stealth-Konfiguration
Methode 1: UFW (Einfach)
Für Einsteiger – schnell eingerichtet, aber weniger granular.
# Defaults setzen
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Nur benötigte Ports öffnen
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw allow 443/udp comment 'QUIC'
# SSH eingeschränkt (siehe SSH-Schutz-Kapitel)
sudo ufw allow 226/tcp comment 'SSH'
# Aktivieren
sudo ufw enable
Limitation: UFW verwendet standardmäßig REJECT, nicht DROP. Portscanner sehen den Server als "gefiltert".
UFW auf DROP umstellen
# /etc/ufw/after.rules am Ende hinzufügen:
sudo nano /etc/ufw/after.rules
# Am Ende der Datei hinzufügen (vor COMMIT):
-A ufw-reject-input -j DROP
-A ufw-reject-forward -j DROP
# UFW neu laden
sudo ufw reload
Methode 2: iptables (Fortgeschritten)
Maximale Kontrolle, aber komplexer.
sudo nano /etc/iptables/rules.v4
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# ══════════════════════════════════════════════════════════════
# GRUNDREGELN
# ══════════════════════════════════════════════════════════════
# Loopback erlauben
-A INPUT -i lo -j ACCEPT
# Established Connections
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Ungültige Pakete verwerfen
-A INPUT -m conntrack --ctstate INVALID -j DROP
# ══════════════════════════════════════════════════════════════
# ANTI-SCAN REGELN
# ══════════════════════════════════════════════════════════════
# Fragmentierte Pakete droppen
-A INPUT -f -j DROP
# XMAS-Pakete (Nmap -sX)
-A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# NULL-Pakete (Nmap -sN)
-A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# SYN-FIN (ungültige Kombination)
-A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
# SYN-RST (ungültige Kombination)
-A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# FIN ohne ACK
-A INPUT -p tcp --tcp-flags FIN,ACK FIN -j DROP
# PSH ohne ACK
-A INPUT -p tcp --tcp-flags PSH,ACK PSH -j DROP
# URG ohne ACK
-A INPUT -p tcp --tcp-flags URG,ACK URG -j DROP
# ══════════════════════════════════════════════════════════════
# ICMP (OPTIONAL: Für maximale Stealth auskommentieren)
# ══════════════════════════════════════════════════════════════
# Ping mit Rate-Limit (oder komplett droppen für Stealth)
# -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 2 -j ACCEPT
-A INPUT -p icmp --icmp-type echo-request -j DROP
# ══════════════════════════════════════════════════════════════
# DIENSTE
# ══════════════════════════════════════════════════════════════
# HTTP/HTTPS
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
-A INPUT -p udp --dport 443 -j ACCEPT
# SSH (später einschränken, siehe SSH-Kapitel)
-A INPUT -p tcp --dport 226 -m conntrack --ctstate NEW -m recent --set --name SSH
-A INPUT -p tcp --dport 226 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
-A INPUT -p tcp --dport 226 -j ACCEPT
# NetBird/WireGuard (falls benötigt)
-A INPUT -p udp --dport 51820 -j ACCEPT
# ══════════════════════════════════════════════════════════════
# LOGGING (Optional - für Debugging)
# ══════════════════════════════════════════════════════════════
# Gedropte Pakete loggen (auskommentieren für Produktion)
# -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-dropped: " --log-level 4
# ══════════════════════════════════════════════════════════════
# STANDARD-POLICY: ALLES ANDERE DROPPEN (NICHT REJECTEN!)
# ══════════════════════════════════════════════════════════════
-A INPUT -j DROP
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Schutz vor Port-Scans bereits vor Connection-Tracking
-A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
-A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
-A PREROUTING -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
-A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
-A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-A PREROUTING -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
-A PREROUTING -m conntrack --ctstate INVALID -j DROP
COMMIT
# Regeln anwenden
sudo iptables-restore < /etc/iptables/rules.v4
# Persistent machen
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
Methode 3: nftables (Modern)
Der moderne Nachfolger von iptables, in neueren Distributionen Standard.
sudo nano /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
# Rate-Limit für SSH
set ssh_meter {
type ipv4_addr
flags dynamic
timeout 1m
}
chain input {
type filter hook input priority 0; policy drop;
# Loopback
iif "lo" accept
# Established
ct state established,related accept
ct state invalid drop
# Anti-Scan
tcp flags & (fin|syn|rst|psh|ack|urg) == 0 drop
tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|psh|ack|urg drop
tcp flags & (fin|syn) == fin|syn drop
tcp flags & (syn|rst) == syn|rst drop
# ICMP droppen (Stealth)
ip protocol icmp drop
ip6 nexthdr icmpv6 drop
# HTTP/HTTPS
tcp dport { 80, 443 } accept
udp dport 443 accept
# SSH mit Rate-Limit
tcp dport 226 ct state new add @ssh_meter { ip saddr limit rate 3/minute burst 5 packets } accept
tcp dport 226 ct state new drop
# Alles andere: DROP
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
# Anwenden
sudo nft -f /etc/nftables.conf
# Aktivieren
sudo systemctl enable nftables
sudo systemctl start nftables
Teil 3: SSH-Schutz – Mehrere Methoden
Grundhärtung (Immer anwenden)
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
# Port ändern
Port 226 # ← Anpassen
# Nur bestimmte User
AllowUsers luna # ← Anpassen
# Kein Root-Login
PermitRootLogin no
# Nur Key-Authentifizierung
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
# Brute-Force erschweren
MaxAuthTries 3
LoginGraceTime 20
MaxSessions 3
MaxStartups 3:50:10
# Timeouts
ClientAliveInterval 300
ClientAliveCountMax 2
# Keine unnötigen Features
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PermitTunnel no
PermitUserEnvironment no
# Sichere Algorithmen
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# Banner entfernen (keine Versionsinformationen)
Banner none
DebianBanner no
sudo systemctl restart sshd
Methode 1: Fail2ban (Basis)
Blockiert IPs nach fehlgeschlagenen Login-Versuchen.
sudo apt install fail2ban -y
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 86400
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8 ::1
[sshd]
enabled = true
port = 226 # ← SSH-Port anpassen
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 604800
findtime = 3600
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
# Status prüfen
sudo fail2ban-client status sshd
Methode 2: CrowdSec (Community-basiert)
Wie Fail2ban, aber mit geteilten Blocklisten aus der Community.
# Installation
curl -s https://install.crowdsec.net | sudo sh
# SSH-Kollektion installieren
sudo cscli collections install crowdsecurity/sshd
# Firewall-Bouncer
sudo apt install crowdsec-firewall-bouncer-iptables -y
# Status
sudo cscli metrics
sudo cscli decisions list
Methode 3: Geo-Blocking
SSH nur aus bestimmten Ländern erlauben.
Mit iptables + xtables-addons
# Installation
sudo apt install xtables-addons-common libtext-csv-xs-perl -y
# GeoIP-Datenbank herunterladen
sudo mkdir -p /usr/share/xt_geoip
cd /tmp
/usr/lib/xtables-addons/xt_geoip_dl
/usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip *.csv
# SSH nur aus Deutschland und Österreich erlauben
sudo iptables -I INPUT -p tcp --dport 226 -m geoip ! --src-cc DE,AT -j DROP
Mit CrowdSec
# GeoIP-Bouncer installieren
sudo cscli scenarios install crowdsecurity/ssh-bf-geoip
# Konfiguration
sudo nano /etc/crowdsec/scenarios/ssh-bf-geoip.yaml
Methode 4: Port Knocking
SSH-Port ist komplett geschlossen, öffnet sich nur nach "Klopfsequenz".
sudo apt install knockd -y
sudo nano /etc/knockd.conf
[options]
UseSyslog
Interface = eth0 # ← Netzwerk-Interface anpassen
[openSSH]
sequence = 7000,8000,9000 # ← Geheime Sequenz wählen
seq_timeout = 5
tcpflags = syn
start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 226 -j ACCEPT
cmd_timeout = 30
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 226 -j ACCEPT
[closeSSH]
sequence = 9000,8000,7000 # ← Umgekehrte Sequenz
seq_timeout = 5
tcpflags = syn
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 226 -j ACCEPT
# SSH-Port aus Firewall entfernen (knockd verwaltet das)
sudo iptables -D INPUT -p tcp --dport 226 -j ACCEPT
# knockd aktivieren
sudo nano /etc/default/knockd
# START_KNOCKD=1 setzen
# KNOCKD_OPTS="-i eth0"
sudo systemctl enable knockd
sudo systemctl start knockd
Client-Verbindung
# knock installieren (Client)
sudo apt install knockd -y
# Verbinden
knock SERVER-IP 7000 8000 9000 && ssh luna@SERVER-IP -p 226
# Nach Session schließen (optional)
knock SERVER-IP 9000 8000 7000
Knock-Script für einfache Nutzung
#!/bin/bash
# ~/bin/ssh-knock.sh
SERVER="dein-server.de"
SSH_PORT="226"
KNOCK_SEQ="7000 8000 9000"
USER="luna"
echo "Knocking..."
knock $SERVER $KNOCK_SEQ
sleep 1
echo "Connecting..."
ssh -p $SSH_PORT $USER@$SERVER
Methode 5: SSH nur via VPN (Empfohlen)
SSH ist nur über das VPN-Netzwerk erreichbar – nicht aus dem Internet.
Mit NetBird
# iptables: SSH nur von NetBird-Interface
sudo iptables -A INPUT -i wt0 -p tcp --dport 226 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 226 -j DROP
Oder in der Haupt-Firewall-Konfiguration:
# In /etc/iptables/rules.v4:
# Statt:
-A INPUT -p tcp --dport 226 -j ACCEPT
# Ersetzen durch:
-A INPUT -i wt0 -p tcp --dport 226 -j ACCEPT
# Kein weiterer SSH-Eintrag = SSH aus Internet blockiert
Mit WireGuard
# SSH nur über WireGuard-Subnetz erlauben
sudo iptables -A INPUT -s 10.0.0.0/24 -p tcp --dport 226 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 226 -j DROP
Mit Tailscale
# SSH nur über Tailscale-Interface
sudo iptables -A INPUT -i tailscale0 -p tcp --dport 226 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 226 -j DROP
Methode 6: 2FA (TOTP)
Zusätzlich zum SSH-Key wird ein TOTP-Code benötigt.
sudo apt install libpam-google-authenticator -y
# Als User einrichten
google-authenticator
# Alle Fragen mit 'y' beantworten
# QR-Code mit Authenticator-App scannen
sudo nano /etc/pam.d/sshd
# Am Anfang hinzufügen:
auth required pam_google_authenticator.so
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
# Hinzufügen/Ändern:
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
sudo systemctl restart sshd
Methode 7: SSHGuard (Alternative zu Fail2ban)
Leichtgewichtiger als Fail2ban, unterstützt mehrere Backends.
sudo apt install sshguard -y
# Konfiguration
sudo nano /etc/sshguard/sshguard.conf
# Blockier-Einstellungen
THRESHOLD=30
BLOCK_TIME=120
DETECTION_TIME=1800
# Backend (nftables oder iptables)
BACKEND="/usr/libexec/sshguard/sshg-fw-nft-sets"
sudo systemctl enable sshguard
sudo systemctl start sshguard
Empfohlene Kombinationen
| Sicherheitslevel | Kombination |
|---|---|
| Basis | Grundhärtung + Fail2ban + nicht-standard Port |
| Mittel | Basis + Geo-Blocking + 2FA |
| Hoch | Basis + Port Knocking + 2FA |
| Maximal | SSH nur via VPN + 2FA (kein Internet-Zugang) |
Teil 4: Anti-Scan-Techniken
Scan-Erkennung und -Blockierung
Methode 1: PSAD (Port Scan Attack Detector)
sudo apt install psad -y
# Konfiguration
sudo nano /etc/psad/psad.conf
# Wichtige Einstellungen
EMAIL_ADDRESSES root@localhost; # ← E-Mail für Alerts
HOSTNAME mein-server;
HOME_NET any;
DANGER_LEVEL1 5;
DANGER_LEVEL2 15;
DANGER_LEVEL3 25;
DANGER_LEVEL4 50;
DANGER_LEVEL5 100;
# Auto-Block bei Danger Level 3+
ENABLE_AUTO_IDS Y;
AUTO_IDS_DANGER_LEVEL 3;
AUTO_BLOCK_TIMEOUT 3600;
# iptables-Logging aktivieren (PSAD braucht das)
sudo iptables -A INPUT -j LOG --log-prefix "iptables: "
sudo iptables -A FORWARD -j LOG --log-prefix "iptables: "
# PSAD starten
sudo systemctl enable psad
sudo systemctl start psad
# Status
sudo psad -S
Methode 2: PortSentry
sudo apt install portsentry -y
# Konfiguration
sudo nano /etc/portsentry/portsentry.conf
# Modus: atcp/audp für Stealth-Erkennung
TCP_MODE="atcp"
UDP_MODE="audp"
# Block-Methode
BLOCK_UDP="1"
BLOCK_TCP="1"
# iptables zum Blocken
KILL_ROUTE="/sbin/iptables -I INPUT -s $TARGET$ -j DROP"
# Aktivieren
sudo nano /etc/default/portsentry
# TCP_MODE="atcp"
# UDP_MODE="audp"
sudo systemctl enable portsentry
sudo systemctl restart portsentry
Methode 3: Tarpit (Honeypot)
Verlangsamt Portscanner extrem, indem Verbindungen absichtlich verzögert werden.
# Mit iptables TARPIT-Target (benötigt xtables-addons)
sudo apt install xtables-addons-common -y
# Häufig gescannte Ports in Tarpit
sudo iptables -A INPUT -p tcp --dport 23 -j TARPIT # Telnet
sudo iptables -A INPUT -p tcp --dport 3389 -j TARPIT # RDP
sudo iptables -A INPUT -p tcp --dport 5900 -j TARPIT # VNC
sudo iptables -A INPUT -p tcp --dport 1433 -j TARPIT # MSSQL
sudo iptables -A INPUT -p tcp --dport 3306 -j TARPIT # MySQL (falls nicht benötigt)
Methode 4: Endlessh (SSH-Tarpit)
Fake-SSH-Server auf Port 22, der Angreifer stundenlang beschäftigt.
# Installation
sudo apt install endlessh -y
# Konfiguration
sudo nano /etc/endlessh/config
Port 22
Delay 10000
MaxLineLength 32
MaxClients 4096
LogLevel 1
# Port 22 für endlessh freigeben
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/endlessh
# Starten
sudo systemctl enable endlessh
sudo systemctl start endlessh
# Echter SSH läuft auf Port 226 (oder via VPN)
Banner und Fingerprinting verhindern
SSH-Banner entfernen
# In /etc/ssh/sshd_config.d/99-hardening.conf:
Banner none
DebianBanner no
# Version aus Banner entfernen (kompiliert, daher nur begrenzt möglich)
# Alternative: SSH nur via VPN erreichbar machen
Webserver-Banner entfernen
# Caddy: Automatisch keine Version
# In Caddyfile:
{
servers {
protocols h1 h2 h3
}
}
example.de {
header -Server
# ...
}
# Nginx:
# In /etc/nginx/nginx.conf:
http {
server_tokens off;
more_clear_headers Server;
}
OS-Fingerprinting erschweren
# TCP-Timestamps deaktivieren
sudo sysctl -w net.ipv4.tcp_timestamps=0
# In /etc/sysctl.d/99-stealth.conf:
net.ipv4.tcp_timestamps = 0
net.ipv4.icmp_echo_ignore_all = 1
Teil 5: DDoS-Schutz
Grundlagen
DDoS-Schutz auf Server-Ebene ist begrenzt – bei volumetrischen Angriffen hilft nur Upstream-Filterung (Provider, CDN). Folgende Maßnahmen helfen bei kleineren Angriffen und Application-Layer-Attacks.
Methode 1: Kernel-Tuning
sudo nano /etc/sysctl.d/99-ddos.conf
# SYN-Flood-Schutz
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
# Connection-Tracking-Limits erhöhen
net.netfilter.nf_conntrack_max = 1000000
net.netfilter.nf_conntrack_tcp_timeout_established = 1800
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
# TIME_WAIT-Recycling
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
# Backlog für hohe Last
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
# ICMP-Limits
net.ipv4.icmp_ratelimit = 100
net.ipv4.icmp_ratemask = 88089
# Reverse Path Filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Bogus ICMP ignorieren
net.ipv4.icmp_ignore_bogus_error_responses = 1
sudo sysctl -p /etc/sysctl.d/99-ddos.conf
Methode 2: iptables Rate-Limiting
# SYN-Flood-Schutz
sudo iptables -A INPUT -p tcp --syn -m limit --limit 10/s --limit-burst 20 -j ACCEPT
sudo iptables -A INPUT -p tcp --syn -j DROP
# Allgemeines Rate-Limit pro IP
sudo iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m recent --set
sudo iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m recent --update --seconds 1 --hitcount 20 -j DROP
# HTTP/HTTPS Rate-Limit
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -m limit --limit 50/s --limit-burst 100 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j DROP
# Conntrack-Limit pro IP
sudo iptables -A INPUT -p tcp -m connlimit --connlimit-above 50 --connlimit-mask 32 -j DROP
Methode 3: nftables Rate-Limiting
sudo nano /etc/nftables.conf
table inet ddos_filter {
set blacklist {
type ipv4_addr
flags dynamic,timeout
timeout 1h
}
set rate_limit {
type ipv4_addr
flags dynamic
timeout 1m
}
chain input {
type filter hook input priority -100; policy accept;
# Blacklist
ip saddr @blacklist drop
# SYN-Flood-Schutz
tcp flags syn limit rate 10/second burst 20 packets accept
tcp flags syn add @blacklist { ip saddr timeout 1h } drop
# Allgemeines Rate-Limit
ct state new add @rate_limit { ip saddr limit rate over 20/second burst 50 packets } add @blacklist { ip saddr timeout 1h } drop
}
}
Methode 4: CrowdSec DDoS-Szenarios
# HTTP-DDoS-Erkennung
sudo cscli scenarios install crowdsecurity/http-crawl-non_statics
sudo cscli scenarios install crowdsecurity/http-bad-user-agent
sudo cscli scenarios install crowdsecurity/http-probing
# Aggressive Mode
sudo nano /etc/crowdsec/profiles.yaml
name: aggressive_profile
filters:
- Alert.Remediation == true
decisions:
- type: ban
duration: 24h # Längere Bans
Methode 5: Rate-Limiting im Reverse Proxy
Caddy mit Rate-Limiting
# Caddyfile
{
order rate_limit before basicauth
}
example.de {
rate_limit {
zone static_zone {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy 100.64.0.1:3000
}
Hinweis: Das rate_limit-Modul muss separat installiert werden oder Caddy mit diesem Plugin gebaut werden.
Nginx Rate-Limiting
# /etc/nginx/nginx.conf
http {
# Rate-Limit-Zonen definieren
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}
# In Server-Block:
server {
location / {
limit_req zone=general burst=20 nodelay;
limit_conn conn_limit 10;
proxy_pass http://backend;
}
location /login {
limit_req zone=login burst=5 nodelay;
proxy_pass http://backend;
}
}
Methode 6: Upstream-DDoS-Schutz
Bei größeren Angriffen hilft nur Filterung vor dem Server:
| Anbieter | Typ | Kosten | Empfohlen für |
|---|---|---|---|
| Hetzner | Basis L3/L4 | Inklusive | Einfache Angriffe |
| OVH | VAC (L3-L7) | Inklusive | Gaming, Webserver |
| Cloudflare | CDN + DDoS | Kostenlos/Pro | Webseiten (US-Bedenken) |
| BunnyNet | CDN + DDoS | Pay-per-use | EU-Alternative |
| Path.net | DDoS-Schutz | Ab ~20€/Monat | Dedizierter Schutz |
Teil 6: Dienste trotzdem erreichbar machen
Reverse Proxy als einziger Eintrittspunkt
Das Konzept: Der Server ist "unsichtbar" – nur Port 80/443 sind offen, alles andere ist DROP. Dienste werden über einen Reverse Proxy bereitgestellt.
Internet
│
▼
┌─────────────────────────┐
│ Reverse Proxy (VPS) │
│ │
│ Port 80 ───┐ │
│ Port 443 ───┼──► Caddy │
│ │ │
│ Alle anderen Ports: │
│ DROP (unsichtbar) │
└────────────┬────────────┘
│
NetBird/WireGuard
(verschlüsselt)
│
▼
┌─────────────────────────┐
│ Homeserver │
│ │
│ Wiki, Vaultwarden, ... │
│ (nur via VPN erreichbar)│
└─────────────────────────┘
Multi-Domain-Setup
# Caddyfile für mehrere Dienste
{
email admin@example.de
}
# Wiki
wiki.example.de {
reverse_proxy 100.64.0.1:3000
header -Server
}
# Vaultwarden
vault.example.de {
reverse_proxy 100.64.0.1:8080
header -Server
}
# Git
git.example.de {
reverse_proxy 100.64.0.1:3001
header -Server
}
# Standard: Nichts zeigen
:80, :443 {
respond "Not Found" 404
}
Wildcard-SSL für unbekannte Subdomains
# Alle Subdomains auf einen Catch-All
*.example.de {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
respond "Not Found" 404
}
# Bekannte Dienste
wiki.example.de {
reverse_proxy 100.64.0.1:3000
}
Teil 7: Monitoring und Alerting
Log-Überwachung
# Fail2ban-Aktivität
sudo tail -f /var/log/fail2ban.log
# SSH-Versuche
sudo tail -f /var/log/auth.log | grep sshd
# Firewall-Drops (wenn Logging aktiv)
sudo tail -f /var/log/syslog | grep iptables
Monitoring-Tools
Netdata (Echtzeit-Dashboard)
# Installation
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
# Nur auf localhost (Zugriff via SSH-Tunnel oder VPN)
sudo nano /etc/netdata/netdata.conf
[web]
bind to = 127.0.0.1
Prometheus + Grafana (Fortgeschritten)
# node_exporter für System-Metriken
sudo apt install prometheus-node-exporter -y
# Nur auf VPN-Interface binden
sudo nano /etc/default/prometheus-node-exporter
# ARGS="--web.listen-address=100.64.0.2:9100"
Alerts einrichten
# Einfaches Alert-Script
sudo nano /usr/local/bin/security-alert.sh
#!/bin/bash
# Bei zu vielen Failed SSH-Logins
THRESHOLD=10
COUNT=$(grep "Failed password" /var/log/auth.log | wc -l)
if [ $COUNT -gt $THRESHOLD ]; then
echo "Alert: $COUNT failed SSH attempts" | mail -s "Security Alert" admin@example.de
fi
chmod +x /usr/local/bin/security-alert.sh
# Cronjob
echo "*/5 * * * * root /usr/local/bin/security-alert.sh" | sudo tee /etc/cron.d/security-alert
Zusammenfassung: Sicherheitslevel
| Level | Maßnahmen | Aufwand |
|---|---|---|
| Basis | UFW, Fail2ban, SSH-Härtung, nicht-standard Port | 30 Min |
| Mittel | + iptables Stealth, Anti-Scan, CrowdSec, 2FA | 1-2 Std |
| Hoch | + Port Knocking, Geo-Blocking, Kernel-Hardening | 2-3 Std |
| Maximal | + SSH nur VPN, Endlessh-Tarpit, PSAD, DDoS-Tuning | 3-5 Std |
Schnellstart-Befehle
# Basis-Härtung in 5 Minuten:
sudo apt update && sudo apt install -y ufw fail2ban
# SSH auf neuen Port (z.B. 226)
echo "Port 226" | sudo tee /etc/ssh/sshd_config.d/port.conf
sudo systemctl restart sshd
# Firewall
sudo ufw default deny incoming
sudo ufw allow 226/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
# Fail2ban aktivieren
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
echo "Basis-Härtung abgeschlossen!"
Letzte Aktualisierung: 2025