Babel
Funktion
Babel wird als Layer 3 Routingprotokoll in der Freifunk Franken Backbone verwendet. So werden alle Gateways über das Protokoll direkt oder indirekt miteinander verbunden. Babel tauscht gegenseitig die Routen der Gateways aus, so das jedes Gateway weiß über welchen Weg es eine andere Hood erreichen kann. Das eigentliche Routing übernimmt der Linuxkernel. Babel ist nur für den Austausch der Informationen zuständig.
Vorsicht
ACHTUNG:
IP Adressen dürfen nur announced werden, wenn sie auch erreicht werden können. Wer das Subnetz für eine Hood announced, muss diese Hood auch erreichen können.
Installation
babeld kann direkt aus der Distribution installiert werden.
apt install babeld
Debian liefert mit stretch allerdings eine recht alte Version aus.
Es ist daher sinnvoll, babeld selbst aus den Sourcen zu kompilieren und installieren.
Empfohlen ist aktuell die Version 1.8.5.
Alles danach (git master oder 1.9.0) sollte zum aktuellen Zeitpunkt noch nicht verwendet werden, da sich dort einiges in Sachen Source Specific routen geändert hat und nicht kompatibel ist.
Kurzanleitung fürs bauen und installieren der aktuell empfohlenen Version:
git clone https://github.com/jech/babeld cd babeld git checkout babeld-1.8.5 make sudo make install
Dafür sind in Debian die Pakete git und build-essential nötig.
Änderungen ab Babel 1.8.0
- Die Option 'wired true' gibt es nicht mehr, dafür gibt es jetzt Interface-Typen. Am sinnvollsten für GRE oder wireguard Tunnel ist wohl 'type tunnel'
- Die neueste Version von BabelWeb (0.4.0) ist nicht mit Babel 1.8.0 kompatibel. Daher muss BabelWeb aus dem develop Branch installiert werden oder man nutzt Simple-Babelweb (Eigenentwicklung aus der Community in PHP geschrieben).
systemd service für babeld
Bei Debian Stretch wird babeld noch mit einem SysVinit Skript ausgeliefert. Es kann sinnvoll sein, dieses durch einen passenden systemd Service auszutauschen. Wird babeld ausschließlich aus den Quellen installiert (siehe oben), ist kein init-Skript installiert, in diesem Fall muss dieser systemd Service verwendet werden.
Die Service Datei wird unter /etc/systemd/system/babeld.service
abgelegt.
[Unit] Description=babeld Routing Daemon After=network.target [Service] Type=simple EnvironmentFile=/etc/default/babeld ExecStart=/usr/local/bin/babeld $DAEMON_ARGS $INTERFACES Restart=on-abort [Install] WantedBy=multi-user.target
Ggf. muss die Datei /etc/default/babeld
manuell angelegt werden:
# Defaults for babeld initscript # sourced by /etc/init.d/babeld # List of interfaces on which the protocol should operate INTERFACES="" # Additional arguments DAEMON_ARGS="-S /var/lib/babeld/state"
Beispielkonfiguration
Diese Beispielkonfiguration kann so übernommen werden.
/etc/babeld.conf
# For more information about this configuration file, refer to # babeld(8) # Überschneidung der Tabellen für Source-Specific IPv4 Routing und der fff-Tabelle verhindern first-table-number 100 # Defaultwerte für die Schnittstellen setzen: default type tunnel max-rtt-penalty 128 #Schnittstellenspezifische Optionen setzen: #interface <IFNAME> type wired rxcost 4096 export-table 10 import-table 10 # redistribute rules ## Filter für lokalen Routen (siehe ip route show tab local), die im Babel announced werden. redistribute local ip 10.50.0.0/16 redistribute local ip 10.83.0.0/16 redistribute local ip fd43:5602:29bd::/48 redistribute local deny ## Filter für Routen aus fff, die announced werden sollen. redistribute ip 10.50.0.0/16 redistribute ip 10.83.0.0/16 redistribute ip fd43:5602:29bd::/48 local-port 33123
Die Interfaces, die babeld verwenden soll, müssen auch in der /etc/default/babeld eingetragen werden - durch Leerzeichen getrennt.
/etc/default/babeld
... # List of interfaces on which the protocol should operate INTERFACES="IFNAME1 IFNAME2 IFNAME3" ...
Routen die man manuell in die fff Table einträgt und redistributen (announcen) möchte, müssen mit proto static eingetragen werden. Dies gilt z.B. für die Routen in das Netz einer Hood oder auch für die default Route, so man diese announcen möchte. Beispiel:
... up ip route replace 10.x.x.x/yy dev $IFACE proto static table fff down ip route del 10.x.x.x/yy dev $IFACE proto static table fff ...
Abschließend muss der babeld-Dienst aktiviert und gestartet werden.
systemctl enable babeld systemctl start babeld
IP Adressen für Peering
IPv4
Es sollte für jedes Interface die selbe Adresse verwendet werden, um IP Adressen zu sparen. Die Adressen sollten in folgendem Netz liegen und reserviert werden: https://wiki.freifunk-franken.de/w/Portal:Netz#10.83.252.0.2F22_.28Master_IPs.29
Dabei ist es am sinnvollsten die Adresse als /32 an das Interface zu hängen und Babel die Routen übernehmen zu lassen. Hierbei ist es dann auch egal, aus welchem der beiden Prefixe die Adresse stammt (10.83.x.y bzw. 10.50.x.y). Außerdem ist es bei dieser Konfiguration ebenfalls nicht nötig, die Adresse des Partners als Pointopoint anzuhängen.
ACHTUNG: Es ist dann ebenfalls (erstmal) nicht möglich, den Partner direkt zu pingen, da bei dieser Konfiguration keine passende Route in der main-Tabelle existiert!
IPv6
Für IPv6 gilt in etwas das gleiche. Für das Routing ist eine Link Local Adresse nötig. Bei Ethernet und Layer2 Tunneln wird diese automatisch aus der Mac Adresse gebildet. Bei Layer3 Tunneln muss diese ggf. manuell generiert und als /64 an das Interface gehangen werden.
Damit ein Router sinnvoll auf ICMPv6 antworten kann, ist außerdem eine Adresse aus dem fc00::/7 oder eine öffentliche IPv6 nötig. Dafür kann beispielsweise eine IP aus diesem Netz verwendet werden.
Diese Adresse kann dann einfach an das Loopback Interface (oder ein anderes passendes Interface) gehängt werden. Für die Peeringinterfaces genügt die Link Local Adresse.
macvtap
Ist das Interface in einer VM, die macvtap auf dem Host verwendet, um ein physikalisches Interface zu verwenden, kann es Probleme mit Multicast geben. (gilt nicht bei GRE (das verwendet ja auch kein macvtap :P) in einer VM sondern nur wenn das physikalische Interface verwendet wird, also eth0 oder eth1.6 oder... in den meisten Standardfällen daher uninteressant).
Näheres hier
In libvirt kann die Option trustGuestRxFilters='yes' an das entsprechende Interface gepackt werden, damit Multicast funktioniert:
<interface type='direct' trustGuestRxFilters='yes'> <source dev='enp1s0' mode='vepa'/> <model type='virtio'/> [..] </interface>
local-port
Mithilfe der Option "local-port" kann babeld einen lokalen TCP Socket öffnen, über den von babeld Statusinformationen abgefragt werden können. Dieser Socket ist dann unter ::1 (IPv6 Localhost) erreichbar.
Mithilfe von netcat kann eine TCP Verbindung aufgebaut werden. Vorsicht: netcat muss IPv6 unterstützen, um sich mit ::1 verbinden zu können. netcat-traditional kann das nicht. Daher muss ggf. netcat-openbsd installiert werden.
$ nc ::1 33123 BABEL 1.0 version babeld-1.8.5 host aquarius.sgstbr.de my-id 50:7e:d5:d3:7b:46:59:7a ok
Schickt man ein "dump" an den Server, antwortet der Server mit allem, was er so weiß.
$ nc ::1 33123 BABEL 1.0 version babeld-1.8.5 host aquarius.sgstbr.de my-id 50:7e:d5:d3:7b:46:59:7a ok dump add interface ens7 up true ipv6 fe80::5054:ff:fe81:f31b add interface gre_nue2gw1 up true ipv6 fe80::a04b:9c94:2ab9:555e ipv4 10.83.252.31 [..]
- interface beschreibt Interfaces, für die babeld konfiguriert ist
- neighbour beschreibt Nachbarn, die babeld auf einem Interface sieht
- xroute beschreibt Routen, die babeld selbst announced
- route beschreibt Routen, die babeld von einem Nachbar sieht
Mehr zum local-port kann in der man-Page nachgelesen werden.
Selbstverständlich kann man auch die Ausgabe von netcat in ein anderes Programm wie "grep" pipen. Die Eingabe von "dump" (auf stdin) funktioniert wie gewohnt.
$ nc ::1 33123 | grep xroute dump add xroute 10.83.252.0/32-::/0 prefix 10.83.252.0/32 from ::/0 metric 0 add xroute fd43:5602:29bd:ffff::42/128-::/0 prefix fd43:5602:29bd:ffff::42/128 from ::/0 metric 0
Testen der Konfiguration
Es kann in der Routingtabelle geguckt werden ob hier bereits Routen vorhanden sind:
ip route show tab fff ip -6 route show tab fff
Wie oben beschrieben kann mithilfe des local-port der aktuelle Status von babeld abgefragt werden.
Dabei sollte vor allem geschaut werden, ob
- alle Interfaces, auf denen babeld Routen austauschen soll gelistet sind
- alle Nachbarn gelistet sind und deren rx/txcost und "reach" normal sind
- alle Routen gelistet sind, die selbst announced werden sollen
- Routen von Nachbarn sichbar sind.
Richtlinien für Babel Penalty (rxcost)
- Tunnel zwischen Routern in Rechenzentren: 96
- Ethernet: 96
- Richtfunk
- >100Mbit: 256
- 30-100Mbit: 512
- 10-30Mbit: 1024
- bis 10Mbit: 4096
- Tunnel: 4096 - 16384
Je nach Situation können Links auch schlechter hier angegeben bewertet werden. Auf eine Aufwertung sollte jedoch verzichtet werden. Pro Link sollte maximal 16384 verwendet werden, damit auch bei vielen Hops das Maximum von 65535 nicht erreicht wird.
Begründung:
Wir wollen Richtfunkverbindungen (z.B. Marterlach -> St. Markus -> Hardhöhe -> Neunhof) gegenüber VPN (z.B. Marterlach -> per VPN zu einem HetznerGW -> per VPN nach Neunhof) bevorzugen, obwohl der Weg mehr Hops hat.
Metriken anpassen
Default Route auf einen Server bevorzugen
Die Kosten für eine Route können nicht per Filter verringert werden, sonst wäre das System nicht mehr Loopfrei. Es können aber stattdessen alle anderen Routen entsprechend teurer gemacht werden.
Dies erreicht man durch einen Filter in der Babel Config.
Es wird ein Inputfilter benötigt, der auf ip 0.0.0.0/0 eq 0 greift. Das bedeutet, dass der Filter für alle Routen gilt, die innerhalb von 0.0.0.0/0 liegen (also _alle_ Routen) und die Prefixlänge 0 haben.
Dann muss das zu bevorzugende Interface ohne zusätzliche Penalty (== Kostenerhöhung) hinzugefügt werden.
Die Regeln werden analog zu iptables von oben nach unten abgearbeitet, beim ersten Match die passende Aktion ausgeführt.
in ip 0.0.0.0/0 eq 0 if IFNAME1 allow in ip 0.0.0.0/0 eq 0 if IFNAME2 metric 384 in ip 0.0.0.0/0 eq 0 metric 2048
Weitere Details finden sich in der Babeld Man-Page:
man babeld
Route die man announced abwerten
Es ist auch möglich, routen die man extern announced abzuwerten um darüber weniger wahrscheinlich ausgewählt zu werden.
out ip 10.83.x.x/22 eq 22 metric 512
Bedeutung: Routen die innerhalb 10.83.x.x/22 liegen und exakt Prefixlänge 22 haben, die an Nachbarn weitergegeben werden sollen (out), bekommen 512 Kosten zusätzlich und werden dann weitergegeben.
Filter Regeln
Public IPv6
Auch öffentliche IPv6 Adressen, die innerhalb des Freifunks verwendet werden, müssen im Babel Netz announced werden. Dazu müssen sie im Filter freigeschaltet werden. Dies kann z.b. mit folgenden Abschnitt in der /etc/babeld.conf gemacht werden:
[...] redistribute local ip 2001:db8:aaaa::/56 .. redistribute ip 2001:db8:aaaa::/56 [...]
Es handelt sich hier nur um Filterregeln. Alles was innerhalb das hier eingetragenen Subnetzes als "proto static" in die Routingtabelle eintragen wird, wird Babel an seine Nachbarn announcen.
WebUI für Babel
Die Installation eines WebUIs ist nicht für den Betrieb eines Gateways nötig, kann aber hilfreich sein
Simple-Babelweb
Simple-Babelweb ist eine sehr einfache PHP Seite, die den Babeld local-port auswertet und die Routen als Webseite darstellen kann. Das PHP Script findet man hier: https://github.com/rohammer/Simple-Babelweb
Die Installation funktioniert analog zu jeder anderen PHP-basierten Webseite.
Simple-Babelweb ist eine Eigenentwicklung der Freifunk Franken Community. Es wird aktiv dran weiter entwickelt.
Beispiel: http://fff-jupiter.fff.community/Simple-Babelweb/
Es ist auch ein einfaches Looking Glass https://de.wikipedia.org/wiki/Looking_Glass_(Internet) integriert.
Babelweb 0.4.0
Babelweb wird nicht mehr gepflegt und ist relativ langsam. Wenn ein WebUI für die Anzeige von Routen gewünscht ist, sollte die PHP Version von oben verwendet werden.
Für Babel gibt es ein WebUI. Quellen: https://github.com/kerneis/babelweb
Hinweis: Laut E-Mail von Gabriel Kerneis wird babelweb nicht mehr gepflegt, stattdessen wird der Nachfolger BabelWeb2 https://github.com/Vivena/babelweb2 weiter entwickelt! (Der folgende Text bezieht sich noch auf das ursprüngliche Babelweb 0.4.0.)
Installation:
apt install nodejs-legacy npm npm install -g babelweb
/etc/systemd/system/babelweb.service:
[Unit] Description=babelweb [Service] ExecStart=/usr/local/bin/babelweb Type=simple [Install] WantedBy=multi-user.target
Der Dienst wird registriert und gestartet mit
systemctl enable babelweb systemctl start babelweb
Modifikationen (optional):
Die Dokumentation von Babelweb empfiehlt, das Programm nicht als "root" laufen zu lassen. Manche möchten die Webseiten lieber über einen anderen Port als 8080 erreichen, zum Beispiel über Port 80. Leider benötigt BabelWeb root Rechte, um auf Ports < 1024 zuzugreifen (ein Linux-Feature). Beispiel, hier für einen eingeschränkten Benutzer "normalo" und Port 7070:
[Unit] Description=babelweb [Service] ExecStart=/usr/local/bin/babelweb port=7070 User=normalo Type=simple [Install] WantedBy=multi-user.target
Die Webseite optisch umgestalten ist auch möglich, der Einstiegspunkt ist
vi /usr/local/lib/node_modules/babelweb/static/index.html
Nach Änderungen in der Datei "babelweb.service" muss diese neu eingelesen werden mit
systemctl daemon-reload systemctl restart babelweb
Remote Server einbinden
Es muss ein SSH forwarding zu dem remote Gerät eingerichtet werden, gut erklärt in der Babel Doku: https://github.com/kerneis/babelweb/blob/develop/README.md unter "Monitoring remote babel instances". Danach die Datei server.js anpassen z.b.
[...] "routers" : "[::1]:33123,[::1]:33124,[::1]:33125", [...]
Achtung, keine Leerzeichen vor oder nach dem Komma benutzen!
Problem mit dem neuen Node
In Debian 9 wird keine vollwertige Node Version mehr angeboten, und das Node 0.x aus Debian 8 ist voller Sicherheitslücken. Abhilfe schafft der Download einer aktuellen Version aus Git, hier Node.js 8 LTS (Support bis mindestens Dezember 2019).
apt-get install curl curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - apt-get install -y nodejs npm install -g babelweb
Hinweis: Der Startlink ist nach dieser Installation "/usr/bin/babelweb", dies muss in /etc/systemd/system/babelweb.service gegenüber der Beschreibung im Absatz "WebUI für Babel" geändert werden.
Die letzte Babelweb Version 0.4.0 wurde bereits an die akuellen Node Versionen (>= 7) angepasst, aber eine Programmzeile vergessen. Deshalb muss eine Quellcode-Datei bearbeitet werden. Weiter entwickelt wird jetzt BabelWeb2, s.o.
vi /usr/lib/node_modules/babelweb/node_modules/policyfile/lib/server.js
Dort muss Zeile 254 geändert werden. Vorher:
Object.keys(process.EventEmitter.prototype).forEach(function proxy (key){
Nach Korrektur:
Object.keys(require('events').prototype).forEach(function proxy (key){
Quelle: https://github.com/LearnBoost/websocket.io/issues/55
Animation los werden
Ohne Animation lädt die Seite wesentlich schneller und auf schwachen Rechnern/Handys läuft die nicht gut. In
/usr/local/lib/node_modules/babelweb/static/index.html
folgende Zeilen auskommentieren:
</head> <body> <h1>BabelWeb</h1> <!-- <h2>Routers</h2> <div id="fig"> <p class="legend"> <span class="legend-title">Legend</span> <span class="legend-current">Current</span> <span class="legend-neighbour">Neighbours</span> <span class="legend-other">Others</span> </p> </div> --> <h3>Configuration</h3>