Netzwerk

pfSense/OPNsense mit nur einer öffentlichen IP auf einem Proxmox Root-Server

Wie man einen dedizierten Root-Server (z. B. Hetzner) mit einer einzigen öffentlichen IP so konfiguriert, dass der gesamte VM-Traffic über eine pfSense/OPNsense-Firewall läuft.

Thomas 28. Oktober 2025 5 Min. Lesezeit 80 Aufrufe 25. Mai 2026

Übersicht

Dieser Artikel zeigt, wie man einen dedizierten Root-Server mit statischer IP-Adresse (z. B. bei Hetzner, IONOS oder Netcup) so konfiguriert, dass der gesamte VM-Datenverkehr über eine pfSense/OPNsense-Firewall läuft, mit nur einer einzigen öffentlichen IP-Adresse. Die Proxmox-GUI ist danach nicht mehr direkt aus dem Internet erreichbar und wird über einen lokalen SSH-Tunnel aufgerufen.

Netzwerk-Architektur

Die Lösung basiert auf drei Bridges:

  • vmbr0: WAN-Bridge mit öffentlicher IPv4/IPv6
  • vmbr1: Transit-Bridge (10.0.10.0/30) für pfSense-WAN
  • vmbr2: LAN-Bridge für pfSense und VMs

Eingehender Verkehr wird per DNAT zur WAN-Schnittstelle weitergeleitet (ausgenommen SSH Port 22). Ausgehender Verkehr wird per Masquerading genattet.

Schritt 1: IP-Adressen ermitteln

# Interface setzen (bei Hetzner meist eno1)
IFACE=eno1

# IPv4-Adresse
ip -o -4 addr show dev "$IFACE" | awk '{print "address "$4}'

# IPv6-Adresse (ohne fe80::)
ip -o -6 addr show dev "$IFACE" | awk '$4 !~ /^fe80::/ {print "address "$4}'

# Default-Gateways
ip route | awk -v d="$IFACE" '$1=="default" && $5==d {print "gateway "$3; exit}'
ip -6 route | awk -v d="$IFACE" '$1=="default" && $5==d {print "gateway "$3; exit}'

Schritt 2: /etc/network/interfaces konfigurieren

Die Platzhalter mit den in Schritt 1 ermittelten Werten ersetzen. Die IPv6-Zeilen sind auskommentiert und werden nur benotigt wenn ein geroutetes IPv6-Subnetz vorhanden ist (siehe optionaler Abschnitt weiter unten).

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto eno1
iface eno1 inet manual

auto vmbr0
iface vmbr0 inet static
        address /
        gateway 
        bridge-ports eno1
        bridge-stp off
        bridge-fd 0
        bridge-maxwait 0

# Optional: IPv6 -- siehe Abschnitt weiter unten
#iface vmbr0 inet6 static
#        address /64
#        gateway fe80::1

post-up echo 1 > /proc/sys/net/ipv4/ip_forward

auto vmbr1
iface vmbr1 inet static
        address 10.0.10.1/30
        bridge-ports none
        bridge-stp off
        bridge-fd 0

        # DNAT: alle TCP-Verbindungen ausser SSH an pfSense weiterleiten
        post-up   iptables -t nat -A PREROUTING -i vmbr0 -p tcp ! --dport 22 -j DNAT --to-destination 10.0.10.2
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp ! --dport 22 -j DNAT --to-destination 10.0.10.2 || true

        # Masquerading fuer ausgehenden Traffic vom Transit-Netz
        post-up   iptables -t nat -A POSTROUTING -s '10.0.10.0/30' -o vmbr0 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '10.0.10.0/30' -o vmbr0 -j MASQUERADE || true

# Optional: IPv6 -- siehe Abschnitt weiter unten
#iface vmbr1 inet6 static
#        address fd00:10::1/64
#
#        post-up   sysctl -w net.ipv6.conf.all.forwarding=1
#        post-up   sysctl -w net.ipv6.conf.default.forwarding=1
#
#        post-up   ip -6 route replace /64 via fd00:10::2 dev vmbr1
#        post-down ip -6 route del /64 || true
#
#        post-up   ip6tables -C FORWARD -i vmbr1 -o vmbr0 -j ACCEPT 2>/dev/null || ip6tables -A FORWARD -i vmbr1 -o vmbr0 -j ACCEPT
#        post-up   ip6tables -C FORWARD -i vmbr0 -o vmbr1 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || ip6tables -A FORWARD -i vmbr0 -o vmbr1 -m state --state RELATED,ESTABLISHED -j ACCEPT
#        post-down ip6tables -D FORWARD -i vmbr1 -o vmbr0 -j ACCEPT 2>/dev/null || true
#        post-down ip6tables -D FORWARD -i vmbr0 -o vmbr1 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true

auto vmbr2
iface vmbr2 inet static
        address /24
        bridge-ports none
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 2-4094

Schritt 3: System neu starten

/usr/sbin/reboot

Konfiguration bei pfSense/OPNsense

WAN-Interface

Unter Interfaces → WAN: IPv4 auf Static setzen, Adresse 10.0.10.2/30, Gateway 10.0.10.1. Die Optionen Block private networks und Block bogon networks deaktivieren, da die WAN-IP eine private Transit-Adresse ist.

IPv6 optional: Static fd00:10::2/64, Gateway fd00:10::1.

LAN-Interface

Unter Interfaces → LAN: IPv4 Static, z. B. 192.168.10.254/24. Weitere Subnetze als OPT-Interfaces hinzufugen.

DHCP

Unter Services → DHCP Server pro Interface aktivieren, Range und Gateway eintragen. Als DNS-Server entweder die pfSense-IP (DNS Resolver) oder direkt externe Server wie 1.1.1.1.

Outbound NAT

Unter Firewall → NAT → Outbound den Modus auf Hybrid stellen. Alle internen Subnetze gehen per Masquerade uber das WAN raus.

Optional: Geroutetes IPv6-Subnetz für VMs (Hetzner)

Jeder Hetzner Dedicated Server kommt mit einem /64-Subnetz für den Host selbst. Damit VMs öffentliche IPv6-Adressen erhalten, muss im Hetzner Robot unter IPs / Subnets ein zusätzliches geroutetes /64 bestellt werden.

Die in Schritt 2 auskommentierten IPv6-Zeilen müssen dazu einkommentiert werden. Die vollständige Konfiguration mit IPv6:

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback
iface lo inet6 loopback

auto eno1
iface eno1 inet manual

auto vmbr0
iface vmbr0 inet static
        address /
        gateway 
        bridge-ports eno1
        bridge-stp off
        bridge-fd 0
        bridge-maxwait 0

iface vmbr0 inet6 static
        address /64
        gateway fe80::1

post-up echo 1 > /proc/sys/net/ipv4/ip_forward

auto vmbr1
iface vmbr1 inet static
        address 10.0.10.1/30
        bridge-ports none
        bridge-stp off
        bridge-fd 0

        # DNAT: alle TCP-Verbindungen ausser SSH an pfSense weiterleiten
        post-up   iptables -t nat -A PREROUTING -i vmbr0 -p tcp ! --dport 22 -j DNAT --to-destination 10.0.10.2
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp ! --dport 22 -j DNAT --to-destination 10.0.10.2 || true

        # Masquerading fuer ausgehenden Traffic vom Transit-Netz
        post-up   iptables -t nat -A POSTROUTING -s '10.0.10.0/30' -o vmbr0 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '10.0.10.0/30' -o vmbr0 -j MASQUERADE || true

iface vmbr1 inet6 static
        address fd00:10::1/64

        post-up   sysctl -w net.ipv6.conf.all.forwarding=1
        post-up   sysctl -w net.ipv6.conf.default.forwarding=1

        post-up   ip -6 route replace /64 via fd00:10::2 dev vmbr1
        post-down ip -6 route del /64 || true

        post-up   ip6tables -C FORWARD -i vmbr1 -o vmbr0 -j ACCEPT 2>/dev/null || ip6tables -A FORWARD -i vmbr1 -o vmbr0 -j ACCEPT
        post-up   ip6tables -C FORWARD -i vmbr0 -o vmbr1 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || ip6tables -A FORWARD -i vmbr0 -o vmbr1 -m state --state RELATED,ESTABLISHED -j ACCEPT
        post-down ip6tables -D FORWARD -i vmbr1 -o vmbr0 -j ACCEPT 2>/dev/null || true
        post-down ip6tables -D FORWARD -i vmbr0 -o vmbr1 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true

auto vmbr2
iface vmbr2 inet static
        address /24
        bridge-ports none
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 2-4094

pfSense erhält auf dem Transit-Interface die Adresse fd00:10::2/64 mit Gateway fd00:10::1. Das geroutete /64 wird auf dem LAN-Interface verteilt, entweder statisch oder per DHCPv6/SLAAC.

Zugriff auf die Proxmox-GUI via SSH-Tunnel

Da Port 8006 nicht direkt erreichbar ist, wird die GUI über einen lokalen SSH-Tunnel aufgerufen:

ssh -L 8006:localhost:8006 root@<server-ip>

Danach im Browser https://localhost:8006 aufrufen.

Eine einzige öffentliche IP-Adresse genügt für ein vollständiges Firewall-Setup mit VM-Isolation auf Proxmox.

Kommentare

0

Noch keine Kommentare. Sei der Erste!

Kommentar schreiben

Kommentare werden vor der Veröffentlichung geprüft.