Freifunk-Gateway aufsetzen/babeld

Aus Freifunk Franken
Version vom 12. Mai 2019, 10:34 Uhr von Mifritscher (Diskussion | Beiträge) (→‎Installation: Anleitung fürs holen der aktuell empfohlenen Version)
Wechseln zu:Navigation, Suche

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 Hood A announced muss Hood A auch erreichen können.

Installation

Babel kann direkt aus der Distribution installiert werden.

apt-get install babeld

Debian liefert eine recht alte Version mit. Es ergibt Sinn Babel per apt zu installieren, es dann zu deinstallieren und danach und aus dem Git selbst zu bauen (Version >=1.8.2).

Empfohlen ist die Version 1.8.4 mit folgenden Patch https://github.com/jech/babeld/pull/28/commits/cd8a9ba8014688092060eebe4a67e92d9083099b

https://github.com/jech/babeld

Kurzanleitung fürs holen der aktuell empfohlenen Version:

git clone https://github.com/jech/babeld
cd babeld
git checkout babeld-1.8.4
git cherry-pick 68b6c5ec6d38e9d958c7387f171d0380878f67bf

Ä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-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.

systemd service für babeld

[Unit]
Description=babeld Routing Daemon
After=network.target

[Service]
Type=simple
EnvironmentFile=/etc/default/babeld
ExecStart=/usr/local/bin/babeld $INTERFACES
Restart=on-abort

[Install]
WantedBy=multi-user.target

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

#Falls einzelne Schnittstellen abweichend konfiguriert werden müssen:
#interface IF2 type wired rxcost 1234
#... einfach weiterführen für mehr Interfaces.


export-table 10
import-table 10

# redistribute rules
## Filter für lokalen Routen, 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
redistribute ip 10.50.0.0/16
redistribute ip 10.83.0.0/16
redistribute ip fd43:5602:29bd::/48

local-port 33123
#local-port-readwrite 34567 #funktioniert anscheinend nicht!


Man kann alle Peering-Interfaces mit default abfangen (wie oben geschehen) oder für jedes Peering-Interface eine eigene Zeile verwenden.


Die Interfaces, die babel verwenden soll müssen auch in der /etc/default/babeld eingetragen werden - durch Leerschläge getrennt.

/etc/default/babeld

...
# List of interfaces on which the protocol should operate
INTERFACES="GRE_Beispielinterface1 GRE_Beispielinterface2 WG_Beispielinterface1"
...


Routen die man manuell in die fff Table einträgt und redistributen (weiterverteilen) will, müssen als proto static eingetragen haben. Dies gilt z.b. für die Batman Routen oder auch für die default route (z.b. im VPN Up Script wenn man dies verwendet). Beispiel:

...
post-up ip route replace 10.X.X.X/XX dev $IFACE proto static table fff
...

IP Adressen für Peering

IPv4

Es sollte für jeden Server die selbe Adresse verwendet werden auf jedem Interface. Sinnvollerweise aus dem 10.83.252.X Netz: 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.

Sollte das Netz nicht alleine für diese Verbindung existieren, bietet es sich auch hier an, die Adresse einfach als /128 an das Interface zu hängen.


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.4-1-g6a0bd24
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.4-1-g6a0bd24
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) bei dezentralen Hoods

  • Ethernet: 96
  • Richtfunk
    • >100Mbit: 256
    • 30-100Mbit: 512
    • 10-30Mbit: 1024
    • bis 10Mbit: 4096
  • VPN: 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

Da es nicht möglich ist, im Babel die Route zu bevorzugen (sonst wäre das System nicht mehr Loopsicher), können wir nur alle anderen default routen abwerten.

Dies machen wir durch einen Filter in der Babel Config.

Wir brauchen einen Inputfilter, der auf ip 0.0.0.0/0 eq 0 greift. Dazu das bevorzugte Interface ohne Penalty und alle anderen mit einem Penalty. Das ganze kann z.b. so aussehen

in ip 0.0.0.0/0 eq 0 if IF1 allow
in ip 0.0.0.0/0 eq 0 if IF2 metric 384
in ip 0.0.0.0/0 eq 0 metric 2048

Zuerst wird auf das IF1 kein Penalty gegeben, danach auf IF2 ein Penalty von 384 und anschließend auf alle weiteren Interfaces ein Penalty von 2048.

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 ich mit der ip 10.83.x.x advertise/announce (out) mit exakt /22 Länge schlage metric 512 oben drauf

Filter Regeln

Public IPv6

Wenn man auch Public IPv6 Adressen vergeben möchte muss man diese im Babel Netz announcen. 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:bbbb::/64 </br>
redistribute ip 2001:DB8:aaaa:bbbb::/64
[...]

Hier kann auch ein /48 Bereich eingefügt werden. Es handelt sich hier nur um Filterregeln. Alles was innerhalb das hier eingetragenen Subnetzes als "proto static" in die Routingtabelle eintragen wird, wird Babel weiter announcen (damit die entsprechenden BorderGateways wissen wohin sie den Traffic schicken sollen)

WebUI für Babel

Babelweb 0.4.0

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>

Babelweb in PHP

Eine alternative ist das Babelweb in PHP

Einfach diese File herunterladen und in das Webroot eines Webservers packen. PHP muss installiert sein:

https://github.com/rohammer/Simple-Babelweb

Eigenentwicklung der Freifunk Franken Community und es wird aktuell auch aktiv dran weiter entwickelt.

Beispiel: http://fff-jupiter.fff.community/Simple-Babelweb/

Mittlerweile ist auch ein einfaches Looking Glass https://de.wikipedia.org/wiki/Looking_Glass_(Internet) integriert