Freifunk Supernode/Gateway
In this tutorial, I will provide a script to setup a Freifunk Supernode/Gateway for personal usage. We will use Wireguard as VPN and batman-adv with compat 15
# installs latest version
apt install batctl
# batctl still includes old BATMAN IV.. even if taken from backports
# manually build batman-adv
git clone https://github.com/open-mesh-mirror/batman-adv.git
cd batman-adv
apt install linux-libc-dev
make
make install
# load kernel module
modprobe batman-adv
# check if loaded
dmesg | grep batman_adv
# see version
batctl -v
echo batman-adv >> /etc/modules
#echo 1 > /proc/sys/net/ipv4/ip_forward
sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
sudo sysctl -p
Für Wireguard muss dem Server pro verbindenden Peer ein Public-Key bekannt gemacht werden, damit sich ein Client verbinden kann. Dazu wurde von Freifunk-KBU ein REST-Dienst geschrieben, welcher ähnlich wie bei mullvad VPN funktioniert. Freifunk-Dresden auch. awlnx von Freifunk-MUC hat mit wgkex einen verteilten Dienst geschrieben, der das selbe Problem löst. Freifunk-Franken nutzt Wireguard, jedoch nicht für die normalen Router-Nodes. Freifunk Regensburg hat den wgkex geforked und ohne MQTT im Einsatz
Sources:
Wireguard konfigurieren
Die Upstream-Gluon-Version ist zu großen Teilen statisch zu konfigurieren. Bisher gibt es keine Broker-URL, die Public-Keys müssen manuell verteilt werden. https://github.com/freifunkMUC/site-ffm/issues/169
/etc/wireguard/wg-ffac_welt.conf
[Interface]
Address = 192.168.17.1/24,fe80::11/64
ListenPort = 51820
PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
PreUp = iptables -A POSTROUTING -o ens160 -j MASQUERADE -t nat; ip6tables -t nat -A POSTROUTING -o ens160>
PreDown = iptables -D POSTROUTING -o ens160 -j MASQUERADE -t nat; ip6tables -t nat -D POSTROUTING -o ens1>
[Peer]
PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
AllowedIPs = fe80::1/64
Entsprechend zum Testen auch der client:
[Interface]
PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
Address = 192.168.17.4/32, fd42:42:42::4/128
#DNS = 9.9.9.9
[Peer]
PublicKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
Endpoint = example.de:51820
AllowedIPs = 0.0.0.0/0, ::/0
Anschließend kann man vom Client einen ping an 192.168.17.1 durchführen und landet auf dem server. Auch Ping ans Internet sollte klappen, wenn nicht fehlt vielleicht ipv4/ip_forward siehe oben.
Batman und VXLAN konfigurieren:
Die VNI, praktisch das VLAN-Tag von VXLAN berechnet sich aus:
domain_seed_bytes("gluon-mesh-vxlan", 3)
# BatmanV - compat 15 - Interface automatisch beim boot starten
auto bat0
# batman interface configuration
iface bat0 inet manual
# https://dokuwiki.nausch.org/doku.php/centos:ansible:ffmuc-rpb4-ol
pre-up /usr/sbin/batctl ra BATMAN_V
# interface anlegen
pre-up ip link add $IFACE type batadv
up ip link set up dev $IFACE
post-down ip link del $IFACE
# iif rules
post-up ip -4 rule add iif $IFACE prio 200 table ffac
pre-down ip -4 rule del iif $IFACE prio 200 table ffac
post-up ip -6 rule add iif $IFACE prio 200 table ffac
pre-down ip -6 rule del iif $IFACE prio 200 table ffac
# https://wiki.freifunk-franken.de/w/Freifunk-Gateway_aufsetzen/Batman-adv
auto wg-ffac_welt
iface wg-ffac_welt inet static
requires ens160
use wireguard
address 192.168.17.1/24
auto vx-ffac_welt
iface vx-ffac_welt inet manual
# 2293484 from lua -e 'print(tonumber(require("gluon.util").domain_seed_bytes("gluon-mesh-vxlan", 3), 16))'
pre-up ip l a dev $IFACE type vxlan id 2293484 dstport 4789 udp6zerocsumtx udp6zerocsumrx #ohne local address fe80::1
# udp6zerocsumtx udp6zerocsumrx copied from https://www.open-mesh.org/doc/devtools/Mixing_VM_with_gluon_hardware.html
pre-up ip l s dev $IFACE mtu 1422
pre-up ip addr add fe80::1/64 dev vx-ffac_welt
#address fe80::1/64
post-up batctl -m bat0 if add $IFACE
pre-down batctl -m bat0 if del $IFACE
post-down ip l d dev $IFACE
NAT lässt sich aktivieren mit:
iptables -t nat -A POSTROUTING -o ens160 -j MASQUERADE
Dadurch soll der Router auch direkt auf Internet zugreifen können.
VXLAN testen
Auf dem Server ist bereits im vxlan-Interface die Adresse fe80::1 konfiguriert, wie es das gluon-package verlangt.
Falls nicht: ip addr add fe80::1/64 dev vx-ffac_welt
Der Test-Client muss mit dem Wireguard verbunden sein (überprüfen mit wg
auf server und client) und weiterhin folgende Befehle bekommen:
# 2293484 from lua -e 'print(tonumber(require("gluon.util").domain_seed_bytes("gluon-mesh-vxlan", 3), 16))'
#ip link add vxlan1 type vxlan id 2293484 remote 192.168.17.1 dstport 4789 dev wg-ffac
ip -6 link add vxlan1 type vxlan id 2293484 remote fe80::1%wg_mesh dstport 4789
ip link set vxlan1 up
ip addr add fe80::2/64 dev vxlan1
Dabei muss wg_mesh
der Name der aktiven Wireguard-VPN Verbindung sein.
Anschließend sollte mit ping fe80::1%vxlan1
eine Verbindung zum Server im VXLAN erreicht werden können. (aktuell nicht)
verteiltes Gateway
Anschließend muss der wgkex (verteilt) oder wgskex (single Gateway) installiert werden. Alternativ eine andere Lösung zur manuellen Public-Key Verteilung erfolgen.
Ein neuer Client sollte seinen publickey dann mit http://wg-server:5000/api/v1/wg/key/exchange im Server eintragen.
Anschließend sollte sich der Client mit dem Wireguard-Tunnel (Layer 3) verbinden können. Darin liegt das VXLAN (Layer 2), worin wiederum BATMAN (Layer 2) gesprochen wird.
Ein Gluon-Client sollte anschließend das gluon-mesh-vpn-wireguard paket installieren und sich mit dem entsprechenden Endpunkt verbinden.
Update 08.03
Verbindung klappt, VXLAN-Konfiguration ist erfolgt, Ping geht noch nicht.
Gluon-Client mit entsprechenden Paketen wurde gebaut.
Update 16.03
Installation von BATMAN_V hinzugefügt, Konfiguration bisher noch kaputt
Wireguard einmal kaputt konfiguriert
Vom Server aus klappt:
ping fe80::274:dfff:fe40:e8e0%wg-ffac_welt
Vom Client aus klappt:
ping fe80::1%wg_mesh
Allerdings kein VXLAN, auch nicht durch manuelles Anlegen der Interfaces.
Update 21.03
Durch händische Konfiguration auf einem nicht-gluon Client, hat es nun geklappt:
Wireguard-Konfiguration mit:
Address = fe80::5/128
AllowedIPs = 192.168.17.1/24, fe80::1/64
Dann
# passende ip addresse anlegen, damit vxlan remote addresse klappt
ip addr add 192.168.17.2 dev wg-ffac
# neues vxlan auf dem client anlegen
ip link add vxlan10 type vxlan id 2293484 remote 192.168.17.1 dstport 4789
# ip addresse hinzufügen
ip addr add fe80::20/64 dev vxlan10
# interface aktivieren
ip link set up vxlan10
Ein ping 192.168.17.1
klappt im wg interface und nun klappt auch ping fe80::1%vxlan10
bzw andersrum ping fe80::20%vx-ffac_welt
Na schön, mit nicht lokalen Addressen kann der remote korrekt konfiguriert werden. Wie kriegt man das nun mit link-local addressen verbastelt?
Es scheint, als würden die anderen immer mit pyroute eine neue route und irgendwie einen FDB Eintrag hinzufügen: https://github.com/freifunkh/wireguard-vxlan-glue/blob/master/netlink.py#L147
Die man-page sagt, das remote-Kommando
specifies the unicast destination IP address to use in outgoing packets when the destination link layer address is not known in the VXLAN device forwarding database
FDB steht also für Forwarding Database und das setzen des remotes wird einfach umgangen indem ein sinnvoller fdb eintrag angelegt wird. Aber wie klappt das manuell?
Update 29.03
interface_linklocal() {
# We generate a predictable v6 address
local macaddr="$(echo $(uci get wireguard.mesh_vpn.privatekey | wg pubkey) |md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/')"
local oldIFS="$IFS"; IFS=':'; set -- $macaddr; IFS="$oldIFS"
echo "fe80::$1$2:$3ff:fe$4:$5$6"
}
bridge fdb append to 00:00:00:00:00:00 dst $(link_local $1) dev vx-welt
und
ip ro add $(link_local $1) dev wg-ffac_welt
https://github.com/freifunk-gluon/community-packages/pull/6#issuecomment-681118964
die IP-Adresse ist die vom (über wireguard) verbundenen Gluon-Node
Die Antwort ist:
RTNETLINK answers: Address family not supported by protocol
Dann muss man überall sicherstellen, dass ip -6
verwendet wird. Dann klappt das auch.
Update 18.06
Eine allgemeine Anleitung auf Basis von Ansible zur Errichtung eines Supernodes habe ich nun hier veröffentlicht:
https://github.com/maurerle/ff-supernode
Dies ist stark inspiriert von https://github.com/freifunkh/ansible und soll den Umstieg für andere Communities erleichtern
Weitere TODOs
-
Wie kann automatische Segmentierung bestehender Knoten funktionieren, um kleinere Mesh-Wolken zu erzeugen?
- anhand location kann segment gesetzt werden - dadurch wird dann die Freifunk-Domain entschieden
- neuer wg-autosegmenter schreibt in wg-peers repo rein und schiebt keys zwischen den domains hin und her
- zugehöriger public Key darf nur in eine Domain rein und wird vom wg-autosegmenter verwaltet
- Nachteil: Nutzer kann seine Domain nicht selber setzen, sondern nur anhand location und nachbarn hoffen, korrekt gesetzt zu werden
-
Handhabung alter Router (Release eine letzten Gluon-2020.x version zum Upgrade der alten Firmware)
-
automatisierte Verteilung der Wireguard Public-Keys (nutzung eines Git-Repos - ermöglicht automatisierung und manuellen flow)
Quellcode:
Quellcode zum Bauen befindet sich hier: https://github.com/maurerle/site