Ich betreibe mehrere Websites und Dienste auf einem einzigen dedizierten Server – aber ich wollte nicht, dass dieser Server direkt am Internet hängt. Was ich wollte:
- Die Rechenleistung (und den Preis) eines dedizierten Root-Servers mit Proxmox VE.
- Einen einzigen, sauberen Interneteingang mit Cloud-Firewall, einem echten Router davor und VPN-Zugang – ohne dafür Spezialhardware zu mieten.
- DDoS-Schutz und TLS zentral an einer Stelle, nicht auf jedem Webserver einzeln.
- Internen Traffic, der das Hetzner-Rechenzentrum nie verlässt.
Herausgekommen ist eine gestaffelte Architektur: ein winziger Cloud-Server mit einem MikroTik Cloud Hosted Router (CHR) als Torwächter, per VXLAN direkt an das Software-Defined-Networking eines Proxmox-Dedicated-Servers gekoppelt. Dahinter ein HAProxy als Reverse Proxy, und erst danach die eigentlichen VMs.
Dieser Beitrag ist bewusst als Anleitung geschrieben: mit Diagrammen, echten Befehlen und – fast wichtiger – den Stolperfallen, die mich Nerven gekostet haben.
Hinweis zu den Adressen: Alle öffentlichen IPs, Schlüssel und MAC-Adressen in diesem Text sind Platzhalter aus den Dokumentations-Bereichen (RFC 5737 / RFC 3849). Ersetze sie durch deine eigenen. Das interne Netz
10.99.0.0/24kannst du übernehmen.
Inhaltsverzeichnis
- Die Architektur auf einen Blick
- Warum VXLAN und kein Hetzner vSwitch?
- Teil 1 – Der Cloud-Server & die Hetzner Cloud Firewall
- Teil 2 – MikroTik CHR installieren
- Teil 3 – Das VXLAN-Overlay aufbauen
- Teil 4 – Der CHR als DHCP, Gateway und NAT
- Teil 5 – Die grobe Firewall am CHR
- Teil 6 – VPN-Zugang per WireGuard
- Teil 7 – HAProxy: TLS, Routing und das Feintuning
- Die wichtigsten Stolperfallen
- Verifikation
- Fazit
1. Die Architektur auf einen Blick
Der Kerngedanke ist eine Zwiebel aus Schutzschichten: außen grob und billig, innen fein und teuer. Jede Schicht fängt ab, was die nächste gar nicht erst sehen soll.
INTERNET
│
▼
┌─────────────────────────────┐
│ Hetzner Cloud Firewall │ ← Schicht 1: lässt nur
│ (nur 80/443 TCP, 443 UDP, │ das Nötigste durch
│ SSH von Admin-IP) │
└──────────────┬──────────────┘
│
╔═════════════════════════▼═══════════════════════════╗
║ Hetzner Cloud · kleiner V-Server (CX/CPX) ║
║ ┌───────────────────────────────────────────────┐ ║
║ │ MikroTik CHR (RouterOS 7) │ ║ ← Schicht 2:
║ │ • ether1 = öffentliche IP (WAN) │ ║ grobe Firewall,
║ │ • NAT: 80/443 → HAProxy │ ║ NAT, DHCP,
║ │ • DHCP v4+v6, Gateway 10.99.0.1 │ ║ VPN-Konzentrator
║ │ • WireGuard-VPN nach Hause / weitere Netze │ ║
║ │ • VXLAN-Endpunkt (VNI 99) │ ║
║ └──────────────────────┬────────────────────────┘ ║
╚═════════════════════════╪═══════════════════════════╝
│ VXLAN (UDP 4789), MTU 1450
│ unverschlüsselt, aber DC-intern
╔═════════════════════════╪═══════════════════════════╗
║ Hetzner Robot · Dedicated Server mit Proxmox VE ║
║ ┌──────────────────────▼────────────────────────┐ ║
║ │ VXLAN-Endpunkt ⇄ Bridge vmbr99 (SDN) │ ║
║ └───┬───────────┬───────────┬───────────┬───────┘ ║
║ │ │ │ │ ║
║ ┌──▼──┐ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ║
║ │Admin│ │HAProxy│ │ Web 1 │ │ Web N │ … ║ ← Schicht 3+:
║ │ .100│ │ .101 │ │ .106 │ │ .10x │ ║ HAProxy = TLS,
║ └─────┘ └───┬───┘ └───────┘ └───────┘ ║ DDoS-Feintuning
║ │ routet nach Host/SNI ║ Web-VMs = Dienste
║ └────────► nginx / uvicorn / … ║
╚═════════════════════════════════════════════════════╝
alle im selben L2-Segment 10.99.0.0/24 · 2001:db8:97::/64Der Datenpfad einer eingehenden Anfrage (Mermaid – nur falls dein Blog Mermaid rendert, sonst gilt das ASCII-Bild oben):
flowchart LR
U[Besucher] --> HF[Hetzner Cloud FW]
HF -->|80/443| CHR[MikroTik CHR NAT + Rate-Limit]
CHR -->|dst-nat 10.99.0.101| VX{{VXLAN VNI 99}}
VX --> HAP[HAProxy VM TLS + Limits]
HAP -->|Host/SNI-Routing| W1[Web-VM nginx]
HAP --> W2[Web-VM uvicorn]Die Rollenverteilung:
| Komponente | Aufgabe |
|---|---|
| Hetzner Cloud Firewall | Erste, billigste Schicht. Wirft alles außer 80/443 (+SSH) weg. |
| MikroTik CHR | Router, grobe Firewall (per-IP-Limits), NAT, DHCP v4/v6, VPN-Konzentrator, VXLAN-Endpunkt. |
| Proxmox VE | Virtualisierung, stellt das VXLAN-Segment als Bridge für alle VMs bereit. |
| HAProxy-VM | TLS/Zertifikate, Host-/SNI-Routing, feingranulares Rate-Limiting, HTTP/3. |
| Web-VMs | Die eigentlichen Dienste, je Dienst eine VM. |
2. Warum VXLAN und kein Hetzner vSwitch?
Hetzner bietet mit dem vSwitch eine Möglichkeit, Robot-Server über VLANs zu verbinden. Warum stattdessen ein selbstgebautes VXLAN?
- Cloud und Robot sind zwei Welten. Hetzner-Cloud-Netzwerke und der Robot-vSwitch sprechen nicht nativ miteinander. Ich brauche aber genau diese Brücke: Cloud-CHR ⇄ Dedicated-Proxmox. VXLAN als Overlay über die öffentlichen IPs ist herstellerneutral und funktioniert zwischen beliebigen Endpunkten.
- Voller Durchgriff. Ich terminiere das Overlay selbst auf dem CHR und auf Proxmox und entscheide über VNI, MTU, DHCP und Routing – kein Hetzner-Automatismus dazwischen.
- Der Traffic bleibt im Rechenzentrum. Cloud-Server und Dedicated stehen bei Hetzner. Die VXLAN-Pakete laufen DC-intern. Deshalb ist die bewusste Entscheidung vertretbar, das Overlay unverschlüsselt zu fahren.
⚠️ Sicherheitshinweis: VXLAN hat keine Verschlüsselung. Wer dem DC-internen Pfad nicht traut, kapselt das VXLAN in einen WireGuard-Tunnel (VTEP-Adressen dann aus dem WireGuard-
/30). Das kostet etwas Durchsatz, MTU und CPU, ist aber die saubere Lösung für höhere Schutzbedarfe. Ich habe mich hier bewusst dagegen entschieden.
3. Teil 1 – Der Cloud-Server & die Hetzner Cloud Firewall
Der Router läuft auf einem kleinen Cloud-Server – er routet und filtert nur, er rechnet nichts. Ein CX22/CPX11 reicht locker.
- In der Hetzner Cloud Console ein Projekt anlegen, Server erstellen (Debian als Basis – wir überschreiben es gleich mit dem CHR-Image).
- Cloud Firewall anlegen und dem Server zuweisen. Eingehend erlauben:
| Richtung | Protokoll | Port | Quelle | Zweck |
|---|---|---|---|---|
| in | TCP | 80 | 0.0.0.0/0, ::/0 | HTTP |
| in | TCP | 443 | 0.0.0.0/0, ::/0 | HTTPS |
| in | UDP | 443 | 0.0.0.0/0, ::/0 | QUIC / HTTP/3 |
| in | UDP | 51820 | 0.0.0.0/0, ::/0 | WireGuard (VPN-Zugang) |
| in | UDP | 4789 | Proxmox-Public-IP | VXLAN (nur vom Dedi!) |
| in | TCP | 22 | deine-Admin-IP | SSH/Management (optional) |
Die UDP-4789-Regel nur für die IP des Dedicated-Servers freizugeben ist wichtig – sonst könnte jeder Pakete in dein Overlay injizieren.
4. Teil 2 – MikroTik CHR installieren
Der CHR ist RouterOS als Disk-Image für Virtualisierer/Cloud. Installation über das Hetzner-Rescue-System, indem wir das Raw-Image direkt auf die Systemplatte schreiben.
# Server im Rescue-Modus (Linux) starten, dann per SSH einloggen:
cd /tmp
wget https://download.mikrotik.com/routeros/7.21.5/chr-7.21.5.img.zip
unzip chr-7.21.5.img.zip
# ACHTUNG: /dev/sda ist die Systemplatte – das überschreibt ALLES.
dd if=chr-7.21.5.img of=/dev/sda bs=4M oflag=sync
rebootNach dem Reboot bootet RouterOS. Standard-Login: Benutzer admin, kein Passwort (sofort setzen!). Da der CHR die öffentliche IP per DHCP von Hetzner bekommt, ist er direkt per SSH/Winbox erreichbar.
# Zuerst absichern:
/user set admin password=EIN-STARKES-PASSWORT
/ip service disable telnet,ftp,www,api,api-ssl
/ip dhcp-client add interface=ether1 disabled=no # WAN-IP von Hetzner beziehen💡 CHR-Lizenz: Ohne Lizenz limitiert der CHR jedes Interface auf 1 Mbit/s. Für den Produktivbetrieb brauchst du mindestens eine p1-Lizenz (1 Gbit/s). Es gibt eine 60-Tage-Testlizenz (
p-unlimited) zum Ausprobieren.
5. Teil 3 – Das VXLAN-Overlay aufbauen
Jetzt die Brücke zwischen CHR und Proxmox. Wir nutzen Unicast-VXLAN mit statischem Remote-Endpunkt (VTEP) – kein Multicast, weil das über das Internet ohnehin nicht ginge.
Kenngrößen (auf beiden Seiten identisch):
| Parameter | Wert |
|---|---|
| VNI (VXLAN Network Identifier) | 99 |
| UDP-Port | 4789 |
| MTU | 1450 (1500 Underlay − 50 Byte VXLAN-Overhead) |
| CHR-VTEP (local) | z. B. 203.0.113.10 |
| Proxmox-VTEP (remote) | z. B. 198.51.100.20 |
5a. CHR-Seite (RouterOS)
/interface vxlan
add name=vxlan_proxmox vni=99 mtu=1450 local-address=203.0.113.10
/interface vxlan vteps
add interface=vxlan_proxmox remote-ip=198.51.100.20
# Der CHR bekommt die Gateway-Adressen im Overlay:
/ip address
add address=10.99.0.1/24 interface=vxlan_proxmox
/ipv6 address
add address=2001:db8:97::1 interface=vxlan_proxmox advertise=no5b. Proxmox-Seite (Software-Defined Networking)
Am elegantesten über das Proxmox SDN: Datacenter → SDN → Zones → Add → VXLAN.
- Zone:
vxlanz, Peers = beide VTEP-IPs (203.0.113.10,198.51.100.20), MTU1450. - VNet:
vmbr99, Zonevxlanz, Tag = 99 (das ist die VNI). - Anschließend Apply. VMs hängst du danach einfach an das VNet
vmbr99.
Wer es lieber transparent in /etc/network/interfaces hat – das ist exakt das, was das SDN im Hintergrund erzeugt:
auto vxlan99
iface vxlan99 inet manual
pre-up ip link add vxlan99 type vxlan id 99 dstport 4789 \
local 198.51.100.20 remote 203.0.113.10 nolearning
pre-up ip link set vxlan99 mtu 1450
up ip link set vxlan99 up
down ip link del vxlan99
auto vmbr99
iface vmbr99 inet manual
bridge-ports vxlan99
bridge-stp off
bridge-fd 0
mtu 1450Damit hängt auch der Proxmox-Host selbst am Overlay und kann mit allen VMs sprechen (praktisch fürs Deployment). Optional gibst du dem Host eine Adresse auf vmbr99.
🔧 MTU ist hier nicht verhandelbar. Underlay 1500 → VXLAN kostet 50 Byte → 1450. Setzt du die VM-Interfaces auf 1500, werden große Pakete still verschluckt (Blackholing): SSH-Login geht, aber ein
apt updateoder große HTTP-Responses hängen.
6. Teil 4 – Der CHR als DHCP, Gateway und NAT
Der CHR ist das Herz des Overlays: Er verteilt Adressen, ist Default-Gateway und macht das NAT nach außen.
6a. DHCP für IPv4
/ip pool
add name=dhcp_pool1 ranges=10.99.0.2-10.99.0.100
/ip dhcp-server
add name=dhcp1 interface=vxlan_proxmox address-pool=dhcp_pool1 lease-time=1w
/ip dhcp-server network
add address=10.99.0.0/24 gateway=10.99.0.1 dns-server=1.1.1.1,8.8.8.8
# Feste Adressen für die wichtigen VMs (per MAC gepinnt):
/ip dhcp-server lease
add address=10.99.0.100 mac-address=AA:BB:CC:00:01:00 server=dhcp1 comment="admin-pc"
add address=10.99.0.101 mac-address=AA:BB:CC:00:01:01 server=dhcp1 comment="haproxy"
add address=10.99.0.106 mac-address=AA:BB:CC:00:01:06 server=dhcp1 comment="web1"6b. DHCP für IPv6
/ipv6 pool
add name=v6pool prefix=2001:db8:97::/64 prefix-length=64
/ipv6 dhcp-server
add name=v6dhcp interface=vxlan_proxmox address-pool=v6pool prefix-pool=v6pool6c. NAT
/ip firewall nat
# Internet-Ausgang für alle internen Hosts:
add chain=srcnat action=masquerade out-interface=ether1
# Eingehend auf den HAProxy (10.99.0.101) umleiten:
add chain=dstnat action=dst-nat protocol=tcp dst-port=80 in-interface=ether1 to-addresses=10.99.0.101 to-ports=80
add chain=dstnat action=dst-nat protocol=tcp dst-port=443 in-interface=ether1 to-addresses=10.99.0.101 to-ports=443
add chain=dstnat action=dst-nat protocol=udp dst-port=443 in-interface=ether1 to-addresses=10.99.0.101 to-ports=443 # QUIC/HTTP-3IPv6 wird geroutet, nicht genattet – die VMs bekommen globale v6-Adressen aus deinem /64 und sind direkt erreichbar. Für den v6-Default am CHR:
/ipv6 route add dst-address=::/0 gateway=fe80::1%ether17. Teil 5 – Die grobe Firewall am CHR
Der CHR muss sich nur um 80/443 kümmern (Hetzner hat davor schon alles andere weggeworfen), und er muss nur grobe Fluten abfangen – das Feintuning macht später HAProxy. Deshalb liegen die Schwellen bewusst hoch (CGNAT-freundlich: hinter einer Mobilfunk-IP sitzen viele echte Nutzer).
IPv4-Filter
/ip firewall filter
# >200 gleichzeitige TCP-Verbindungen pro IP verwerfen (selbstheilend, kein Bann)
add chain=forward action=drop protocol=tcp dst-address=10.99.0.101 dst-port=80,443 \
connection-state=new connection-limit=200,32 comment="v4: max 200 gleichzeitig/IP"
# dasselbe für QUIC:
add chain=forward action=drop protocol=udp dst-address=10.99.0.101 dst-port=443 \
connection-state=new connection-limit=200,32 comment="v4 QUIC: max 200 gleichzeitig/IP"
# bereits geblockte Quellen sofort verwerfen:
add chain=forward action=drop src-address-list=proxy-flood comment="Blacklist-Drop"
# bis 150 neue Verbindungen/s pro IP durchlassen …
add chain=forward action=accept protocol=tcp dst-address=10.99.0.101 dst-port=80,443 \
connection-state=new dst-limit=150/1s,150,src-address/10s comment="Rate ok"
# … darüber für 1 h auf die Blacklist:
add chain=forward action=add-src-to-address-list protocol=tcp dst-address=10.99.0.101 \
dst-port=80,443 connection-state=new address-list=proxy-flood address-list-timeout=1hIPv6-Filter
/ipv6 firewall filter
add chain=forward action=drop protocol=tcp dst-address=2001:db8:97::c0de/128 \
dst-port=80,443 connection-state=new connection-limit=200,64 comment="v6: max 200 je /64"
add chain=forward action=drop protocol=udp dst-address=2001:db8:97::c0de/128 \
dst-port=443 connection-state=new connection-limit=200,64 comment="v6 QUIC: max 200 je /64"Warum IPv6 anders ist: Der zweite Wert bei connection-limit=200,64 ist die Netzmaske, auf die die Quelladresse gruppiert wird – hier /64, also ein Endkundenanschluss. Ohne diese Gruppierung würde ein Angreifer einfach Adressen in seinem eigenen /64 rotieren (davon hat er Milliarden) und jedes Limit umgehen. Und eine Rate-Blacklist wie bei v4 gibt es hier bewusst nicht: RouterOS‘ dst-limit klassifiziert nur nach voller /128, wäre also mit /64-Rotation wirkungslos. Das connection-limit mit /64-Gruppierung ist der passendere v6-Schutz.
🛑 Firewall-Änderungen IMMER im Safe Mode – und richtig beenden! Das ist die Falle, die mich am meisten gekostet hat. Details unten. Kurz:
Strg-Xrein, Regeln setzen/prüfen, zweitesStrg-Xraus (Meldung[Safe Mode taken off]). Erst dann sind die Regeln dauerhaft.
8. Teil 6 – VPN-Zugang per WireGuard
Der CHR ist auch mein VPN-Konzentrator: Von zu Hause und aus anderen Netzen komme ich über WireGuard direkt ins 10.99.0.0/24, ohne Ports nach außen zu öffnen.
/interface wireguard
add name=wg0 listen-port=51820 mtu=1420
/interface wireguard peers
add interface=wg0 name=home public-key="<PUBKEY-DES-CLIENTS>" \
allowed-address=10.10.255.30/32 persistent-keepalive=15s
/ip address
add address=10.10.255.29/30 interface=wg0Größere Standort-Kopplungen fahre ich über OSPF auf dem WireGuard-Link, damit Routen automatisch ausgetauscht werden – mit einem wichtigen Detail:
/routing ospf instance
add name=ospf1 originate-default=never redistribute=connected,static
/routing ospf area
add name=area1 instance=ospf1
/routing ospf interface-template
add area=area1 interfaces=wg0 type=ptp
# Verhindern, dass der CHR eine Default-Route vom Peer lernt und plötzlich
# seinen GESAMTEN Ausgangstraffic durch den Tunnel schickt:
/routing filter rule
add chain=ospf-in rule="if (dst==0.0.0.0/0) { reject }"Der Block_Default-Filter ist der Trick: Der Tunnel ist für interne Netze erreichbar, wird aber nie zum Default-Gateway des CHR. Sonst liefe dein kompletter Server-Ausgangstraffic durch die Gegenstelle.
9. Teil 7 – HAProxy: TLS, Routing und das Feintuning
Erst hinter dem CHR sitzt die VM, die die eigentliche Arbeit pro Anfrage macht: HAProxy auf 10.99.0.101. Er terminiert TLS, routet nach Hostname/SNI auf die richtige Web-VM und macht das feingranulare Rate-Limiting (Request-Raten, Fehlerraten, Slowloris) – alles, wofür der grobe CHR-Filter zu grob ist.
Minimal-Skelett (/etc/haproxy/haproxy.cfg):
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"
# Host-basiertes Routing über eine Map – WICHTIG: map_str, nicht map_dom!
use_backend %[req.hdr(host),lower,map_str(/etc/haproxy/maps/hosts.map)]
default_backend be_default
backend be_qr64
server s1 10.99.0.109:80
backend be_seekampf
server s1 10.99.0.108:8000hosts.map:
qr64.de be_qr64
seekampf.de be_seekampf
www.seekampf.de be_seekampfZertifikate hole ich per DNS-01-Challenge (Wildcard möglich, kein Port 80 nötig), z. B. mit certbot und dem passenden DNS-Plugin deines Providers. Neue Site = Eintrag in hosts.map + Backend + Zertifikat, das Frontend bleibt unangetastet.
Für QUIC/HTTP-3 in HAProxy noch zwei Pflicht-Details:
global
cluster-secret DEIN-GEHEIMNIS # sonst wird tune.quic....retry-threshold ignoriert
tune.quic.fe.sock-per-conn connection10. Die wichtigsten Stolperfallen
Das hier ist der Teil, den ich mir selbst vorher gewünscht hätte.
🔴 Safe Mode ohne Commit = alles weg
RouterOS‘ Safe Mode ist kein „Speichern“, sondern ein Rollback-Journal. Du betrittst ihn mit Strg-X (Prompt zeigt [Safe]), machst deine Änderungen – aber sie werden nur behalten, wenn du mit einem zweiten Strg-X sauber aussteigst (Meldung [Safe Mode taken off]). Schließt du vorher das Terminal oder reißt die Verbindung ab, macht RouterOS alle Änderungen der Sitzung rückgängig.
Genau das ist mir passiert: Ich hatte meine Firewall-Filter im Safe Mode importiert, getestet, alles lief – dann die Sitzung beendet, ohne zu committen. Wochen später fiel per /export auf, dass nur noch die NAT-Regeln (aus einer committeten Sitzung) da waren, die Filter aber spurlos verschwunden. Außerhalb von Safe Mode schreibt RouterOS sofort persistent – das Risiko existiert nur wegen des nicht-committeten Safe Mode.
Merke: Nach jeder Änderung erst print prüfen, dann zweites Strg-X. Und Persistenz nie an „die Regel ist gerade aktiv“ festmachen – Beleg ist erst ein frischer /export in einer neuen Sitzung (idealerweise nach Reboot).
🔴 MTU-Blackholing im Overlay
Vergisst du die MTU auf 1450 zu setzen, funktioniert der Login (kleine Pakete), aber große Transfers hängen. Symptom: ssh geht, apt update/große Downloads bleiben stehen. Auf allen Overlay-Interfaces (VXLAN, Bridge, VM-NIC) 1450 setzen.
🔴 map_dom ist unsicher fürs Host-Routing
In HAProxy matcht map_dom ein Label an beliebiger Stelle – qr64.de.boese-domain.de würde dann fälschlich bedient. Nimm map_str und trage jede Subdomain explizit in die Map ein.
🔴 VXLAN-Port am falschen Ort offen
UDP 4789 in der Hetzner Cloud Firewall nur für die IP des Dedicated-Servers freigeben, nicht für die Welt – sonst kann jeder Frames in dein L2-Segment einspeisen.
11. Verifikation
# Von außen: kommt HTTP/HTTPS durch die ganze Kette?
curl -I https://deine-domain.de
# HTTP/3 / QUIC prüfen (z. B. https://http3check.net) oder:
curl --http3 -I https://deine-domain.deAm CHR (RouterOS):
# Greifen die Filter? Trefferzähler statt Fremdlast:
/ip firewall filter print stats
/ipv6 firewall filter print stats
# Wer ist gerade geblockt?
/ip firewall address-list print where list=proxy-flood
# VXLAN-Endpunkt/Peer prüfen:
/interface vxlan print
/interface vxlan vteps printAuf Proxmox:
ip -d link show vxlan99 # id 99, dstport 4789, mtu 1450?
bridge fdb show dev vxlan99 # ist der remote-VTEP gelernt?
ping 10.99.0.1 # Gateway (CHR) erreichbar?12. Fazit
Die Architektur wirkt auf den ersten Blick nach viel – aber jede Schicht hat genau eine Aufgabe, und das macht sie robust und wartbar:
- Hetzner-Firewall wirft das Grobe weg,
- der MikroTik CHR ist Router, grobe Firewall, DHCP und VPN in einem – für ein paar Euro Cloud-Server plus Lizenz,
- VXLAN koppelt Cloud und Dedicated ohne Hersteller-Lock-in, mit DC-internem Traffic,
- Proxmox liefert die VMs,
- HAProxy macht das Feintuning, das eine Paket-Firewall nicht kann.
Das Ergebnis: ein einziger, gut kontrollierter Interneteingang vor beliebig vielen Diensten – und ein dedizierter Server, der nie direkt am Netz hängt. Nachbauen lohnt sich, wenn du mehrere Sites/Dienste sauber und sicher hinter einer Stelle bündeln willst.




16. Juli 2026 um 19:29 Uhr
Hallo Dennis,
das liest sich wirklich sehr gut. Allerdings frage ich mich gerade vielviel Wartungsarbeiten, etc. anfallen.
Grüße
Manfred
19. Juli 2026 um 22:11 Uhr
Der Mikrotik ist quasi Wartungsfrei.. das vxlan auch.. nur der Proxmox als Update. HAproxy macht selber das zertifkats renew.
22. Juli 2026 um 19:16 Uhr
Klasse Beschreibung. Kannst Du davon bitte ein Video machen?
Der HA-Proxy liegt als VM auf dem Proxmox?
26. Juli 2026 um 09:46 Uhr
Jo, der HA-Proxy liegt dann schon auf der Hardware.
8. August 2026 um 08:55 Uhr
Hallo Dennis, erst einmal vielen Dank für deine guten und wertvollen Inspirationen.
Eine Frage bleibt mir bei diesem Projekt: Warum führst du den Traffic über das WAN nach außen und über das WAN des Proxmox wieder herein (Hairpin über die öffentlichen IPs), statt ihn im privaten Netz zu halten?
Ich habe das bei mir über ein privates Hetzner-Cloud-Netz plus VXLAN gelöst. Ein reines L2-Segment über die Nodes hinweg wäre theoretisch am einfachsten, aber Hetzners privates Netz ist reines Layer 3 (kein Broadcast/Unknown-Unicast über die Nodes, MAC-Filter auf die zugewiesene NIC-Adresse) — ein knotenübergreifendes L2 trägt dort also nicht. Damit bleibt nur ein VXLAN-Overlay: MAC-in-UDP auf dem L3-Underlay, MTU entsprechend reduziert (1450 − 50 Byte Encapsulation = 1400). So läuft der VTEP-Transport komplett über das private Netz statt über WAN.
Ich vermute, dein Weg über WAN kommt daher, dass bei dir Proxmox auf einem Dedicated-Server läuft und du kein gemeinsames Cloud-Privatnetz zwischen CHR und Proxmox hast — dann bleibt dir als VTEP-Transport ja fast zwangsläufig die öffentliche Strecke. Liege ich da richtig?
Ein Problem habe ich aktuell noch: Die zweite (private) virtio-NIC bekomme ich am CHR nicht ans Laufen — sie bleibt auf „no-link“ (RouterOS 7.21.5, virtio-Treiber). Als Workaround habe ich das Edge-Routing derzeit mit VyOS statt CHR umgesetzt; dort wird die NIC sauber erkannt.
Viele Grüße
Philipp
8. August 2026 um 09:14 Uhr
Ich glaube da reden wir nur aneinander vorbei. Der Dedicated hat ja nur seine WAN Schnittstelle und diese ist mit SDN über VXLAN zu dem Mikrotik in der Cloud verbunden. Dann habe ich zwar die 50 MTU Verschnitt, aber lande am Ende bei 1450 und nicht 1400. Jeglicher Traffic wird immer über den Mikrotik in der Cloud geleitet.
8. August 2026 um 09:27 Uhr
Danke!
Fast aneinander vorbei 😉 Aber verstanden und genau, du hast am Dedi nur ein Interface. Dann ist der Weg nachvollziehbar und klar, dass du mit SDN über VXLAN gehst. Meine MTU Size kommt auf 1400 (leider) weil ich nicht Richtung Proxmox möchte sondern nach OpenStack und hier hängt Neutron noch dazwischen. Der kostet nochmal ein paar Bytes.
12. August 2026 um 07:26 Uhr
Hi Dennis,
hast du diesen Text mit KI geschrieben?
Der Satz mit „falls dein Blog Mermaid rendert“ ist irgendwie seltsam.
25. August 2026 um 00:03 Uhr
Würde das ganze auch mit einer OPNsense statt dem CHR funktionieren?