Ein häufiges Szenario bei Hetzner: Ein günstiger Cloud-vServer übernimmt die öffentliche Erreichbarkeit, während die eigentliche Rechenlast auf einem dedizierten Proxmox-Server im selben Rechenzentrum läuft. Das Problem dabei – Hetzners Cloud- und Robot-Produktlinien sprechen technisch nicht direkt miteinander. Ein Cloud-vSwitch bindet nur Cloud-Server ein, ein Root-Server bei Hetzner Robot bleibt außen vor. Wer beide Welten dennoch sauber verbinden will, baut sich die Brücke selbst: mit einem MikroTik CHR als Router auf dem Cloud-Server und einem VXLAN-Overlay-Tunnel zum Proxmox-Host. Diesen Aufbau zeigen wir hier Schritt für Schritt – von der Firewall bis zur fertigen TLS-Terminierung per HAProxy.
Warum VXLAN statt Hetzner vSwitch
Ein selbstverwaltetes VXLAN-Overlay hat gegenüber dem proprietären vSwitch mehrere Vorteile: Es funktioniert produktübergreifend zwischen Cloud und dedizierter Hardware, lässt Ihnen die volle Kontrolle über VNI, MTU, DHCP und Routing, und der Traffic verlässt dabei nie das Rechenzentrumsnetz. Unverschlüsseltes VXLAN ist in diesem Rahmen vertretbar, weil der Datenverkehr intern bleibt – wer zusätzliche Absicherung möchte, kapselt den VXLAN-Traffic in einen WireGuard-Tunnel, muss dafür aber MTU-Verluste und etwas mehr CPU-Last einplanen.
Architektur im Überblick
Der Traffic durchläuft mehrere Schichten, jede mit einer klar abgegrenzten Aufgabe:
- Hetzner Cloud Firewall: erste Filterstufe, lässt nur die tatsächlich benötigten Ports passieren
- MikroTik CHR: Routing, grobe Firewall, DHCP/NAT, VPN-Konzentrator und VXLAN-Endpunkt
- VXLAN-Overlay: Layer-2-Tunnel zwischen Cloud-Server und Proxmox-Host
- Proxmox-Bridge: bindet die VMs an das Overlay-Netz an
- HAProxy: TLS-Terminierung, host-basiertes Routing, feingranulares Rate-Limiting
Als Beispielnetz verwenden wir in diesem Artikel die Dokumentations-Adressbereiche
203.0.113.0/24 und 198.51.100.0/24 (RFC 5737) für die öffentlichen IPs sowie
10.20.30.0/24 für das interne Overlay – in der Praxis ersetzen Sie diese natürlich durch Ihre
tatsächlich zugewiesenen Adressen.
Schritt 1: Hetzner Cloud Firewall vorbereiten
Für den Cloud-Server genügt eine kleine Instanz (CX22 reicht) – sie routet und filtert nur, sie trägt keine Rechenlast. Wichtig ist die Firewall-Konfiguration, denn sie ist die erste Verteidigungslinie:
Eingehend TCP 80 0.0.0.0/0, ::/0 HTTP
Eingehend TCP 443 0.0.0.0/0, ::/0 HTTPS
Eingehend UDP 443 0.0.0.0/0, ::/0 QUIC / HTTP-3
Eingehend UDP 51820 0.0.0.0/0, ::/0 WireGuard
Eingehend UDP 4789 198.51.100.12/32 VXLAN – NUR von der Proxmox-IP!
Eingehend TCP 22 <Ihre Admin-IP> SSH-Management
Der VXLAN-Port 4789/UDP ist der sensibelste Eintrag: Steht er offen für 0.0.0.0/0, kann grundsätzlich jeder Layer-2-Frames in Ihr Overlay-Netz einschleusen. Er gehört ausschließlich auf die öffentliche IP des Proxmox-Servers beschränkt.
Schritt 2: MikroTik CHR auf dem Cloud-Server installieren
RouterOS gibt es nicht direkt als Hetzner-Image – der Cloud-Server wird stattdessen über das Hetzner-Rescue-System mit dem CHR-Image überschrieben. Die einzelnen Schritte und die Absicherung direkt nach dem ersten Boot beschreiben wir ausführlich in MikroTik CHR auf Hetzner Cloud installieren, hier die Kurzfassung:
# Im Rescue-System (Linux) per SSH:
wget https://download.mikrotik.com/routeros/7.21.5/chr-7.21.5.img.zip
gunzip -c chr-7.21.5.img.zip > chr.img 2>/dev/null || unzip chr-7.21.5.img.zip
dd if=chr-7.21.5.img of=/dev/sda bs=4M oflag=sync
# danach den Server neu starten – er bootet jetzt RouterOS
Nach dem ersten Login (Standard: Benutzer admin, kein Passwort) sofort ein starkes Passwort setzen und
nicht benötigte Dienste deaktivieren:
/ip dhcp-client add interface=ether1 disabled=no
/ip service disable telnet,ftp,www,api,api-ssl
Ohne Lizenz drosselt CHR sämtliche Interfaces auf 1 Mbit/s – für den Produktivbetrieb ist mindestens eine p1-Lizenz (1 GBit/s) nötig. Für erste Tests reicht die 60 Tage gültige Testlizenz.
Schritt 3: Die VXLAN-Bridge aufbauen
Beide Tunnelenden benötigen identische Parameter: dieselbe VNI, denselben UDP-Port und dieselbe MTU. Da der VXLAN-Header rund 50 Byte belegt, setzen wir die Tunnel-MTU bei einer 1500-Byte-Strecke auf 1450 – und zwar konsequent auf allen drei Ebenen: VXLAN-Interface, Bridge und jeder einzelnen VM-Netzwerkkarte.
Auf dem MikroTik CHR:
/interface vxlan
add name=vxlan-proxmox vni=200 mtu=1450 local-address=203.0.113.45
/interface vxlan vteps
add interface=vxlan-proxmox remote-ip=198.51.100.12
/ip address
add address=10.20.30.1/24 interface=vxlan-proxmox
/ipv6 address
add address=2001:db8:20:30::1/64 interface=vxlan-proxmox advertise=no
Auf dem Proxmox-Host geht es am komfortabelsten über das eingebaute SDN-Modul (Datacenter → SDN
→ Zones → VXLAN-Zone anlegen, Peer-IP und MTU eintragen, anschließend ein VNet mit passendem VNI-Tag erstellen).
Wer es lieber klassisch per Konfigurationsdatei mag, trägt es direkt in /etc/network/interfaces ein:
auto vxlan200
iface vxlan200 inet manual
pre-up ip link add vxlan200 type vxlan id 200 dstport 4789 \
local 198.51.100.12 remote 203.0.113.45 nolearning
pre-up ip link set vxlan200 mtu 1450
up ip link set vxlan200 up
down ip link del vxlan200
auto vmbr200
iface vmbr200 inet manual
bridge-ports vxlan200
bridge-stp off
bridge-fd 0
mtu 1450
Typischer Stolperstein: Bleibt irgendwo die MTU auf 1500 stehen, äußert sich das tückisch – SSH-Sitzungen
funktionieren weiterhin einwandfrei (kleine Pakete), aber größere Downloads oder TLS-Handshakes mit großen Zertifikatsketten
hängen scheinbar grundlos. Nach der Einrichtung lohnt ein Blick mit ip -d link show vxlan200, ob MTU und VNI
tatsächlich überall übernommen wurden.
Schritt 4: Routing, DHCP und NAT auf der CHR
/ip pool
add name=dhcp-pool1 ranges=10.20.30.50-10.20.30.200
/ip dhcp-server
add name=dhcp1 interface=vxlan-proxmox address-pool=dhcp-pool1 lease-time=1w
/ip dhcp-server network
add address=10.20.30.0/24 gateway=10.20.30.1 dns-server=1.1.1.1,9.9.9.9
# Feste Adressen für zentrale VMs per MAC-Bindung
/ip dhcp-server lease
add address=10.20.30.10 mac-address=AA:BB:CC:00:00:10 server=dhcp1 comment="admin-vm"
add address=10.20.30.20 mac-address=AA:BB:CC:00:00:20 server=dhcp1 comment="haproxy"
add address=10.20.30.30 mac-address=AA:BB:CC:00:00:30 server=dhcp1 comment="web1"
/ip firewall nat
add chain=srcnat action=masquerade out-interface=ether1
add chain=dstnat action=dst-nat protocol=tcp dst-port=80 in-interface=ether1 to-addresses=10.20.30.20 to-ports=80
add chain=dstnat action=dst-nat protocol=tcp dst-port=443 in-interface=ether1 to-addresses=10.20.30.20 to-ports=443
add chain=dstnat action=dst-nat protocol=udp dst-port=443 in-interface=ether1 to-addresses=10.20.30.20 to-ports=443
IPv6 lassen wir bewusst geroutet statt NAT’iert – die VMs erhalten dadurch eigene global gültige Adressen und sind direkt aus dem Internet erreichbar, was insbesondere Fehlersuche und Monitoring erheblich vereinfacht.
Schritt 5: Grobe Firewall-Regeln auf der CHR
Die Feinarbeit – etwa Rate-Limiting pro URL – übernimmt später HAProxy. Auf Router-Ebene reicht ein grobes Netz gegen offensichtliche Flut-Angriffe, mit Schwellwerten, die auch Nutzer hinter Firmen-NAT nicht versehentlich aussperren:
/ip firewall filter
add chain=forward action=drop protocol=tcp dst-address=10.20.30.20 dst-port=80,443 \
connection-state=new connection-limit=100,32 comment="max. 100 gleichzeitige Verbindungen je Quell-IP"
add chain=forward action=accept protocol=tcp dst-address=10.20.30.20 dst-port=80,443 \
connection-state=new dst-limit=100/1s,100,src-address/10s comment="max. 100 neue Verbindungen/s je Quelle"
add chain=forward action=add-src-to-address-list protocol=tcp dst-address=10.20.30.20 \
dst-port=80,443 connection-state=new address-list=flood-blocklist address-list-timeout=1h \
comment="Quelle bei Überschreitung 1h automatisch sperren"
add chain=forward action=drop src-address-list=flood-blocklist comment="Sperrliste anwenden"
Bei IPv6 lohnt sich eine Gruppierung nach /64 statt nach einzelner Adresse – sonst kann ein Angreifer
Limits durch Adressrotation innerhalb seines eigenen Präfixes einfach umgehen.
Wichtige Falle beim Testen von Firewall-Regeln: Arbeiten Sie über eine per RouterOS-Regel potenziell
betroffene Verbindung, aktivieren Sie vorher den Safe Mode (Strg+X, Prompt zeigt [Safe]).
Erst ein sauberes zweites Strg+X übernimmt die Änderungen dauerhaft – bricht die Sitzung vorher ab,
werden sämtliche Änderungen automatisch zurückgerollt. Nach jeder Sitzung lohnt ein /export in einer neuen
Verbindung, um sicherzugehen, dass die Regeln wirklich persistent sind.
Schritt 6: WireGuard als Fernzugriff
Für den administrativen Zugriff auf das interne Netz, ohne dafür Ports öffentlich freizugeben, dient WireGuard als VPN-Konzentrator auf der CHR:
/interface wireguard
add name=wg-remote listen-port=51820 mtu=1420
/interface wireguard peers
add interface=wg-remote name=admin-notebook public-key="<CLIENT-PUBLIC-KEY>" \
allowed-address=10.40.50.2/32 persistent-keepalive=15s
/ip address
add address=10.40.50.1/30 interface=wg-remote
Die Interface-MTU liegt bewusst 30 Byte unter der Overlay-MTU (1420 statt 1450), um Platz für den WireGuard-eigenen Verkapselungs-Overhead zu lassen – wird das übersehen, entsteht dieselbe Art von stillem Paketverlust wie beim VXLAN-MTU-Problem oben, nur eine Ebene tiefer.
Wer mehrere Standorte dauerhaft über WireGuard koppeln möchte, kann zusätzlich OSPF für das automatische Lernen
von Routen aktivieren. Dabei unbedingt eine Filterregel setzen, die verhindert, dass ein Remote-Standort versehentlich
eine Default-Route (0.0.0.0/0) einspeist – sonst würde plötzlich der gesamte ausgehende Traffic der CHR
durch den VPN-Tunnel laufen:
/routing filter rule
add chain=ospf-in rule="if (dst==0.0.0.0/0) { reject }"
Schritt 7: HAProxy übernimmt TLS und Routing
HAProxy sitzt als letzte Schicht vor den eigentlichen Backend-VMs, terminiert TLS und leitet anhand des Hostnamens weiter:
frontend fe_https
bind :443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
bind quic4@:443 ssl crt /etc/haproxy/certs/ alpn h3
bind quic6@:::443 ssl crt /etc/haproxy/certs/ alpn h3
http-after-response set-header alt-svc "h3=\":443\"; ma=86400"
use_backend %[req.hdr(host),lower,map_str(/etc/haproxy/maps/hosts.map)]
default_backend be_default
backend be_web1
server s1 10.20.30.30:80
backend be_web2
server s1 10.20.30.31:8000
Die Zuordnungsdatei hosts.map listet jede erlaubte Domain explizit auf:
kunde-a.de be_web1
www.kunde-a.de be_web1
kunde-b.de be_web2
www.kunde-b.de be_web2
Sicherheitsrelevantes Detail: Unbedingt map_str statt map_dom verwenden.
map_dom matcht Domain-Labels an beliebiger Position – damit würde eine Regel für kunde-a.de
auch auf kunde-a.de.angreifer-domain.com zutreffen. map_str vergleicht dagegen den kompletten
Host-Header exakt und schließt diese Lücke.
Für HTTP/3 per QUIC braucht es zusätzlich zwei globale Einstellungen, ohne die die QUIC-Performance spürbar leidet bzw. der Retry-Mechanismus gar nicht greift:
global
cluster-secret <ZUFAELLIGER-SCHLUESSEL>
tune.quic.fe.sock-per-conn connection
Verifikation
Nach dem Aufbau lohnt sich ein systematischer Check von außen und von innen:
# Von extern:
curl -I https://kunde-a.de
curl --http3 -I https://kunde-a.de
# Auf der CHR:
/interface vxlan vteps print
/ip firewall filter print stats
# Auf Proxmox:
ip -d link show vxlan200
bridge fdb show dev vxlan200
ping 10.20.30.1
Stolperfallen im Überblick
- Safe Mode nicht sauber beendet: Regeln aus einer abgebrochenen Safe-Mode-Sitzung existieren beim nächsten Login nicht mehr.
- MTU nicht überall auf 1450: führt zu stillem Paketverlust bei größeren Paketen – SSH läuft, Downloads hängen.
- VXLAN-Port zu offen: UDP 4789 muss auf die Proxmox-IP beschränkt bleiben, sonst kann jeder Frames einschleusen.
map_domstattmap_str: öffnet Tür und Tor für Subdomain-Spoofing im HAProxy-Routing.- OSPF-Default-Route-Leck: ohne Filterregel kann ein Remote-Peer versehentlich zur neuen Default-Route werden.
- WireGuard-MTU vergessen: ohne Abzug für den WireGuard-Overhead entsteht dieselbe MTU-Falle wie beim VXLAN, nur getunnelt.
Fazit
Ein Hetzner Cloud-vServer als schlanke Firewall- und Routing-Instanz vor einem leistungsstärkeren dedizierten Proxmox-Server ist eine kosteneffiziente und flexible Architektur – sie erfordert aber sauberes Netzwerk-Handwerk über mehrere Schichten hinweg. Von der MTU-Kette über die Firewall-Segmentierung bis zum HAProxy-Routing steckt der Teufel im Detail. Genau solche mehrschichtigen Netzwerk- und Hosting-Architekturen setzen wir bei K&C NetFox regelmäßig für Kunden um – sprechen Sie uns an, wenn Sie eine vergleichbare Anbindung planen oder eine bestehende Lösung absichern möchten.