11 GB Restore über OpenVPN. Geschätzte Restzeit: 45 Minuten. Bei 3 MB/s. Im Jahr 2026.

Der Proxmox Backup Server steht am Remote-Standort, verbunden über eine pfSense mit WireGuard Site-to-Site. Aber der Proxmox-Hypervisor selbst hängt noch an einem OpenVPN-Tunnel. Single-Threaded. Userspace. MSS 1208 Bytes. Das ist kein Tuning-Problem — das ist ein architektonisches Limit.


Das Setup

Hypervisor (Hetzner)          pfSense Gateway           Remote-Standort
┌──────────────┐              ┌──────────────┐          ┌──────────────┐
│ srv-r2d2     │──OpenVPN────►│ gw-obiwan    │──WG─────►│ gw-yoda      │
│ Proxmox VE   │  tun0        │ pfSense 2.8  │ tun_wg0  │ pfSense      │
│              │  3 MB/s 😩   │ :51820       │          │ 172.20.x.x   │
└──────────────┘              └──────────────┘          └──────────────┘
                                                         │
                                                         ▼
                                                        PBS (172.20.20.4)

Der pfSense-Gateway hat bereits einen funktionierenden WireGuard Site-to-Site-Tunnel zum Remote-Standort. Nur der Hypervisor hängt noch am OpenVPN-Tropf.

Ziel: Hypervisor als neuen WireGuard-Peer auf die pfSense bringen. OpenVPN ablösen.


Die Migration in 5 Schritten

Schritt 1: WireGuard auf dem Hypervisor

apt-get install -y wireguard-tools
mkdir -p /etc/wireguard && chmod 700 /etc/wireguard
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
chmod 600 /etc/wireguard/private.key
cat /etc/wireguard/public.key  # Notieren!

Config erstellen:

# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <dein-private-key>
Address = 10.69.69.3/32

[Peer]
PublicKey = <pfsense-public-key>
Endpoint = <pfsense-wan-ip>:51820
AllowedIPs = 172.20.0.0/16, 10.69.69.0/24
PersistentKeepalive = 25

Schritt 2: Peer auf pfSense hinzufügen

Am einfachsten über die Web-UI: VPN → WireGuard → Peers → Add.

  • Tunnel: tun_wg0 (der bestehende)
  • Public Key: (vom Hypervisor)
  • Allowed IPs: 10.69.69.3/32
  • Persistent Keepalive: 25

Save. Apply.

Über SSH geht es auch — aber da lauert Pitfall #1.

Schritt 3: Switchover

# OpenVPN stoppen
systemctl stop openvpn-client@<dein-tunnel>

# WICHTIG: tun0 manuell entfernen (siehe Pitfall #3)
ip link del tun0 2>/dev/null

# WireGuard hoch
wg-quick up wg0

Schritt 4: Testen

ping -c2 10.69.69.1    # pfSense WireGuard-IP
ping -c2 172.20.20.4   # PBS am Remote-Standort
wg show                 # Handshake + Transfer prüfen

Schritt 5: Persistent machen

systemctl disable openvpn-client@<dein-tunnel>
systemctl enable wg-quick@wg0

Die drei Pitfalls

Klingt einfach? Ist es auch — bis es das nicht mehr ist.

Pitfall 1: filter_configure() auf pfSense killt alles

Wenn du den Peer per SSH und PHP in die config.xml schreibst, brauchst du danach einen Reload. Der intuitive Weg:

// NICHT MACHEN:
interface_reconfigure("opt1");
filter_configure();           // ← Das hier zerstört dein VPN

filter_configure() regeneriert alle pf-Regeln. Inklusive Anti-Spoofing. Wenn du gleichzeitig das Interface-Subnetz geändert hast (z.B. /30 auf /24), schreibt pfSense neue Anti-Spoofing-Regeln — und deine aktive VPN-Session fliegt raus. SSH-Timeout. Web-UI weg. Alles weg.

Der sichere Weg: Nur WireGuard synchen, keine Firewall anfassen:

require_once("/usr/local/pkg/wireguard/includes/wg.inc");
parse_config(true);
wg_tunnel_sync(array("tun_wg0"), true, true, false);

Das syncht nur die WireGuard-Config, ohne die Firewall-Regeln neu zu schreiben. Der bestehende Site-to-Site-Tunnel bleibt stehen.

Oder einfach die Web-UI nehmen. Ernsthaft. Bei pfSense-Config-Änderungen über SSH ist die Frage nicht ob du dich aussperrst, sondern wann.

Pitfall 2: Deine Tunnel-IP muss ins /30 passen

Auf meiner pfSense war das WireGuard-Interface als 10.69.69.1/30 konfiguriert. Der bestehende Site-to-Site-Peer hat 10.69.69.2. Ich wollte dem Hypervisor 10.69.69.5 geben.

Problem: /30 = nur 4 Adressen (.0 bis .3). Die .5 liegt außerhalb. pfSense hat keine Route zurück zum Hypervisor, weil die Adresse nicht im direkt verbundenen Subnetz liegt.

Mein erster Instinkt: Subnetz auf /24 erweitern. Das funktioniert — löst aber filter_configure() aus (Pitfall #1). Und damit war das Netzwerk tot.

Der einfache Fix: 10.69.69.3 nehmen statt .5. Die .3 liegt innerhalb des /30. Keine Subnetz-Änderung nötig. Kein filter_configure(). Kein Risiko.

/30 Subnetz:
.0 = Netzwerk
.1 = pfSense (Gateway)
.2 = Site-to-Site Peer
.3 = Hypervisor ← hier rein!

Pitfall 3: OpenVPN lässt tun0 stehen

systemctl stop openvpn-client@gw-tunnel

Du denkst, der Tunnel ist weg? Überraschung:

$ ip route | grep tun0
172.20.0.0/16 via 12.1.0.1 dev tun0    # ← Zombie-Route
172.22.22.0/24 via 12.1.0.1 dev tun0   # ← Noch eine

$ ip link show tun0
235: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP>  # ← Interface lebt!

OpenVPN entfernt das tun-Interface nicht immer sauber beim Stoppen. Die alten Routen bleiben stehen. Wenn du jetzt wg-quick up wg0 machst:

RTNETLINK answers: File exists
[#] ip link delete dev wg0

wg-quick versucht die gleichen Routen zu setzen, scheitert am Konflikt, und räumt sein eigenes Interface wieder ab. Kein Tunnel.

Noch fieser: Wenn tun0 eine Route für 172.20.0.0/16 hat und wg0 auch eine setzt, gewinnt die spezifischere oder zuerst gesetzte Route. Dein Traffic geht weiter über das tote OpenVPN-Interface ins Nirvana.

Fix:

systemctl stop openvpn-client@<tunnel>
ip link del tun0 2>/dev/null    # Interface + alle Routen entfernen
wg-quick up wg0                 # Jetzt sauber

Bonus-Pitfall: </peers> in config.xml ist nicht eindeutig

Falls du den pfSense-Peer per Script in die config.xml schreibst und str_replace("</peers>", ...) verwendest: Vergiss es. Mehrere Packages nutzen <peers>-Tags — bei mir war es Squid Reverse Proxy. Mein neuer WireGuard-Peer landete in drei verschiedenen Sections.

Immer eindeutige Marker verwenden (z.B. den Public Key des benachbarten Peers) und Treffer-Anzahl validieren:

$count = substr_count($xml, $marker);
if ($count !== 1) { echo "ABORT"; exit(1); }

AllowedIPs: Was rein muss und was nicht

Eine Sache die mich 10 Minuten gekostet hat: Der Hypervisor hostet selbst das 10.0.0.0/24 Netz (VM-Bridge). Wenn du das in die WireGuard AllowedIPs packst:

# FALSCH:
AllowedIPs = 10.0.0.0/24, 172.20.0.0/16, 10.69.69.0/24

# RICHTIG:
AllowedIPs = 172.20.0.0/16, 10.69.69.0/24

Die 10.0.0.0/24 Route über WireGuard kollidiert mit der bestehenden Bridge-Route. wg-quick bricht ab. Logisch, wenn man drüber nachdenkt — aber in der Hitze des Gefechts packt man gerne einfach alle Netze rein die der alte OpenVPN-Tunnel geroutet hat.


Health-Check

Nicht vergessen: Der alte OpenVPN-Healthcheck-Cron startet sonst OpenVPN wieder:

# Alten Cron entfernen
rm /etc/cron.d/openvpn-healthcheck

# Neuen anlegen
cat > /etc/cron.d/wireguard-healthcheck << 'EOF'
*/5 * * * * root /usr/local/bin/wireguard-healthcheck.sh
EOF

cat > /usr/local/bin/wireguard-healthcheck.sh << 'SCRIPT'
#!/bin/bash
if ! ip link show wg0 >/dev/null 2>&1; then
    logger -t "wireguard-healthcheck" "wg0 missing - restart"
    systemctl restart wg-quick@wg0
    sleep 3
fi
if ! ping -c 1 -W 5 10.69.69.1 >/dev/null 2>&1; then
    logger -t "wireguard-healthcheck" "tunnel unreachable - restart"
    systemctl restart wg-quick@wg0
fi
SCRIPT
chmod +x /usr/local/bin/wireguard-healthcheck.sh

Ergebnis

MetrikOpenVPNWireGuard
ImplementierungUserspace, single-threadedKernel-Space
MSS1208 Bytes1420 Bytes
Throughput (PBS)~3 MB/sDeutlich mehr
11 GB Restore~45 Min (Timeout!)Erfolgreich
CPU-LastSpürbar (Crypto in Userspace)Minimal

Der Restore der vorher in Timeouts gelaufen ist, ging jetzt sauber durch.


Fazit

Die Migration selbst ist simpel: Keypair generieren, Config schreiben, Peer hinzufügen, umschalten. 15 Minuten Arbeit.

Die Pitfalls sind es, die dich erwischen:

  1. filter_configure() nicht per CLI aufrufen — nur wg_tunnel_sync()
  2. Tunnel-IP innerhalb des bestehenden Subnetzes wählen — spart die Subnetz-Änderung
  3. tun0 manuell entfernen nach OpenVPN-Stop — ip link del tun0
  4. Nur eigene Netze in AllowedIPs — nicht das lokale VM-Netz
  5. Eindeutige Marker in config.xml</peers> ist mehrdeutig

Wenn du Proxmox PBS über einen Remote-Standort betreibst und noch OpenVPN nutzt: Der Wechsel auf WireGuard ist ein No-Brainer. Aber mach vorher ein Backup deiner pfSense-Config. Vertrau mir.