Proxmox mit noez.de FlexIP's für die VM's via GRE

Veröffentlicht: / Letztes Update:

Nachdem wir unsere Virtualisierung mit Proxmox VE eingerichtet haben, benötigen wir zusätzliche IPv4 Adressen für unsere virtuellen Maschinen und Linux Container, damit diese von aussen erreichbar sind.

Leider bieten viele Server Hoster in den kleineren Serverreihen keine zusätzlichen IPv4-Adressen mehr an oder man muss diese für teures Geld hinzubuchen. (Mir sind Preise von bis zu 5,99 € pro Monat und pro IPv4-Adresse bekannt.)

Hierzu gibt es nun eine gute Lösung von noez.de (Stand 04.01.2024):
Für eine monatliche Grundgebühr von 2,00 EUR erhaltet Ihr einen GRE Tunnel und könnt einzelne IPv4-Adressen oder mehrere zusammenhängende IPv4-Adressen hinzubuchen. Dies Kosten für zusätzliche IPv4-Adressen liegen hier bei 0,50 EUR pro Monat und IP. Das bedeutet, wenn Ihr Euch 8 IPv4-Adressen bucht, zahlt Ihr insgesamt 6,00 EUR pro Monat. (Link: noez.de FlexIP's

Der Vorteil dieser Lösung von noez.de ist, dass Ihr auch die reverse DNS für die jeweiligen IPv4-Adressen setzen könnt und die Einrichtung unter Proxmox ist sehr einfach. Bitte bucht eine IP-Adresse mehr als Ihr benötigt, da wir bei der gezeigten Lösung eine IPv4-Adresse als Gateway benötigen. Wichtig ist auch noch zu erwähnen, dass Ihr -auch wenn Ihr ein z. B. /28er Netz bestellt-, alle IP-Adressen als /32er Netzmaske geroutet bekommt, dies hat den Vorteil, dass wirklich jede der IP-Adressen nutzbar ist.

Aber kommen wir nun zur Einrichtung:

Stellt sicher, dass auf dem Server kein CloudInit oder NetManager aktiv ist und das Netzwerkinterface in der Datei /etc/network/interfaces konfiguriert.

Eins vorweg: Ich benutze in meinen Anleitungen den Editor nano. Wenn Ihr damit eine Datei bearbeitet, könnt Ihr die Änderungen mit "Strg + O" speichern und mit "Strg + X" den Editor verlassen.

Als erstes öffnen wir die Datei "/etc/network/interfaces:" im Editor:

sudo nano /etc/network/interfaces

Diese Datei passt Ihr dann wie folgt an:
Die farbig markierten Parameter müsst Ihr an Euren Server anpassen!
Die öffentlichen IP-Adressen sind von mir mit x anonymisiert.

auto lo
iface lo inet loopback

auto enp3s0
iface enp3s0 inet static
    address x.x.x.x/xx
    gateway x.x.x.x
    post-up sysctl -w net.ipv4.ip_forward=1
    post-up iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o enp3s0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '10.0.0.0/24' -o enp3s0 -j MASQUERADE
    post-up iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
    post-down iptables -D FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

iface enp3s0 inet6 static
    address 2001:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/xx
    gateway 2001:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx

auto vmbr0
iface vmbr0 inet static
    address 10.0.0.0/24
    bridge-ports none
    bridge-stp off
    bridge-fd 0
    mtu 1476
    post-up /root/noez_gre_up.sh
    pre-down /root/noez_gre_down.sh

Erklärung:
post-up und post-down geben an, zu welchem Zeitpunkt der dahinter stehende Befehl ausgeführt wird. post-up bedeutet nach dem Start des Netzwerkinterfaces und post-down bedeutet nach dem Stoppen des Netzwerkinterfaces.

Mit "sysctl -w net.ipv4.ip_forward=1" sagen wir dem Linux Kernel, dass er IPv4 Pakete zwischen den Interfaces weiterleiten soll.
Die Firewall Regel "iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o enp3s0 -j MASQUERADE" richtet für das lokale IP-Netz 10.0.0.0/24 ein NAT ein, damit wir unseren virtuellen Maschinen für die Installation eine IPv4 Adresse aus dem Netz 10.0.0.0/24 vergeben können und darüber auf das Internet zugegriffen werden kann.

Einige Betriebssysteme verweigern eine /32er IPv4 bei der Installation auf einer VM!

Die nächste Firewall Regel "iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu " ist wichtig, da mir einen GRE Tunnel nutzen und es dadurch zu Problemen mit der Paketlänge kommen kann. (Path MTU Discovery)

Die Bridge vmbr0 (oder eine höhere Zahl wie z. B. vmbr1) ist sozusagen ein virtueller Netzwerkswitch an dem jede virtuelle Maschine und Linux Container an einen eigenen Port angeschlossen wird.
Dieser brücke weisen wir die IPv4 Adresse 10.0.0.1/24 zu, welche wir später beim NAT auch als Gateway nutzen. Wichtig ist, dass die Bridge, über welche wir die FlexIP's leiten werden, nicht mit dem Interface des Servers gebrückt ist, da es sonst zu Problemen bei der Paketweiterleitung kommen kann. (Bridges sind ein Mysterium ;-))

Über die Einträge "post-up /root/noez_gre_up.sh" und "pre-down /root/noez_gre_down.sh" rufen wir zwei Scripte auf, welche den Tunnel aufbauen und schließen, sowie die benötigten Firewall regeln der IP-Adressen aktiviert und deaktiviert. Diese beiden Dateien legen wir im folgenden Schritt an.

Die benötigten Scripte anlegen:

Die Befehle für den Aufbau und Abbau des Tunnels lagern wir in zwei Shell-Scripte aus, da dies zu unübersichtlich in der Netzwerkkonfiguration sein würde und manchmal auch einzelne Einträge verloren gehen, wenn man im Nachgang über das Control Panel von Proxmox z.B. eine neue Bridge anlegt.

Bitte führt folgende Befehle aus, um die benötigten Dateien anzulegen:

sudo touch /root/noez_gre_up.sh
sudo touch /root/noez_gre_down.sh
sudo chmod -v 755 /root/noez_gre_up.sh
sudo chmod -v 755 /root/noez_gre_down.sh

Mit den obigen Befehlen legen wir die benötigten Dateien im /root-Verzeichnis an und legen die Zugriffsrechte fest.

In den folgenden beiden Dateien werden einige Daten aus dem Login Bereich von noez.de benötigt. Dazu loggt Ihr Euch unter https://noez.de/de/cp/dashboard ein, klickt dann im linken Menü auf den Punkt "Services". In der Übersicht über Eure gebuchten Dienste wählt Ihr den "GRE Tunnel (GRE)" aus, den Ihr für Euren Server nutzen möchtet (falls Ihr mehrere gebucht habt).

Daraufhin öffnet sich die Übersichtsseite Eures GRE Tunnels, dort klickt Ihr dann auf Webinterface.

Dort findet Ihr die IP-Adressen "Inernal-Gateway" und "Internal-ClientIP", die benötigen wir zusammen mit der IP Adresse des Tunnel Servers. In dem Feld "Remote IP", tragt Ihr die öffentliche IPv4 Adresse Eures Servers ein und klickt auf Update.

Jetzt fehlt uns nur noch die IP Adresse des Tunnelservers. Diese findet Ihr, wenn Ihr etwas herunter scrollt. Diese tragt Ihr in den beiden Scripten, welche wir gleich erstellen anstelle des Platzhalters "Noez-RemoteIP" ein. Zudem findet Ihr in den dortigen Befehlen auch die jeweilige Netzmaske Eurer IP Adressen.

Da Ihr aber auch wissen müsst, welche IPv4 Adresse Ihr von noez.de zugeteilt bekommen habt, scrollt Ihr nun ganz herunter. Dort findet Ihr eine Liste mit allen IPv4 Adressen, die auf Euren Tunnel geroutet werden. Die /24er Netzmaske die in der Spalte Subnet angeben ist. Dürft Ihr natürlich nicht verwenden, da Euch dies nur zeigen soll, aus welchem übergeordneten IP Netz die jeweilige IP stammt.

Da wir jetzt alle Daten haben, die wir benötigen, nehmen wir wieder unseren Editor nano, um die bereits angelegten - aber noch leeren - Dateien mit Inhalt zu füllen.

sudo nano /root/noez_gre_up.sh

Nun fügen wir folgendes in die Datei "/root/noez_gre_up.sh" ein:

#!/bin/bash

# GRE Tunnel zum Endpunkt von noez.de anlegen und verbinden

ip tunnel add noezgre1 mode gre local Remote IP remote Noez-RemoteIP ttl 255
ip addr add Internal-ClientIP/30 dev noezgre1
ip link set noezgre1 up

# Eine IP Adresse der Bridge vmbr0 zuweisen, diese dient als VM Gateway

ip addr add 5.x.x.xx2/32 dev vmbr0

# Festlegen auf welche IP Pakete aus dem Tunnel reagiert werden soll
# und dies in eine eigene Routing Tabelle mit der Nummer 20 eintragen,
# sowie dass Standard Gateway für diese Tabelle festlegen
# Jede IP benötigt einen eigenen Eintrag (Angabe ohne Netzmaske)

ip rule add from 5.x.x.xx2 table 20 prio 1
ip rule add from 5.x.x.xx3 table 20 prio 1
ip rule add from 5.x.x.xx4 table 20 prio 1
ip rule add from 5.x.x.xx5 table 20 prio 1
ip rule add from 5.x.x.xx6 table 20 prio 1
ip rule add from 5.x.x.xx7 table 20 prio 1
ip rule add from 5.x.x.xx8 table 20 prio 1
ip rule add from 5.x.x.xx9 table 20 prio 1
ip route add default via Internal-Gateway dev noezgre1 table 20

# Die IP Routen in die Bridge zeigen lassen
# Auch hier benötigt jede IP einen eigenen Eintrag mit der Netzmaske /32
# ausser Ihr habt etwas anderes als /32 zugewiesen bekommen

ip route add 5.x.x.xx2/32 dev vmbr0
ip route add 5.x.x.xx3/32 dev vmbr0
ip route add 5.x.x.xx4/32 dev vmbr0
ip route add 5.x.x.xx5/32 dev vmbr0
ip route add 5.x.x.xx6/32 dev vmbr0
ip route add 5.x.x.xx7/32 dev vmbr0
ip route add 5.x.x.xx8/32 dev vmbr0
ip route add 5.x.x.xx9/32 dev vmbr0

Erklärung:

Im oberen Teil der Datei bauen wir den Tunnel auf und weisen dem neuen Netzwerkinterface noezgre1 die für unseren Tunnel vorgegebene Client IP zu, damit wir über den Tunnel kommunizieren können.

Danach weisen wir der vmbr0 (bitte anpassen, wenn Ihr zu Anfang eine andere Bridge Nummer verwendet) eine der uns zugewiesenen IPv4 Adressen zu, diese verwenden wir später als Gateway für unsere virtuellen Maschinen und Linux Container. Dies ist notwendig, damit der Traffic seinen Weg aus der Bridge heraus findet Es scheint auch mit der IP 10.0.0.1 zu funktionieren, wenn Ihr diese als Gateway verwendet. (Ist mir aber zu wackelig!)

Mit dem Befehl "ip rule add from 5.x.x.xx2 table 20 prio 1" sagen wir unserem Kernel, dass er auf Pakete der angegeben IP-Adresse reagieren soll, sonst werden diese Pakete ignoriert und bekommt keine Verbindung. Zusätzlich soll die Regel in die Routing Tabelle an oberster Stelle eingetragen werden.

Bis jetzt wäre nur die IP-Adresse 5.x.x.xx2 von aussen erreichbar. Alles was innerhalb der Bridge ist, weiß der Kernel noch nicht. (ganz grob gesagt)
Damit auch die IP-Adressen der VM's und LXC's erreichbar sind, müssen wird den Kernel mit "ip route add" anweisen, den Traffic für unsere IP's in die Bridge zu routen.

Die zweite Datei

Analog zur noez_gre_up.sh bearbeiten wir jetzt die Datei noez_gre_down.sh.

sudo nano /root/noez_gre_up.sh

In die Datei "/root/noez_gre_up.sh" fügen wir folgenden Inhalt ein:

#!/bin/bash

# Der vmbr0 die noez IP Adresse entziehen

ip addr del 5.x.x.xx2/32 dev vmbr0

# Dem Kernel sagen, dass wir nicht mehr für diese IP Adressen zuständig sind
# Jede IP benötigt einen eigenen Eintrag (Angabe ohne Netzmaske)

ip rule del from 5.x.x.xx2 table 20 prio 1
ip rule del from 5.x.x.xx3 table 20 prio 1
ip rule del from 5.x.x.xx4 table 20 prio 1
ip rule del from 5.x.x.xx5 table 20 prio 1
ip rule del from 5.x.x.xx6 table 20 prio 1
ip rule del from 5.x.x.xx7 table 20 prio 1
ip rule del from 5.x.x.xx8 table 20 prio 1
ip rule del from 5.x.x.xx9 table 20 prio 1

# Default Route durch den Tunnel entfernen

ip route del default via Internal-Gateway dev noezgre1 table 20

# IP Routen in den Tunnel entfernen
# Auch hier benötigt jede IP einen eigenen Eintrag mit der Netzmaske /32
# ausser Ihr habt etwas anderes als /32 zugewiesen bekommen

ip route del 5.x.x.xx2/32 dev vmbr0
ip route del 5.x.x.xx3/32 dev vmbr0
ip route del 5.x.x.xx4/32 dev vmbr0
ip route del 5.x.x.xx5/32 dev vmbr0
ip route del 5.x.x.xx6/32 dev vmbr0
ip route del 5.x.x.xx7/32 dev vmbr0
ip route del 5.x.x.xx8/32 dev vmbr0
ip route del 5.x.x.xx9/32 dev vmbr0

# IP Tunnel auf down setzen, ip entziehen und abbauen

ip addr del Internal-ClientIP/30 dev noezgre1
ip link set noezgre1 down
ip tunnel del noezgre1

Erklärung:

In der zweiten Datei machen wir alles rückgängig, was wir beim Aufbau des Tunnels in die Routing Tabellen eingetragen haben und welche IP's wir zugewiesen haben. So halten wir unser Routing sauber und wir haben weniger Fehlermeldungen in den Logfiles beim erneuten Aufbau des Tunnels.

Abschließender Schritt

Wenn Ihr alle Konfigurationen noch einmal überprüft und alles gespeichert habt, können wir das Netzwerk neu starten.
Dies macht Ihr mit dem folgenden Befehl:

sudo service networking restart

Ab jetzt ist die Nutzung der FlexIP's auf Eurem Server für VM's und LXC's möglich.

IPv4 in VM's einrichten

Wenn Ihr eine virtuelle Maschine anlegt oder einer bestehenden ein weiteres Netzwerkinterface hinzufügt, müsst Ihr als Bridge "vmbr0" auswählen und als Modell wählt Ihr "intel E1000" aus. Danach setzt Ihr unten den Haken bei Erweitert und tragt in dem Feld Multiqueue den Wert "8", sowie im Feld MTU den Wert 1 ein. MTU 1 bedeutet, dass der MTU Wert der Bridge genutzt werden soll, welcher in unserem Fall bei 1440 liegt. Der Grund hierfür ist, das wir bei der Datenübertragung durch einen GRE Tunnel bei bestimmten Payloads und Protokollen zu große IP Pakete erzeugen und Verbindungen instabil werden und der GRE Tunnel selbst noch 4 Byte selbst benötigt, welche an die IP Pakete angefügt werden. Zudem richten wir in dem nächsten Blogeintrag über die vmbr0 noch einen IPv6 Tunnel ein.
Einen Rechner zur Berechnung der MTU findet Ihr hier: MTU Rechner.

Beim Anlegen einer virtuellen Maschine könnt Ihr noch keine IP-Adressen festlegen. Dies macht Ihr beim Installieren des Betriebssystems oder via CloudInit.
Das Gateway ist die der vmbr0 zugewiesene IP-Adresse. (In unserem Beispiel ist dies: 5.x.x.xx2)

IPv4 in LXC's einrichten

Beim Linux Containern richtet Ihr die IP-Adressen direkt währen der Einrichtung ein. Hier müsst Ihr die Netzwerkeinstellungen wie folgt ausfüllen:

Bridge: vmbr0
MTU: Wie Bridge
IPv4: Statisch
IPv4/CIDR: 5.x.x.xx3/32 <- Die gewünschte IP Adresse unter der Ihr den LXC erreichbar machen wollt inkl. der Netzmaske. (In diesem Beispiel /32)
Gateway (IPv4): 5.x.x.xx2 <- Die IP-Adresse welcher Ihr der vmbr0 zugewiesen habt.


Eine Anleitung, wie Ihr IPv6-Adressen von tunnelbroker.net für Eure VM's und LXC's unter Proxmox nutzt, findet Ihr hier.