Zero Trust Hosting: Sicherheit ohne VPNs — Moderner Zugriffsschutz
"Trust but verify" ist tot. Zero Trust heisst: Nichts und niemand ist vertrauenswürdig — nicht mal innerhalb des eigenen Netzwerks. Jeder Zugriff wird verifiziert, jede Verbindung verschlüsselt, jeder User kontextbasiert berechtigt. Für Hosting-Infrastruktur bedeutet das: weg vom VPN, hin zu Identity-Aware Proxies und mTLS.
Warum VPNs nicht mehr reichen
Das traditionelle VPN modelliert ein internes Netzwerk als "sicher" und die Außenwelt als "unsicher". Das ist ein Irrtum:
- Flat Networks: Wer einmal im VPN ist, hat Zugriff auf ALLE Netzwerkressourcen. Ein kompromittierter Laptop = Einbruch in das gesamte Netz.
- Overprivileged: Mitarbeiter bekommen oft dauerhaften Vollzugriff, auch wenn sie nur eine spezifische Ressource brauchen.
- No Context: VPNs prüfen keine Geräte-Sicherheit, keine Identity, keine Standort-bezogene Risk-Scores.
- Single Point of Failure: Ein VPN-Exploit → gesamtes Netz offengelegt. Auch bei MFA-MVPN.
Googles BeyondCorp (ab 2011, public seit 2014) war der erste großflächige Beweis: Zero Trust funktioniert production-scale. Seither hat sich das Modell zur Branchenpraxis entwickelt.
Was VPNs noch gut können: Site-to-Site-Konnektivität zwischen fixed Netzwerken (z.B. Büro ↔ Rechenzentrum). Für diesen Use Case sind WireGuard/OpenVPN immer noch sinnvoll. Für User-Zugriff auf Anwendungen? Zero Trust ist die bessere Lösung.
Die 3 Kernprinzipien von Zero Trust
1. Verify Explicitly
Jede Zugriffsanfrage wird mit allen verfügbaren Daten verifiziert: Identity (Wer?), Device (Von welchem Gerät?), Location (Wo?), Context (Zu welcher Zeit? Von welcher App?), Access Policy (Welche Berechtigungen?). Minimum: Multi-Faktor-Authentifizierung + Device Compliance.
2. Use Least-Privilege Access
Nutzer bekommen nur so viel Zugriff, wie sie für ihre aktuelle Aufgabe brauchen — nicht mehr. JIT (Just-in-Time) Access: Rechte werden nur für die Dauer der Aufgabe gewährt und danach automatisch entzogen.
3. Assume Breach
Designe das System so, dass ein kompromittierter User oder ein durchschnittlicher Angreifer möglichst wenig Schaden anrichten kann. Segmentierung, Micro-Segmentation, Encrypted Traffic Everywhere, Monitoring auf every anomaly.
Architecture: Identity-Aware Proxy (IAP)
Ein IAP sitzt vor jeder Anwendung und prüft: Wer bist du? Ist dein Gerät compliant? Hast du Berechtigung für diese spezifische Ressource? Erst dann wird der Request durchgelassen.
# Cloudflare Access — Application Access Policy
# Schützt admin.example.com ohne VPN
# Nur User mit genehmigtem IdP + kompatiblem Gerät
# via Terraform (empfohlen)
resource "cloudflare_access_application" "admin_panel" {
account_id = var.cloudflare_account_id
name = "Admin Panel"
domain = "admin.example.com"
session_duration = "24h"
# Policy: nur User mit corporate email + managed device
policy {
name = "Engineering Team"
precedence = 1
include {
email_domain = ["example.com"]
}
exclude {
# Externe Contractor
email_domain = ["contractor.io"]
}
require {
# Device Posture: nur verwaltete Geräte (MDM required)
device_posture = ["corp-managed-device"]
}
approval_group = ["security-team@example.com"] # JIT approval
}
}mTLS: Mutual TLS für Service-to-Service-Kommunikation
Tradtionelles TLS: Client verifiziert Server. mTLS: BEIDE Seiten verifizieren sich gegenseitig. Jeder Service hat ein eigenes Zertifikat, ausgestellt von einer internen CA. Keine Verbindung möglich ohne valid cert.
# Service Mesh: envoy + SPIFFE/SPIRE für automatische mTLS-Zertifikate
# SPIRE = SPIFFE Runtime Environment — automatische Zertifikats-Rotation
# Jeder Pod bekommt automatisch ein X.509-SVID (SPIFFE Verifiable Identity Document)
# envoy sidecar config (envoy.yaml)
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 8443
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: webapp
http_filters:
- name: envoy.filters.http.router
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: true # mTLS: Client-Zert erforderlich
common_tls_context:
tls_certificate_spath:
certificate_chain:
filename: /etc/certs/tls.crt
private_key:
filename: /etc/certs/tls.key
validation_context:
trusted_ca:
filename: /etc/certs/ca.crt
# SPIFFE-kompatible Validierung
subject_alt_name_match:
- san: "spiffe://cluster.local/ns/production/sa/webapp"Tailscale: VPN-Reboot als WireGuard-Mesh
Tailscale ist ein WireGuard-basiertes Mesh-VPN, das层层 VPNs obsolet macht. Kein zentraler Gateway, kein Flaschenhals. Jeder Node bekommt eine WireGuard-Identität und kann direkt mit anderen Nodes komunizieren.
# Tailscale installieren (Server)
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --accept-routes --advertise-exit-node
# Tailscale installieren (Laptop/Desktop)
# → Download von tailscale.com, Login mit GitHub/Google SSO
# Ergebnis: Alle Geräte in einem privaten Overlay-Netz
# 10.100.x.x Adressen, NAT-Traversal via DERP-Server wenn kein direkter Weg
# Keine Port-Forwarding, kein Port-Open auf dem Router
# SSH via Tailscale (Taildrop, Tailscale SSH)
tailscale status
# → Alle Geräte im Netz mit ihren Tailscale-IPs
# SSH auf Server: ssh admin@100.64.x.x (kein VPN-Client nötig!)
# Dateitransfer: tailscale file transfer
# ACL Policy: Wer darf auf was?
# devices-policy.hujson
{
"acls": [
{
"action": "accept",
"src": ["group:engineering"],
"dst": ["tag:production:22,443,5432"],
},
{
"action": "accept",
"src": ["group:contractor"],
"dst": ["tag:staging:22,443"],
},
],
"tagOwners": {
"tag:production": ["group:security"],
"tag:staging": ["group:engineering"],
},
"groups": {
"group:engineering": ["user@example.com"],
"group:contractor": ["contractor@external.io"],
},
}Cloudflare Access vs. Tailscale vs. HashiCorp Boundary
| Kriterium | Cloudflare Access | Tailscale | HashiCorp Boundary |
|---|---|---|---|
| Modell | Identity-Aware Proxy (Layer 7) | WireGuard Mesh (Layer 3) | SSH/HTTP Proxy + Vault-Integration |
| Zugriff auf | Web-Apps, SSH, RDP, Kubernetes | Alle Ports/Protokolle | SSH, RDP, Database, Kubernetes |
| Device Compliance | Ja (CrowdStrike, Jamf, Kolide, etc.) | Basic (OS detection) | Nein |
| IdP-Integration | Okta, Azure AD, Google, GitHub, SAML | GitHub, Google, Okta (über IdP) | Vault Identity (OIDC/SAML) |
| mTLS | Client-Zert + Cloudflare CA | WireGuard + optional mTLS | Workload Identity (Vault PKI) |
| Netzwerk | Cloudflare Edge (global) | Peer-to-peer, DERP-Relay | Hub-Spoke, zentral |
| Eigenes Netzwerk | Cloudflare Tunnel (kein Inbound-Port) | Exit Nodes (optional) | Worker + Controller |
| Preis | Free: 1 App, 50 User; $100/Monat Unlimited | Free: 100 Geräte; $25/Monat pro User | Free (OSS); Cloud: $0.20/std + $0.10/user |
| Best für | Web-Apps + Browser-basiertes SSH/RDP | Globale Netze + Developers | Database-Zugriff, Compliance-Audit |
Zero Trust für typische Hosting-Szenarien
Szenario 1: Admin-Panel ohne VPN (Cloudflare Access)
# Cloudflare Tunnel: keine inbound Ports, kein Firewall-Rule nötig
cloudflared service install
# tunnel.yaml — Connection zum Cloudflare Edge, kein öffentlicher Port
tunnel: <TUNNEL_ID>
credentials-file: /var/lib/cloudflared/credentials.json
ingress:
- hostname: admin.example.com
service: https://localhost:8443
originRequest:
caPool: /etc/ssl/certs/company-ca.crt
- hostname: api.example.com
service: https://localhost:3000
- service: http_status:404
# Ergebnis: admin.example.com erreichbar
# Cloudflare terminiert TLS + Auth
# Dein Server: nur localhost-Verbindungen, kein öffentlicher PortSzenario 2: SSH-Zugriff ohne offene Ports (Tailscale SSH)
# Tailscale SSH — SSH ohne offene Port 22
# Server: tailscale up --ssh
# Client: tailscale up --ssh
# SSH auf Server (kein VPN-Client, kein Port 22)
ssh admin@webserver-1
# Tailscale übernimmt Auth + Routing
# User muss in Tailscale org sein, IdP-authentifiziert
# Zugriff auf Server: nur für User mit Tailscale-Identität
# Für Contractor mit begrenztem Zugriff:
tailscale serve https://localhost:22 --bg
# oder: tailscale ssh --exit-node=workstationSzenario 3: Database-Zugriff mit Zero Trust (Boundary)
# HashiCorp Boundary: Database-Access ohne direkte Verbindung
boundary authenticate oidc -scope-name "corp"
# Session zu Postgres-Cluster starten (nur mit Berechtigung)
boundary connect -target-name "prod-postgres" -scope-name "prod"
# Boundary öffnet einen lokalen Port (z.B. 54321)
# Client verbindet sich via localhost:54321
# Connection geht durch Boundary-Worker, authentifiziert via Vault
# Keine Firewall-Port-Öffnung nötig, kein direkter DB-Port offen
# Vault integriert sich für dynamische DB-Credentials:
# Jede Session bekommt temporäre, gescopte DB-Credentials
# Session endet → Credentials werden automatisch widerrufenNetwork Policies: Micro-Segmentation
Zero Trust Network Policies definieren explizit, wer mit wem reden darf. Alles andere ist blockiert.
# Kubernetes NetworkPolicy — Default: Deny All
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Explizite Allow: Frontend → API
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 3000
---
# Explizite Allow: API → Postgres
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 5432Micro-Segmentation ist der Schlüssel. Standard-Kubernetes erlaubt alle Pod-Pod-Kommunikation per Default. Eine kompromittierte Frontend-Pod könnte direkt auf die Datenbank zugreifen. Network Policies + mTLS = selbst wenn ein Pod gehackt ist, kommt er nicht weiter als erlaubt.
Implementierung: Schritt-für-Schritt Zero Trust Stack
Phase 1: Identity + Device Compliance (Woche 1-2)
- Alle User über IdP (Okta/Azure AD) authentifiziert
- MFA erzwungen für alle User, auch interne
- Device Compliance: MDM (Jamf/Intune), Endpoint Protection
- Cloudflare Access oder Tailscale für VPN-Ersatz
Phase 2: Application Layer (Woche 3-4)
- Cloudflare Tunnel für alle HTTP/S-Apps (kein Port 443 offen)
- Access Policies: Wer darf auf welche App, von wo, mit welchem Gerät
- Alle Admin-Panels hinter Access Policy
Phase 3: Service Mesh + Micro-Segmentation (Woche 5-6)
- mTLS im Kubernetes-Cluster (Linkerd oder Istio, oder Cilium)
- Network Policies für alle Namespaces
- Service-to-Service-Auth: nur authorisierte Services dürfen reden
Phase 4: Monitoring + Incident Response (Woche 7-8)
- Zugriffs-Logs zentral: Cloudflare Logs, Tailscale audit logs, Kubernetes audit
- SIEM-Regel: Anomaler Zugriff von neuem Standort → Alert
- Quarterly Access Review: Wer hat noch Zugriff?
Zero Trust Spickzettel: Deine Checkliste
- Kein implicit Trust. Jede Verbindung wird verifiziert — auch intern. "Internal Network" ist kein Trust-Faktor.
- Cloudflare Access = einfachster Einstieg für Web-Apps. Cloudflare Tunnel + Access Policies = kein öffentlicher Port, kein VPN.
- Tailscale = bestes VPN-Ersatz für Developers. Peer-to-Peer-Mesh, Identity-basiert, kein Gateway-Flaschenhals.
- mTLS + Service Mesh = Kubernetes-interner Zero Trust. Linkerd oder Cilium, mit Network Policies kombiniert.
- Least Privilege = selbst wenn ein User-Account kompromittiert ist, ist der Schaden begrenzt auf die minimal nötigen Ressourcen.
- Assume Breach → monitore anomalous Logins, device posture changes, unusual network patterns. Alert bei every deviation.
- JIT Access statt dauerhafte Berechtigungen. Dev braucht Production-Zugriff? Genehmigung via Access Request → temporär 2h → automatisch entzogen.
- Micro-Segmentation: Kubernetes NetworkPolicy + Service Mesh. Ein kompromittierter Pod kommt nicht weiter als seine explizite Erlaubnis erlaubt.
- Alle Logins werden geloggt und auditiert. Compliance-Anforderung und Security-Asset gleichzeitig.