Hetzner
Leider funktioniert diese Lösung aktuell nicht, da routeviews.org nicht mehr existiert
Vorab: Dies ist keine korrekte Lösung. Es ist lediglich ein sehr unschöner Hack. Eine Lösung kann für solche Situationen nur in Zusammenarbeit mit dem Hoster erfolgen. Verweigert sich dieser, bleibt nur der Hack.
Hetzner monitored den Traffic, den die Gateways verursachen. Sollten Verbindungsversuche zu nicht gerouteten IPs dabei sein, generiert Hetzner Abuse und schickt es (Achtung!) nicht an die hinterlegte Abuse-Adresse. Was man dagegen tun kann ist hier beschrieben.
Man benötigt zunächst alle routbaren Adresse/Prefixe. Diese kann man sich z.B. bei routeviews.org runterladen. Diese Adressen können dann in die Routing-Tabelle eingepflegt werden. Am besten geht das, wenn das Gateway in einer VM ist, dann kann der Host die Filterung übernehmen.
In diesem Beispiel kommunizieren die Gateways, welche in VMs laufen, über das Interface "f3n". Normalerweise wird jeder Traffic von diesem Interface einfach weiter zum default Gateway geschickt. (Bei professionellen Hostern wird dann spätestens beim Border-Gateway jeglicher auf null geroutet). Der Mechanismus ist nun, per "ip rules" alle Verbindungen, die aus f3n (also von den VMs) kommen in eine eigene Routing Tabelle (hetzner1) zu sperren. In dieser werden alle routbaren Prefixe mit dem default gateway von Hetzner als next-hop eingetragen. Als default gateway in dieser Tabelle wird 127.0.0.1 über lo eingetragen. Alle x Stunden sollte die Tabelle aufgefrischt werden. Dazu wird eine neue (hetzner2) angelegt und anschließend die Regel umgebogen.
Hetzner-Script auf dem Host
Dies ist die einfachere und "bessere" Implementierung, denn das Script läuft nur einmalig auf dem Hostrechner, während die einzelnen Freifunk-VMs davon entkoppelt sind.
/etc/iproute2/rt_tables:
.. 11 hetzner1 12 hetzner2
hetzner.sh:
cd /tmp current=$(ip ru | grep hetzner | sed 's/.*hetzner//g' | tr -d '[:space:]') if [ "$current" = "1" ]; then next="2" else next="1" fi echo "Downloading routing snapshot" wget -q http://archive.routeviews.org/oix-route-views/oix-full-snapshot-latest.dat.bz2 -O oix-full-snapshot-latest.dat.bz2 echo "Unpacking" bzip2 -d -f oix-full-snapshot-latest.dat.bz2 echo "Parsing" allIP=oix-full-snapshot-latest.uniq tail -n+6 oix-full-snapshot-latest.dat | cut -d' ' -f3 | uniq | grep -v "0.0.0.0/0" > $allIP echo "Aggregating the prefixes" filterIP=oix-full-snapshot-latest.filtered unlink $filterIP for i in $(seq 0 255); do (grep "^$i\." $allIP | aggregate >> $filterIP) 2>&1 | grep -v "aggregate: maximum prefix length permitted will be 32" | grep -v "aggregate: no prefixes supplied" done echo "Cleaning up hetzner$next" ip ro flush ta hetzner$next echo "Inserting new valid routes to hetzner$next" for prefix in $(cat $filterIP | grep -v "^#"); do ip ro add $prefix via 5.9.89.33 table hetzner$next done echo "Inserting null route to hetzner$next" ip ro add default via 127.0.0.1 dev lo table hetzner$next echo "Adding new rule for hetzner$next" ip ru add from all iif f3n lookup hetzner$next if [ -n "$current" ]; then echo "Removing old rule for hetzner$current" ip ru del from all iif f3n lookup hetzner$current echo "Cleaning up old hetzner$current" ip ro flush ta hetzner$current fi
Hetzner-Script auf der VM
Manche haben nur eine VM gemietet und keinen Zugang zum Host. Mit etwas Bastelei ist auch dieser Betriebsfall realisierber.
Vorbereitung
Wir benötigen außer "fff" noch drei zusätzliche Routing-Tabellen.
vi /etc/iproute2/rt_tables
... 20 fff 21 hetzner1 22 hetzner2 30 fffdefault ...
Babel erzeugt für interne Zwecke ein paar Tabellen direkt auf 10 folgend, deshalb bei der Nummerierung etwas Platz lassen. Die Tabellen "hetzner1" und "hetzner2" werden wechselweise vom Hetzner-Script befüllt. Die Tabelle "fffdefault" bekommt eine Dummy-Defaultroute. Hintergrund: In der fff-Tabelle darf keine Defaut-Route sein. Dann wird nämlich in der Hetzner-Tabelle weitergesucht, und dort schreibt das Script eine Defaultroute auf Lokalhost und macht damit den Internet-Exit für alle IPv4 Adressen dicht, die nicht in der Hetzner-Tabelle aufgelistet sind.
Beim Systemstart vor Aufruf des Hetzner-Scripts wird der Internet-Exit dicht gemacht. Außerdem wird die oben erwähnte Dummy-Defaultroute gesetzt. Diese Dummy-Route wäre ein gültiger Internet-Exit für alles, deshalb darf die Tabelle "fffdefault" unter keinen Umständen angesprungen werden. Diese Route wird nur angelegt, damit Babel eine gültige Defaultroute findet. Sonst würde es das Adressband 0.0.0.0/0 nicht anbieten. Im Beispiel ist "eth0" der Internet-Exit.
ip route replace default via 127.0.0.1 dev lo table fff ip route replace default dev eth0 proto static table fffdefault
Alle Interfaces, die auf die fff-Tabelle verweisen, sollen zuerst in der fff-Tabelle nachschauen, und danach in der gerade aktiven Hetzner-Tabelle "hetzner1" bzw. "hetzner2". Dafür bekommt jedes Interface eine Priorität (priority) in fff zugewiesen und später im Hetzner-Script eine niedrigere Priorität (höhere Nummer) in der Hetzner-Tabelle. Hinweis: Die Prioritäten müssen höher (kleinere Nummer) als 100 sein, weil Babel die Priorität 100 für interne Zwecke benötigt.
vi /etc/network/interfaces
iface bat0 inet manual ... post-up ip rule add iif $IFACE table fff priority 41 ... iface bat1 inet manual ... post-up ip rule add iif $IFACE table fff priority 42 ... iface fff-ab-dc-01 inet static ... post-up ip rule add iif $IFACE table fff priority 51 ...
Babel soll in der Freifunk-Tabelle (fff) und in der Tabelle mit der Dummy-Defaultroute (fffdefault) nachschauen, nicht jedoch in der Hetzner-Tabelle. Es wird also "import-table 30" ergänzt, wenn die Nummerierung wie oben gewählt wurde.
vi /etc/babeld.conf
... export-table 20 import-table 20 import-table 30 ...
Änderungen im Hetzner-Script
Bei mehreren Interfaces wird in die Variable "current" mehrfach die Nummer des aktuell aktiven Hetzner-Scripts geschrieben. Für die spätere Logik muss das auf ein Zeichen gekürzt werden.
... current=$(ip rule | grep hetzner | sed 's/.*hetzner//g' | tr -d '[:space:]') current=$(expr substr $current 1 1) ...
Die IP im folgenden Scriptteil muss auf das Gateway des Server-Vermieters zeigen, nicht auf die eigene IP. Je nach Server-Rack sind die Gateways unterschiedlich, hier im Beispiel also 8.8.1.1.
... echo "Inserting new valid routes to hetzner$next" for prefix in $(cat $filterIP | grep -v "^#"); do ip ro add $prefix via 8.8.1.1 table hetzner$next done ...
Alle Interfaces, denen vorhin Prioritäten für die fff-Tabelle zugeteilt wurden, müssen nun auch (niedrigere) Prioritäten für die Hetzner-Tabelle bekommen (höhere Nummern).
... echo "Adding new rule for hetzner$next" ip ru add from all iif bat0 lookup hetzner$next priority 60 ip ru add from all iif bat1 lookup hetzner$next priority 61 ip ru add from all iif fff-ab-dc-01 lookup hetzner$next priority 62 if [ -n "$current" ]; then echo "Removing old rule for hetzner$current" ip ru del from all iif bat0 lookup hetzner$current ip ru del from all iif bat1 lookup hetzner$current ip ru del from all iif fff-ab-dc-01 lookup hetzner$current ...
Am Ende des Scripts wird zum Abschluss die Defaultroute aus der fff-Tabelle gelöscht. Achtung, Babel legt eine Defaultroute in fff an, wenn nicht (wie hier) beim Systemstart schon eine angelegt wurde.
... ip route del default table fff
Script zyklisch aufrufen
Das Script muss nun beim Systemstart und zyklisch alle X Stunden aufgerufen werden, möglichst nicht zu Zeiten mit Spitzenlast. Während der ca. 5 Minuten Abarbeitungszeit geht die Prozessorlast auf 100%, deshalb empfiehlt sich mit "nice -n 19" das Script mit niedrigster Priorität zu starten.
vi /etc/rc.local
# call Hetzner routing workaround with lowest priority (nice -n 19 sh /root/hetzner.sh) &
crontab -e
0 4 * * * nice -n 19 sh /root/hetzner.sh