Verstecken und Absichern
Inhaltsverzeichnis
- Sicherheitskonzepte und Architekturen
- Server-Grundhärtung
- SSH absichern und verstecken
- Firewall-Konfiguration
- VPN-Gateway Setup (WireGuard)
- Reverse Proxy mit Nginx + DDoS-Schutz
- Cloudflare für Web-Services
- Minecraft/Gaming-Server Setup
- Self-Hosted Services im Homelab
- Bastion/Jump Server
- Port-Knocking
- Fail2Ban und Intrusion Prevention
- Monitoring und Alerting
- 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:
- Server härten (Kapitel 2)
- WireGuard einrichten (Kapitel 5)
- SSH nur über VPN (Kapitel 3)
- Nginx installieren (Kapitel 6)
- Cloudflare konfigurieren (Kapitel 7)
- Firewall: Nur Cloudflare IPs für 80/443 (Kapitel 4)
- 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:
- 3 Server mieten: Gate (billig), Game1, Game2
- WireGuard zwischen allen (Kapitel 5)
- Velocity auf Gate (Kapitel 8)
- Minecraft auf Game-Servern
- TCPShield einrichten (Kapitel 8)
- Firewall: Game-Server nur von Gate (Kapitel 4)
- 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:
- Server im LAN
- Cloudflare Tunnel einrichten (Kapitel 7, 9)
- Nginx Reverse Proxy (Kapitel 6, 9)
- Services installieren
- Tailscale für Admin-Zugang (einfacher als WireGuard)
- 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:
- Bastion härten (Kapitel 2, 3, 10)
- Port-Knocking für SSH (Kapitel 11)
- WireGuard (Kapitel 5)
- Firewall: Alles deny, nur spezifische Verbindungen (Kapitel 4)
- Reverse Proxy mit mTLS zwischen Komponenten
- Monitoring zentral (Kapitel 13)
No comments to display
No comments to display