Skip to main content

Verstecken und Absichern


Inhaltsverzeichnis

  1. Sicherheitskonzepte und Architekturen
  2. Server-Grundhärtung
  3. SSH absichern und verstecken
  4. Firewall-Konfiguration
  5. VPN-Gateway Setup (WireGuard)
  6. Reverse Proxy mit Nginx + DDoS-Schutz
  7. Cloudflare für Web-Services
  8. Minecraft/Gaming-Server Setup
  9. Self-Hosted Services im Homelab
  10. Bastion/Jump Server
  11. Port-Knocking
  12. Fail2Ban und Intrusion Prevention
  13. Monitoring und Alerting
  14. Praktische Komplettszenarien

1. Sicherheitskonzepte und Architekturen

Grundprinzipien

Defense in Depth (Mehrschichtige Verteidigung)

Jede Schicht bietet eigenen Schutz. Wenn eine versagt, schützen andere noch.

┌─────────────────────────────────────┐
│ Ebene 7: CDN/DDoS (Cloudflare)     │
├─────────────────────────────────────┤
│ Ebene 6: Edge/Gateway Server        │
├─────────────────────────────────────┤
│ Ebene 5: Reverse Proxy + WAF        │
├─────────────────────────────────────┤
│ Ebene 4: VPN-Tunnel                 │
├─────────────────────────────────────┤
│ Ebene 3: Firewall/IPS               │
├─────────────────────────────────────┤
│ Ebene 2: Application Security       │
├─────────────────────────────────────┤
│ Ebene 1: Server-Härtung             │
└─────────────────────────────────────┘

Zero Trust

  • Vertraue nichts, auch nicht im "internen" Netz
  • Jede Verbindung authentifizieren
  • Minimale Berechtigungen

Security through Obscurity (als ZUSATZ)

  • NICHT als einzige Maßnahme!
  • Aber: Versteckte Services = weniger Bot-Angriffe
  • Ports ändern, IPs verbergen, Services verstecken

Architektur-Szenarien

Szenario 1: Blog/Website mit Cloudflare (DDoS-Schutz)

Internet
   ↓
┌──────────────────────────────────┐
│ Cloudflare (DDoS + WAF + Cache)  │
└──────────────────────────────────┘
   ↓ (nur Cloudflare IPs erlaubt)
┌──────────────────────────────────┐
│ Nginx Reverse Proxy              │
│ IP: 203.0.113.10 (versteckt)     │
│ Ports: 80, 443                   │
└──────────────────────────────────┘
   ↓ (localhost oder intern)
┌──────────────────────────────────┐
│ Application (WordPress, etc.)    │
│ Lauscht auf: 127.0.0.1:8080      │
└──────────────────────────────────┘

Management:
Admin → VPN (WireGuard) → Server SSH (Port 55222, nur VPN-IPs)

Vorteile:

  • Echte Server-IP komplett versteckt
  • DDoS-Schutz durch Cloudflare
  • WAF (Web Application Firewall)
  • Kostenlos für Basic

Szenario 2: Minecraft-Server mit "Bauernopfer"

Internet
   ↓
┌──────────────────────────────────┐
│ TCPShield / Cloudflare Spectrum  │ ← DDoS-Schutz für TCP
└──────────────────────────────────┘
   ↓
┌──────────────────────────────────┐
│ "Gate" Server (Proxy)            │
│ IP: 203.0.113.20 (öffentlich)    │
│ Port: 25565                      │
│ Software: Velocity/BungeeCord    │
└──────────────────────────────────┘
   ↓ (VPN-Tunnel)
┌──────────────────────────────────┐
│ Actual Game Server (versteckt)   │
│ IP: 10.0.0.50 (nur VPN)          │
│ Port: 25565 (nur von Gate)       │
└──────────────────────────────────┘

Management:
Admin → VPN → SSH zu beiden Servern

Vorteile:

  • Echter Game-Server komplett geschützt
  • Gate-Server ist "Bauernopfer" (billig, schnell ersetzbar)
  • Bei DDoS: Gate-Server austauschen, Game-Server läuft weiter

Szenario 3: Homelab mit Bastion Host

Internet
   ↓
┌──────────────────────────────────┐
│ Bastion/Jump Server              │
│ IP: Öffentlich                   │
│ Ports: 55222 (SSH, Port-Knocking)│
│        51820 (WireGuard)         │
└──────────────────────────────────┘
   ↓ (privates Netz 10.0.0.0/24)
┌──────────────────────────────────┐
│ Reverse Proxy (Nginx)            │
│ IP: 10.0.0.10                    │
│ Services: Jellyfin, Nextcloud    │
└──────────────────────────────────┘
   ↓
├─ Jellyfin: 10.0.0.20:8096
├─ Nextcloud: 10.0.0.21:80
├─ Home Assistant: 10.0.0.22:8123
└─ NAS: 10.0.0.30

Public Access:
Internet → Cloudflare Tunnel → Reverse Proxy → Services
(KEINE offenen Ports außer Bastion)

Admin Access:
Admin → VPN → Bastion → Intern

Vorteile:

  • Alle Services im privaten Netz
  • Nur ein exponierter Punkt (Bastion)
  • Cloudflare Tunnel für Web-Services (kein Port-Forwarding)

Szenario 4: Multi-Server Setup mit VPN-Gateway

Internet
   ↓
┌─────────────────────────────────────────┐
│ VPN Gateway (WireGuard)                 │
│ IP: 203.0.113.5                         │
│ Port: 51820 (nach Port-Knocking)        │
└─────────────────────────────────────────┘
   ↓ (VPN-Netz 10.8.0.0/24)
   ├─ VPN Client: Admin (10.8.0.2)
   │
   ↓ (Internes Netz 10.0.0.0/24)
┌──────────────────────────────────┐
│ Nginx Reverse Proxy              │
│ IP: 10.0.0.10                    │
└──────────────────────────────────┘
   ↓
├─ App Server 1: 10.0.0.31
├─ App Server 2: 10.0.0.32
├─ Database: 10.0.0.40
└─ Cache (Redis): 10.0.0.41

Public Web:
Internet → Cloudflare → VPN Gateway (Forwarding) → Nginx → Apps

Management:
Admin → VPN → Alle Server via SSH

2. Server-Grundhärtung

Initial Setup

# System aktualisieren
sudo apt update && sudo apt upgrade -y

# Automatische Sicherheitsupdates
sudo apt install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades

Admin-User erstellen

# User erstellen
sudo adduser admin

# Starkes Passwort (wird später durch Keys ersetzt):
# Mindestens 24 Zeichen: Groß/Klein/Zahlen/Sonderzeichen

# Sudo-Rechte
sudo usermod -aG sudo admin

# SSH-Key generieren (auf lokalem Rechner)
ssh-keygen -t ed25519 -C "admin@myserver"

# Key auf Server kopieren
ssh-copy-id admin@SERVER_IP

# WICHTIG: Test in neuer Session
ssh admin@SERVER_IP
sudo whoami  # muss "root" ausgeben

# Erst nach erfolgreichem Test:
sudo passwd -l root

Kernel-Härtung

sudo nano /etc/sysctl.d/99-security.conf
# IP-Forwarding (0 für normale Server, 1 für VPN-Gateway)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# SYN-Flood-Schutz
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2

# Spoof-Schutz (Reverse Path Filtering)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# ICMP-Redirects ignorieren
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Source-Routing deaktivieren
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Martian-Pakete loggen
net.ipv4.conf.all.log_martians = 1

# ICMP-Broadcasts ignorieren
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1

# TCP-Timestamps deaktivieren (Fingerprinting erschweren)
net.ipv4.tcp_timestamps = 0

# Kernel-Pointer verstecken
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1

# ASLR (Address Space Layout Randomization)
kernel.randomize_va_space = 2
sudo sysctl -p /etc/sysctl.d/99-security.conf

Unnötige Services deaktivieren

# Services auflisten
systemctl list-unit-files --type=service --state=enabled

# Beispiele (NUR wenn wirklich nicht benötigt!)
sudo systemctl disable --now bluetooth.service
sudo systemctl disable --now cups.service
sudo systemctl disable --now avahi-daemon.service
sudo systemctl disable --now ModemManager.service

3. SSH absichern und verstecken

SSH-Keys einrichten

Auf lokalem Rechner:

# Ed25519 Key (empfohlen)
ssh-keygen -t ed25519 -C "admin@secure-server"

# Mit Passphrase (zusätzliche Sicherheit)
# Eingabe: Starke Passphrase

# Key auf Server kopieren
ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@SERVER_IP

# Config erstellen für einfachen Zugriff
nano ~/.ssh/config

~/.ssh/config:

Host myserver
    HostName SERVER_IP
    User admin
    Port 55222
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60
    ServerAliveCountMax 3

Verbinden:

ssh myserver

sshd_config - Maximale Härtung

sudo nano /etc/ssh/sshd_config

Empfohlene Konfiguration:

# Port ändern (weniger Bot-Angriffe)
Port 55222

# Nur IPv4
AddressFamily inet

# Nur auf spezifischen IPs lauschen (optional)
# ListenAddress 0.0.0.0
# Oder bei VPN: nur VPN-IP
# ListenAddress 10.8.0.1

# Root-Login verbieten
PermitRootLogin no

# NUR Key-Authentifizierung
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no

# PAM nutzen
UsePAM yes

# Kerberos/GSSAPI deaktivieren
KerberosAuthentication no
GSSAPIAuthentication no

# X11-Forwarding (nur wenn benötigt)
X11Forwarding no

# Agent-Forwarding deaktivieren
AllowAgentForwarding no

# TCP-Forwarding einschränken
AllowTcpForwarding no
# Oder nur für spezifische User
# Match User admin
#     AllowTcpForwarding yes

# MaxAuthTries reduzieren
MaxAuthTries 3
MaxSessions 2

# Login-Grace-Time reduzieren
LoginGraceTime 30

# Nur spezifische User erlauben
AllowUsers admin

# Oder spezifische Gruppen
# AllowGroups ssh-users

# Client-Alive (Idle-Timeout)
ClientAliveInterval 300
ClientAliveCountMax 2

# Banner deaktivieren
Banner none

# Strict Modes
StrictModes yes

# Host-based Auth deaktivieren
HostbasedAuthentication no

# Moderne Krypto-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

# SFTP-Subsystem (nur wenn benötigt)
Subsystem sftp /usr/lib/openssh/sftp-server

SSH neu starten:

# Syntax-Check
sudo sshd -t

# WICHTIG: Alte Session offen lassen!
# In neuer Session testen
ssh -p 55222 admin@SERVER_IP

# Wenn erfolgreich:
sudo systemctl restart sshd

SSH nur über VPN erlauben

Wenn VPN eingerichtet ist (siehe Kapitel 5):

sudo nano /etc/ssh/sshd_config
# Nur auf VPN-Interface lauschen
ListenAddress 10.8.0.1

# Oder nur VPN-IPs erlauben (in Firewall)

In Firewall:

# SSH nur von VPN-Netz
sudo ufw delete allow 55222/tcp
sudo ufw allow from 10.8.0.0/24 to any port 55222 proto tcp

SSH mit 2FA (Zwei-Faktor-Authentifizierung)

# Google Authenticator installieren
sudo apt install libpam-google-authenticator

# Für User einrichten
google-authenticator

Fragen beantworten:

  • Time-based tokens: yes
  • Update .google_authenticator: yes
  • Disallow multiple uses: yes
  • Increase time window: no
  • Rate limiting: yes

QR-Code mit Authenticator-App scannen

PAM konfigurieren:

sudo nano /etc/pam.d/sshd

Am Anfang hinzufügen:

# 2FA
auth required pam_google_authenticator.so nullok

sshd_config anpassen:

sudo nano /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
sudo systemctl restart sshd

Login jetzt: SSH-Key + 2FA-Code erforderlich


4. Firewall-Konfiguration

UFW (Uncomplicated Firewall) - Einfach

Initial Setup:

# Installieren
sudo apt install ufw

# Standard-Policies (WICHTIG: Reihenfolge!)
sudo ufw default deny incoming
sudo ufw default allow outgoing

# SSH erlauben (BEVOR ufw enable!)
sudo ufw allow 55222/tcp comment 'SSH'

# Firewall aktivieren
sudo ufw enable

# Status
sudo ufw status verbose

Services hinzufügen:

# HTTP/HTTPS (nur wenn Webserver)
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# WireGuard VPN
sudo ufw allow 51820/udp comment 'WireGuard'

# Von spezifischer IP
sudo ufw allow from 203.0.113.50 to any port 55222 proto tcp comment 'SSH from Admin'

# Von IP-Range
sudo ufw allow from 10.0.0.0/24 to any port 3306 proto tcp comment 'MySQL from LAN'

# Rate-Limiting (gegen Brute-Force)
sudo ufw limit 55222/tcp comment 'SSH Rate-Limited'

Nur Cloudflare IPs erlauben (für Webserver):

# Script erstellen
sudo nano /usr/local/bin/ufw-cloudflare.sh
#!/bin/bash
# Cloudflare IPs für UFW

# Alte Regeln löschen
sudo ufw delete allow 80/tcp 2>/dev/null
sudo ufw delete allow 443/tcp 2>/dev/null

# Cloudflare IPv4
for IP in $(curl -s https://www.cloudflare.com/ips-v4); do
    sudo ufw allow from $IP to any port 80 proto tcp comment 'Cloudflare'
    sudo ufw allow from $IP to any port 443 proto tcp comment 'Cloudflare'
done

# Cloudflare IPv6
for IP in $(curl -s https://www.cloudflare.com/ips-v6); do
    sudo ufw allow from $IP to any port 80 proto tcp comment 'Cloudflare'
    sudo ufw allow from $IP to any port 443 proto tcp comment 'Cloudflare'
done

echo "Cloudflare IPs aktualisiert"
sudo chmod +x /usr/local/bin/ufw-cloudflare.sh
sudo /usr/local/bin/ufw-cloudflare.sh

Cron für monatliche Aktualisierung:

sudo crontab -e
0 3 1 * * /usr/local/bin/ufw-cloudflare.sh

iptables/nftables - Fortgeschritten

iptables DDoS-Schutz:

# SYN-Flood-Schutz
sudo iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
sudo iptables -A INPUT -p tcp --syn -j DROP

# Port-Scan-Schutz
sudo iptables -N port-scan
sudo iptables -A port-scan -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j RETURN
sudo iptables -A port-scan -j DROP
sudo iptables -A INPUT -j port-scan

# Connection-Limit (max 80 Verbindungen pro IP)
sudo iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 80 -j REJECT

# Ping-Flood-Schutz
sudo iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

# Speichern
sudo apt install iptables-persistent
sudo netfilter-persistent save

5. VPN-Gateway Setup (WireGuard)

WireGuard ist modern, schnell und sicher - perfekt um Server komplett zu verstecken.

WireGuard auf Gateway-Server installieren

# Ubuntu 20.04+
sudo apt update
sudo apt install wireguard

# Kernel-Modul laden
sudo modprobe wireguard

# IP-Forwarding aktivieren
sudo nano /etc/sysctl.d/99-wireguard.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf

Keys generieren

# Server-Keys
cd /etc/wireguard
sudo umask 077
sudo wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key

# Client-Keys
sudo wg genkey | sudo tee client1_private.key | wg pubkey | sudo tee client1_public.key

# Anzeigen
sudo cat server_private.key
sudo cat server_public.key
sudo cat client1_private.key
sudo cat client1_public.key

Server-Konfiguration

sudo nano /etc/wireguard/wg0.conf
[Interface]
# VPN-IP des Servers
Address = 10.8.0.1/24

# Server Private Key
PrivateKey = SERVER_PRIVATE_KEY_HIER

# Port
ListenPort = 51820

# Firewall-Regeln beim Start/Stopp
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Client 1 (Admin)
[Peer]
# Client Public Key
PublicKey = CLIENT1_PUBLIC_KEY_HIER

# Erlaubte IPs (VPN-IP des Clients)
AllowedIPs = 10.8.0.2/32

# Keep-Alive
PersistentKeepalive = 25

# Client 2 (optional)
[Peer]
PublicKey = CLIENT2_PUBLIC_KEY_HIER
AllowedIPs = 10.8.0.3/32

Interface Namen prüfen:

ip a
# Suche nach deinem Internet-Interface (meist eth0, ens3, oder ähnlich)
# Ersetze "eth0" in PostUp/PostDown falls anders

Client-Konfiguration

Auf Client-Rechner:

sudo nano /etc/wireguard/wg0-client.conf
[Interface]
# Client VPN-IP
Address = 10.8.0.2/24

# Client Private Key
PrivateKey = CLIENT1_PRIVATE_KEY_HIER

# DNS (optional - Server DNS oder 1.1.1.1)
DNS = 1.1.1.1

[Peer]
# Server Public Key
PublicKey = SERVER_PUBLIC_KEY_HIER

# Server öffentliche IP und Port
Endpoint = SERVER_PUBLIC_IP:51820

# Routen durch VPN
# Nur VPN-Netz:
AllowedIPs = 10.8.0.0/24

# ODER alle Zugriffe durch VPN (Kill-Switch):
# AllowedIPs = 0.0.0.0/0

# Keep-Alive
PersistentKeepalive = 25

WireGuard starten

Server:

# Interface starten
sudo wg-quick up wg0

# Autostart beim Boot
sudo systemctl enable wg-quick@wg0

# Status
sudo wg show

Client:

# Verbinden
sudo wg-quick up wg0-client

# Testen
ping 10.8.0.1

# SSH über VPN
ssh admin@10.8.0.1

Firewall für WireGuard

# Server
sudo ufw allow 51820/udp comment 'WireGuard'

# SSH nur von VPN
sudo ufw delete allow 55222/tcp
sudo ufw allow from 10.8.0.0/24 to any port 55222 proto tcp

VPN-Gateway mit internem Netz

Szenario: VPN-Server (10.8.0.1) routet zu internem Netz (10.0.0.0/24)

Server-Config:

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
PrivateKey = SERVER_PRIVATE_KEY
ListenPort = 51820

# Forwarding zu internem Netz
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32

Client-Config:

[Interface]
Address = 10.8.0.2/24
PrivateKey = CLIENT_PRIVATE_KEY

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = SERVER_IP:51820

# Zugriff auf VPN + internes Netz
AllowedIPs = 10.8.0.0/24, 10.0.0.0/24

Test:

# Von Client
ping 10.0.0.10  # Interner Server
ssh admin@10.0.0.20  # Interner Server

6. Reverse Proxy mit Nginx + DDoS-Schutz

Nginx installieren

sudo apt install nginx

# Oder neueste Version
sudo apt install software-properties-common
sudo add-apt-repository ppa:nginx/stable
sudo apt update
sudo apt install nginx

Basis-Konfiguration

sudo nano /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 2048;
    multi_accept on;
    use epoll;
}

http {
    # Basic Settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;  # Version verstecken
    
    # Buffer Limits (gegen Buffer-Overflow)
    client_body_buffer_size 1K;
    client_header_buffer_size 1k;
    client_max_body_size 100M;  # Anpassen je nach Need
    large_client_header_buffers 2 1k;
    
    # Timeouts
    client_body_timeout 10;
    client_header_timeout 10;
    send_timeout 10;
    
    # Rate Limiting Zone
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    
    # Logging
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    
    # Gzip
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml;
    
    # Virtual Hosts
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Website-Konfiguration mit DDoS-Schutz

sudo nano /etc/nginx/sites-available/mysite.conf
# Rate-Limiting-Zones (bereits in nginx.conf, aber hier zur Referenz)
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

# Backend-Server
upstream backend {
    server 127.0.0.1:8080;
    # Oder interner Server:
    # server 10.0.0.20:8080;
}

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    
    # HTTP zu HTTPS redirect
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    # SSL-Zertifikate (Let's Encrypt)
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # SSL-Härtung
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    # Rate Limiting
    limit_req zone=mylimit burst=20 nodelay;
    limit_conn conn_limit 10;
    
    # Logs
    access_log /var/log/nginx/mysite_access.log;
    error_log /var/log/nginx/mysite_error.log;
    
    # Root
    root /var/www/mysite;
    index index.html index.php;
    
    location / {
        try_files $uri $uri/ =404;
        
        # Oder Proxy zu Backend:
        # proxy_pass http://backend;
        # proxy_set_header Host $host;
        # proxy_set_header X-Real-IP $remote_addr;
        # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # Block bad bots
    location ~* (bot|crawler|spider|scraper) {
        return 403;
    }
    
    # Deny hidden files
    location ~ /\. {
        deny all;
    }
}

Aktivieren:

sudo ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Let's Encrypt SSL

sudo apt install certbot python3-certbot-nginx

# Zertifikat holen
sudo certbot --nginx -d example.com -d www.example.com

# Auto-Renewal testen
sudo certbot renew --dry-run

Nginx als Reverse Proxy für interne Services

# Jellyfin
upstream jellyfin {
    server 10.0.0.20:8096;
}

server {
    listen 443 ssl http2;
    server_name jellyfin.example.com;
    
    # SSL...
    
    location / {
        proxy_pass http://jellyfin;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket-Support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

7. Cloudflare für Web-Services

Cloudflare bietet DDoS-Schutz, WAF, CDN und versteckt deine echte Server-IP.

Cloudflare einrichten

1. Account erstellen:

  • cloudflare.com
  • Domain hinzufügen
  • Nameserver bei Domain-Registrar ändern

2. DNS konfigurieren:

A     @           SERVER_IP   (Proxy an = orange Cloud)
A     www         SERVER_IP   (Proxy an)
CNAME api         @           (Proxy an)

Orange Cloud = Traffic durch Cloudflare

3. SSL/TLS Mode:

  • Dashboard → SSL/TLS
  • Modus: Full (strict)

4. Firewall-Regeln (kostenlos begrenzt):

# Nur Deutschland erlauben
Country is not in {DE} → Block

# Bad Bots blockieren
(http.user_agent contains "bot") → Challenge

# Rate-Limiting
(http.request.uri.path eq "/api/login") → Rate Limit (5 requests/min)

Server nur für Cloudflare öffnen

UFW-Script (siehe Kapitel 4):

sudo /usr/local/bin/ufw-cloudflare.sh

Oder in Nginx:

# Cloudflare IPs erlauben, Rest blocken
geo $cloudflare {
    default 0;
    # IPv4
    103.21.244.0/22 1;
    103.22.200.0/22 1;
    103.31.4.0/22 1;
    # ... (alle von https://www.cloudflare.com/ips-v4)
}

server {
    if ($cloudflare = 0) {
        return 403;
    }
    # ...
}

Cloudflare Tunnel (kein Port-Forwarding nötig!)

Alternative: Cloudflare Tunnel - Server braucht KEINE offenen Ports!

# cloudflared installieren
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb

# Login
cloudflared tunnel login

# Tunnel erstellen
cloudflared tunnel create mytunnel

# Config
sudo nano ~/.cloudflared/config.yml
tunnel: TUNNEL_ID
credentials-file: /home/admin/.cloudflared/TUNNEL_ID.json

ingress:
  - hostname: example.com
    service: http://localhost:80
  - hostname: api.example.com
    service: http://localhost:8080
  - service: http_status:404
# Route DNS
cloudflared tunnel route dns mytunnel example.com
cloudflared tunnel route dns mytunnel api.example.com

# Service einrichten
sudo cloudflared service install
sudo systemctl start cloudflared
sudo systemctl enable cloudflared

Vorteile:

  • Keine offenen Ports (nur ausgehende Verbindung)
  • DDoS-Schutz
  • Automatisches SSL

8. Minecraft/Gaming-Server Setup

Szenario: Minecraft mit Gate-Server (Bauernopfer)

Architektur:

Spieler
  ↓
TCPShield (DDoS-Schutz) oder Cloudflare Spectrum
  ↓
Gate-Server (203.0.113.50:25565) - Velocity/BungeeCord
  ↓ (WireGuard VPN)
Game-Server (10.8.0.10:25565) - Minecraft

Gate-Server Setup

# Java installieren
sudo apt install openjdk-17-jre-headless

# Velocity herunterladen
mkdir -p ~/minecraft-gate
cd ~/minecraft-gate
wget https://api.papermc.io/v2/projects/velocity/versions/latest/builds/latest/downloads/velocity-3.x.x.jar

# Starten (initial)
java -Xms512M -Xmx1024M -jar velocity-*.jar

# Config bearbeiten
nano velocity.toml

velocity.toml:

bind = "0.0.0.0:25565"
motd = "My Server"

[servers]
# Game-Server (über VPN)
lobby = "10.8.0.10:25565"
survival = "10.8.0.11:25565"

[forced-hosts]
"play.example.com" = ["lobby"]

[advanced]
# IP-Forwarding aktivieren
connection-timeout = 5000
read-timeout = 30000

Game-Server Setup (versteckt)

# Minecraft Server auf 10.8.0.10
# NUR über VPN erreichbar!

# Firewall
sudo ufw default deny incoming
sudo ufw allow from 10.8.0.0/24 to any port 25565

# server.properties
nano server.properties
server-ip=10.8.0.10
server-port=25565
online-mode=false  # Velocity macht die Auth

TCPShield Integration

1. Account bei tcpshield.com erstellen

2. Domain hinzufügen: play.example.com

3. DNS konfigurieren:

SRV  _minecraft._tcp.play  0 5 25565 shield.tcpshield.com
A    play                   TCPShield-IP

4. Backend in TCPShield:

Backend IP: Gate-Server-IP (203.0.113.50)

5. Velocity konfigurieren:

nano velocity.toml
[advanced]
haproxy-protocol = true

Systemd-Service für Gate

sudo nano /etc/systemd/system/minecraft-gate.service
[Unit]
Description=Minecraft Gate (Velocity)
After=network.target

[Service]
Type=simple
User=minecraft
WorkingDirectory=/home/minecraft/velocity
ExecStart=/usr/bin/java -Xms512M -Xmx1024M -jar velocity.jar
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable minecraft-gate
sudo systemctl start minecraft-gate

Bei DDoS: Gate-Server austauschen

# Neue billige VPS mieten
# Velocity drauf installieren
# Backend-IP in TCPShield ändern
# Alte VPS zerstören

# Game-Server läuft weiter, Spieler merken nichts!

9. Self-Hosted Services im Homelab

Szenario: Nextcloud, Jellyfin, Home Assistant

Architektur:

Internet
  ↓
Cloudflare Tunnel (keine offenen Ports!)
  ↓
Nginx Reverse Proxy (10.0.0.10)
  ├─→ Nextcloud (10.0.0.20:80)
  ├─→ Jellyfin (10.0.0.21:8096)
  └─→ Home Assistant (10.0.0.22:8123)

Admin Access:
  WireGuard VPN → Bastion Host → Internes Netz

Cloudflare Tunnel Setup

# cloudflared installieren (siehe Kapitel 7)

# Config
sudo nano ~/.cloudflared/config.yml
tunnel: YOUR_TUNNEL_ID
credentials-file: /root/.cloudflared/YOUR_TUNNEL_ID.json

ingress:
  # Nextcloud
  - hostname: cloud.example.com
    service: http://10.0.0.10:80
    originRequest:
      noTLSVerify: true
  
  # Jellyfin
  - hostname: jellyfin.example.com
    service: http://10.0.0.10:8096
  
  # Home Assistant
  - hostname: ha.example.com
    service: http://10.0.0.10:8123
  
  # Catch-all
  - service: http_status:404
# DNS-Routes
cloudflared tunnel route dns mytunnel cloud.example.com
cloudflared tunnel route dns mytunnel jellyfin.example.com
cloudflared tunnel route dns mytunnel ha.example.com

# Service starten
sudo systemctl start cloudflared
sudo systemctl enable cloudflared

Nginx Reverse Proxy Config

Nextcloud:

sudo nano /etc/nginx/sites-available/nextcloud
upstream nextcloud {
    server 10.0.0.20:80;
}

server {
    listen 80;
    server_name cloud.example.com;
    
    client_max_body_size 10G;
    
    location / {
        proxy_pass http://nextcloud;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Jellyfin:

upstream jellyfin {
    server 10.0.0.21:8096;
}

server {
    listen 8096;
    server_name jellyfin.example.com;
    
    location / {
        proxy_pass http://jellyfin;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Home Assistant:

upstream homeassistant {
    server 10.0.0.22:8123;
}

server {
    listen 8123;
    server_name ha.example.com;
    
    location / {
        proxy_pass http://homeassistant;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
sudo ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/jellyfin /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/homeassistant /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Firewall im Homelab

# Nginx Proxy
sudo ufw allow from 127.0.0.1 to any port 80
sudo ufw allow from 127.0.0.1 to any port 8096
sudo ufw allow from 127.0.0.1 to any port 8123

# VPN
sudo ufw allow 51820/udp

# SSH nur von VPN
sudo ufw allow from 10.8.0.0/24 to any port 22

# Services nur intern
# (keine öffentlichen Ports außer VPN!)

10. Bastion/Jump Server

Ein Bastion Host ist der EINZIGE öffentlich erreichbare Server - alle anderen sind versteckt.

Architektur

Internet
  ↓
Bastion Host (203.0.113.100)
  - SSH: Port 55222 (Port-Knocking)
  - WireGuard: 51820
  ↓ (Private Network 10.0.0.0/24)
  ├─ App Server 1 (10.0.0.10)
  ├─ App Server 2 (10.0.0.11)
  ├─ Database (10.0.0.20)
  └─ NAS (10.0.0.30)

Bastion-Server Setup

# Minimale Installation
# Nur SSH + WireGuard + Firewall

# SSH härten (siehe Kapitel 3)
# WireGuard einrichten (siehe Kapitel 5)

# Firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 51820/udp
# SSH mit Port-Knocking (siehe Kapitel 11)

# Logging maximieren
sudo nano /etc/ssh/sshd_config
LogLevel VERBOSE

SSH Proxy Jump

Auf lokalem Rechner:

nano ~/.ssh/config
# Bastion
Host bastion
    HostName 203.0.113.100
    User admin
    Port 55222
    IdentityFile ~/.ssh/bastion_key

# Interne Server (via Bastion)
Host app1
    HostName 10.0.0.10
    User admin
    ProxyJump bastion
    IdentityFile ~/.ssh/internal_key

Host db
    HostName 10.0.0.20
    User admin
    ProxyJump bastion

Verbinden:

# Direkt zu internem Server (über Bastion)
ssh app1
ssh db

# SCP über Bastion
scp -o ProxyJump=bastion file.txt app1:/tmp/

Bastion-Härtung

# Zwei-Faktor-Auth (siehe Kapitel 3)
# IP-Whitelist (nur bekannte IPs)
sudo ufw allow from ADMIN_IP to any port 55222

# Audit-Logging
sudo apt install auditd
sudo systemctl enable auditd
sudo systemctl start auditd

# SSH-Sessions loggen
sudo nano /etc/audit/rules.d/ssh.rules
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /var/log/auth.log -p wa -k auth_log
sudo service auditd restart

11. Port-Knocking

Port-Knocking versteckt SSH - Port ist "geschlossen" bis korrekte Sequenz geklopft wird.

knockd installieren

sudo apt install knockd

knockd konfigurieren

sudo nano /etc/knockd.conf
[options]
    UseSyslog

[openSSH]
    sequence    = 7000,8000,9000
    seq_timeout = 15
    command     = /usr/sbin/ufw allow from %IP% to any port 55222 proto tcp
    tcpflags    = syn

[closeSSH]
    sequence    = 9000,8000,7000
    seq_timeout = 15
    command     = /usr/sbin/ufw delete allow from %IP% to any port 55222 proto tcp
    tcpflags    = syn

knockd aktivieren

sudo nano /etc/default/knockd
START_KNOCKD=1
KNOCKD_OPTS="-i eth0"  # Dein Interface
sudo systemctl enable knockd
sudo systemctl start knockd

Firewall anpassen

# SSH-Port standardmäßig schließen
sudo ufw delete allow 55222/tcp
sudo ufw reload

Verwendung

Von Client (Linux/Mac):

# Sequenz klopfen
knock SERVER_IP 7000 8000 9000

# Warten 1-2 Sekunden
sleep 2

# SSH verbinden
ssh -p 55222 admin@SERVER_IP

# Nach Session: Port schließen
knock SERVER_IP 9000 8000 7000

knock-Client installieren:

# Debian/Ubuntu
sudo apt install knockd

# macOS
brew install knock

Script für einfache Nutzung:

nano ~/ssh-knock.sh
#!/bin/bash
SERVER="203.0.113.100"
PORT="55222"

# Klopfen
knock $SERVER 7000 8000 9000
sleep 2

# SSH
ssh -p $PORT admin@$SERVER

# Port schließen nach Exit
knock $SERVER 9000 8000 7000
chmod +x ~/ssh-knock.sh
./ssh-knock.sh

Port-Knocking für WireGuard

sudo nano /etc/knockd.conf
[openVPN]
    sequence    = 1111,2222,3333
    seq_timeout = 15
    command     = /usr/sbin/ufw allow from %IP% to any port 51820 proto udp
    tcpflags    = syn

[closeVPN]
    sequence    = 3333,2222,1111
    seq_timeout = 15
    command     = /usr/sbin/ufw delete allow from %IP% to any port 51820 proto udp
    tcpflags    = syn
# WireGuard-Port schließen
sudo ufw delete allow 51820/udp

# Klopfen
knock SERVER 1111 2222 3333
sleep 2
sudo wg-quick up wg0-client

12. Fail2Ban und Intrusion Prevention

Fail2Ban blockiert IPs nach zu vielen fehlgeschlagenen Versuchen.

Installation

sudo apt install fail2ban

Konfiguration

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
# Ban-Zeit (Sekunden) - 1 Stunde
bantime = 3600

# Find-Zeit - Fenster für maxretry
findtime = 600

# Max Versuche
maxretry = 3

# Ignor-IPs (eigene IPs)
ignoreip = 127.0.0.1/8 10.8.0.0/24

# Ban-Action (iptables oder ufw)
banaction = ufw

# E-Mail-Benachrichtigung
destemail = admin@example.com
sendername = Fail2Ban
action = %(action_mwl)s

#
# SSH
#
[sshd]
enabled = true
port = 55222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400  # 24 Stunden

#
# Nginx
#
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3

[nginx-noscript]
enabled = true
port = http,https
filter = nginx-noscript
logpath = /var/log/nginx/access.log
maxretry = 6

[nginx-badbots]
enabled = true
port = http,https
filter = nginx-badbots
logpath = /var/log/nginx/access.log
maxretry = 2

[nginx-noproxy]
enabled = true
port = http,https
filter = nginx-noproxy
logpath = /var/log/nginx/access.log
maxretry = 2

#
# Custom: Wordpress
#
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 7200

Custom Filter - Wordpress

sudo nano /etc/fail2ban/filter.d/wordpress.conf
[Definition]
failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).*
ignoreregex =

Fail2Ban starten

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# Status
sudo fail2ban-client status

# Status einer Jail
sudo fail2ban-client status sshd

# IP manuell bannen
sudo fail2ban-client set sshd banip 192.0.2.100

# IP entbannen
sudo fail2ban-client set sshd unbanip 192.0.2.100

Logs überwachen

# Fail2Ban-Logs
sudo tail -f /var/log/fail2ban.log

# Gebannte IPs
sudo fail2ban-client status sshd

# Alle Jails
sudo fail2ban-client status

13. Monitoring und Alerting

Netdata - Live-Monitoring

# Installation
bash <(curl -Ss https://my-netdata.io/kickstart.sh)

# Zugriff (nur lokal)
# http://localhost:19999

# Oder über Nginx-Proxy mit Auth:
sudo nano /etc/nginx/sites-available/netdata
upstream netdata {
    server 127.0.0.1:19999;
}

server {
    listen 443 ssl http2;
    server_name monitor.example.com;
    
    # SSL...
    
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    location / {
        proxy_pass http://netdata;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Passwort-Datei erstellen:

sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd admin

Logging-Strategie

Zentrale Logs mit rsyslog:

sudo nano /etc/rsyslog.d/50-default.conf
# Alle Logs an zentralen Server
*.* @@10.0.0.50:514

Log-Analyse mit fail2ban

Bereits konfiguriert (siehe Kapitel 12).

Alerting mit Telegram

Script für Alerts:

sudo nano /usr/local/bin/telegram-alert.sh
#!/bin/bash

BOT_TOKEN="YOUR_BOT_TOKEN"
CHAT_ID="YOUR_CHAT_ID"
MESSAGE="$1"

curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
    -d chat_id="${CHAT_ID}" \
    -d text="${MESSAGE}" \
    -d parse_mode="HTML"
sudo chmod +x /usr/local/bin/telegram-alert.sh

Bei SSH-Login:

sudo nano /etc/ssh/sshrc
#!/bin/bash
/usr/local/bin/telegram-alert.sh "SSH Login: $USER from $SSH_CLIENT"

Bei Fail2Ban-Ban:

sudo nano /etc/fail2ban/action.d/telegram.conf
[Definition]
actionban = /usr/local/bin/telegram-alert.sh "Fail2Ban: <ip> banned in <name>"

14. Praktische Komplettszenarien

Szenario A: Einfacher Web-Server mit Cloudflare

Requirements:

  • Blog/Website öffentlich
  • Server-IP versteckt
  • DDoS-Schutz
  • SSL
  • Admin-Zugang sicher

Setup:

Internet
  ↓
Cloudflare (DDoS + CDN)
  ↓
Nginx (nur Cloudflare IPs)
  ↓
WordPress/App

Admin:
  VPN → SSH (Port 55222, nur VPN)

Schritte:

  1. Server härten (Kapitel 2)
  2. WireGuard einrichten (Kapitel 5)
  3. SSH nur über VPN (Kapitel 3)
  4. Nginx installieren (Kapitel 6)
  5. Cloudflare konfigurieren (Kapitel 7)
  6. Firewall: Nur Cloudflare IPs für 80/443 (Kapitel 4)
  7. Fail2Ban (Kapitel 12)

Szenario B: Minecraft-Server mit maximaler Sicherheit

Requirements:

  • Minecraft öffentlich erreichbar
  • DDoS-geschützt
  • Game-Server versteckt
  • Mehrere Server-Instanzen

Setup:

Spieler
  ↓
TCPShield
  ↓
Gate-Server (Velocity) - Bauernopfer
  ↓ WireGuard
Lobby-Server (10.8.0.10)
Survival-Server (10.8.0.11)

Admin:
  VPN → Bastion → Alle Server

Schritte:

  1. 3 Server mieten: Gate (billig), Game1, Game2
  2. WireGuard zwischen allen (Kapitel 5)
  3. Velocity auf Gate (Kapitel 8)
  4. Minecraft auf Game-Servern
  5. TCPShield einrichten (Kapitel 8)
  6. Firewall: Game-Server nur von Gate (Kapitel 4)
  7. Monitoring (Kapitel 13)

Szenario C: Homelab mit Nextcloud, Jellyfin, etc.

Requirements:

  • Mehrere Services
  • Von außen erreichbar
  • KEINE offenen Ports (Fritzbox/Router)
  • Admin-Zugang sicher

Setup:

Internet
  ↓
Cloudflare Tunnel (keine Ports!)
  ↓
Nginx Reverse Proxy
  ├→ Nextcloud
  ├→ Jellyfin
  └→ Home Assistant

Admin:
  Tailscale/WireGuard → Internes Netz

Schritte:

  1. Server im LAN
  2. Cloudflare Tunnel einrichten (Kapitel 7, 9)
  3. Nginx Reverse Proxy (Kapitel 6, 9)
  4. Services installieren
  5. Tailscale für Admin-Zugang (einfacher als WireGuard)
  6. Firewall: Alles deny außer localhost (Kapitel 4)

Szenario D: Multi-Tier mit Bastion

Requirements:

  • Web, App, DB getrennt
  • Nur Bastion öffentlich
  • Zero-Trust zwischen Servern

Setup:

Internet
  ↓
Bastion (SSH + VPN)
  ↓ Private Network
  ├→ Edge-Proxy (Nginx)
  ↓   ├→ App1
      ├→ App2
      └→ Database (nur von Apps)

Admin:
  VPN → Bastion → Jump zu jedem Server

Schritte:

  1. Bastion härten (Kapitel 2, 3, 10)
  2. Port-Knocking für SSH (Kapitel 11)
  3. WireGuard (Kapitel 5)
  4. Firewall: Alles deny, nur spezifische Verbindungen (Kapitel 4)
  5. Reverse Proxy mit mTLS zwischen Komponenten
  6. Monitoring zentral (Kapitel 13)