Bootstrapping einer neuen Freifunk-Infrastruktur

Im folgenden beziehe ich mich auf externe Quellen und beschreibe, wie man mit deren Hilfe relativ flott eine startfähige Freifunk-Infrastruktur auf die Beine stellen kann — und wo sich ggf. die Beine brechen ;)

Unter »Freifunk-Infrastruktur« verstehe ich hier primär die Netzinfrastruktur, damit sich Knoten und Clients anmelden können. Die Außendarstellung notwendigen Dinge wie Webpräsenz, Maillinglisten usw. behandelt ein späterer Artikel (wenn auch nur annährend im Tempo dieses – gestartet Anfang Juli –, dann noch knapp in 2015 ;)).

Wie ein aktuelles Freifunknetz grundsätzlich funktioniert, hatte ich schon verbloggt.

Vorbereitungen

Wer mit dem Gedanken, eine Freifunk-Community zu gründen spielt, findet unter freifunk.net gute Startinformationen. Wenn’s dann an die Technik geht: IPv6 ULA (»eindeutige lokale IPv6-Adressen«; quasi das 10/8 von IPv6) würfeln, am besten bei Sixxs, aus dem /48 dann /64 machen und sich die ersten 10 davon irgendwo aufschreiben, notfalls in eine Excel-Tabelle.
Dann auf die Freifunk-IP-Adressverwaltung gehen und sich ein freies(!) /16 an IPv4-Adressen raussuchen. Für Gütersloh war ich einerseits zu faul, mitten drin nach einem freien zu suchen, zum anderen arbeite ich bei einer Firma, deren interne Adressen sämtlich aus dem RFC-1918-Bereich stammen: 10.255 habe ich da aber noch nicht in Benutzung gesehen, also habe ich zugeschlagen ;) Generell sollte man auch andere reservierte IPv4-Bereiche nutzen können, allerdings mag man später auf Probleme stoßen, wenn man sich mit anderen Freifunknetzen verbinden möchte.
Hat man also einen freien Addressraum, diesen, bitte an der richtigen Stelle, eintragen — als angehender Freifunker sollte man sich schon am Wiki registriert haben … Neben IPv4 bitte auch IPv6 (ULA von eben) und weitere gewünschte Daten eintragen.

Firmwarebasis

Wie gesagt, Stand der Dinge ist eine fastd/batman-adv-Wolke, mit der Lübecker Gluon-Firmware ist der Start recht einfach.

Gluon, site-example auschecken, site-example in site umbenennen, Daten anpassen, make, Kaffee/Bier/Club Mate trinken gehen. Am Ende stehen i. d. R. schon brauchbare Images.

Gluon-Gateway aufsetzen

Ein großes Lob an die Kollegen von Freifunk Hannover, deren Beschreibung der Schritte im Wiki mir als Vorlage diente — und die leider nicht mehr abrufbar ist. Tja, so ist das, wenn man an einem Artikel knapp 3 Monate herumeditiert ;) Eine ebenfalls praktische Vorlage gibt’s im Wiki der Kollegen aus Hamburg, und auch die Kollegen aus dem 3-Länder-Eck haben jüngst über das Setup Ihrer Server gebloggt.

Hier, primär für das lokale Setup als Gedächtnisstütze, ein quasi-log der Kommandos am Beispiel von gw03 (einer gespendeten KVM-Instanz):

root@gw03:~# echo "deb http://repo.universe-factory.net/debian/ sid main" >>/etc/apt/sources.list
root@gw03:~# gpg --keyserver pgpkeys.mit.edu --recv-key 16EF3F64CB201D9C
root@gw03:~# gpg -a --export 16EF3F64CB201D9C | apt-key add -
root@gw03:~# apt-get update
root@gw03:~# apt-get -y install vim sendmail ; apt-get -y purge nano exim ; apt-get -y install batctl batman-adv-dkms fastd bridge-utils git radvd openvpn iptables-persistent dnsmasq build-essential debhelper dnsutils bind9-host traceroute tcpdump libjansson-dev libjansson4 libz-dev vnstati apache2 

Nicht alles davon ist notwendig; ich hasse allerings nano und mag smail exim nicht sonderlich … vnstati und apache installiere ich gleich mit für die am Ende einzurichtende Trafficseite. Und da alfred, batadv-vis sowie alfred-json nicht in Paketform vorliegen, schadet es nicht, sich auch eine Build-Umgebung zu installieren.

root@gw03:~# echo >> /etc/modules "batman-adv"
root@gw03:~# mkdir /etc/fastd/ffgt-mesh-vpn/
gw01:~# rsync -av --progress --rsh="ssh -i /root/.ssh/fastd-rsync" /etc/fastd/ffgt-mesh-vpn/peers/* gw03:/etc/fastd/ffgt-mesh-vpn/peers/ ; rsync -av --progress --rsh="ssh -i /root/.ssh/fastd-rsync" /etc/fastd/ffgt-mesh-vpn/backbone/* gw03:/etc/fastd/ffgt-mesh-vpn/backbone/

Wir sparen uns derzeit das eigene git-Repository für unsere Schlüssel und rsyncen per ssh (später Umstellung geplant auf rsync via fastd-Tunnel). Eine Kom­plexi­täts­ebene we­ni­ger; später macht git sicher Sinn, aber es muß eben eine weitere Soft­ware­kom­po­nen­te auf­ge­setzt und ge­pflegt wer­den.

root@gw03:~# cat <<EOF >/etc/fastd/ffgt-mesh-vpn/fastd.conf
log to syslog level debug;
interface "ffgt-mesh-vpn";
method "salsa2012+gmac";
bind 0.0.0.0:10000;
hide ip addresses yes;
hide mac addresses yes;
include "secret.conf";
mtu 1426;
include peers from "peers";
include peers from "backbone";
on up "
    ifup bat0
    ip link set address de:ca:fb:ad:03:01 up dev \$INTERFACE 
";
EOF

Bei einem neuen GW wäre in etwa folgende Sequenz notwendig …

root@gw05:~# fastd --generate-key >/etc/fastd/ffgt-mesh-vpn/`uname -n`.tmp
2014-10-24 23:35:41 +0200 --- Info: Reading 32 bytes from /dev/random...
root@gw05:~# awk </etc/fastd/ffgt-mesh-vpn/`uname -n`.tmp '/^Secret:/ {printf("secret \"%s\";\n", $2);'} >/etc/fastd/ffgt-mesh-vpn/secret.conf
root@gw05:~# awk </etc/fastd/ffgt-mesh-vpn/`uname -n`.tmp '/^Public:/ {printf("key \"%s\";\n", $2);'} >/etc/fastd/ffgt-mesh-vpn/`uname -n`

… da wir für unsere GWs die Keys allerdings vorgeneriert haben (derzeit für 4 GWs), um sie vorab in der Firmware zu hinterlegen (Henne-Ei-Problem), wird hier nur der Schlüssel für gw03 per cut & paste eingetragen:

root@gw03:~# echo "secret \"12...ef\";" >> /etc/fastd/ffgt-mesh-vpn/secret.conf ; chmod go-r /etc/fastd/ffgt-mesh-vpn/secret.conf
root@gw03:~# cat <<EOF >>/etc/network/interfaces
# Freifunk
auto br-ffgt
iface br-ffgt inet6 static
    bridge-ports none
    address fd42:ffee:ff12:0aff:0301:0000:0000:0001
    netmask 64
iface br-ffgt inet static
    address 10.255.3.1
    netmask 255.255.0.0
allow-hotplug bat0
iface bat0 inet6 manual
    pre-up modprobe batman-adv
    pre-up batctl if add ffgt-mesh-vpn
    up ip link set \$IFACE up
    post-up brctl addif br-ffgt \$IFACE
    post-up batctl it 10000
    post-up /sbin/ip rule add from all fwmark 0x1 table 42
    pre-down brctl delif br-ffgt \$IFACE || true
    down ip link set \$IFACE down
EOF

/usr/local/bin/check_gateway schenke ich mir hier, ebenso die OpenVPN-Einrichtung. Bißchen was soll ja auch noch zu tun bleiben ;) Wobei, nachdem die Hannoveraner Seite ja nicht mehr existiert, /usr/local/bin/check_gateway sieht im Prinzip so aus:

#!/bin/bash
INTERFACE=eth1
shopt -s nullglob
 
ping -q -I $INTERFACE 8.8.8.8 -c 4 -i 1 -W 5 >/dev/null 2>&1
 
if test $? -eq 0; then
    NEW_STATE=server
else
    NEW_STATE=off
fi
 
for MESH in /sys/class/net/ff*/mesh; do
OLD_STATE="$(cat $MESH/gw_mode)"
[ "$OLD_STATE" == "$NEW_STATE" ] && continue
    echo $NEW_STATE > $MESH/gw_mode
    echo 54MBit/54MBit > $MESH/gw_bandwidth
    logger "batman gateway mode changed to $NEW_STATE" 
done

In INTERFACE steht normalerweise der Name des VPN-Interfaces, über jenes wird dann versucht, Googles Nameserver (8.8.8.8) anzupingen, um die grundlegende Funktion des VPN-Tunnels zu verifizieren. Im Erfolgsfalle werden die Mesh-Interfaces von batman_adv in den “server”-Modus geschaltet, was faktisch bedeutet, daß dieser Rechner als (IPv4-) Gateway im batman_adv-Netz bekannt gemacht wird.

Internet-Gateway-Einrichtung wiederum haben die 3-Länder-Eck-Kollegen ganz gut beschrieben ;)

Wie gesagt, statt isc-dhcp-server verwendet ich hier nur dnsmasq, sowohl für DHCP als auch für DNS, das Setup sollte erst einmal ausreichen. Besonderheit im folgenden: da gw03 im gleichen DC wie gw01 steht, bekommen die Clienten von gw03 gw01 als Defaultadresse, gw01 hat(te damals; mittlerweile haben wir die Auslands-VPNs abgeschafft!) einen OpenVPN-Tunnel gen Holland, gw03 b. a. w. nicht.

root@gw03:~# cat <<EOF >/etc/dnsmasq.conf 
server=8.8.8.8@eth0
# forward tlds via local
server=/ffgt/10.255.1.1
# ffgt reverse via local
server=/255.10.in-addr.arpa/10.255.1.1
server=/0.a.f.f.2.1.f.f.e.e.f.f.2.4.d.f.ip6.arpa/10.255.1.1
# Only on the mesh bridge
interface=br-ffgt
bind-interfaces
except-interface=lo
listen-address=10.255.3.1
domain-needed
cache-size=4096
strict-order
no-resolv
no-hosts
domain=ffgt
dhcp-range=10.255.3.10,10.255.3.200,255.255.0.0,1h
dhcp-option=3,10.255.1.1
EOF

Im Endeffekt bedeutet daß, daß gw03 zwar IPs vergibt, der Traffic aber direkt zu gw01 gehen sollte (da das alles ein /16er IPv4-Netz ist und das Netzwerk auf Layer 2 vermascht ist). Mal gucken, ob das so klappt ;)

root@gw03:~# cat <<EOF >/etc/radvd.conf 
interface br-ffgt
{    
    AdvSendAdvert on;
    MaxRtrAdvInterval 200;
    prefix fd42:ffee:ff12:0aff:0000:0000:0000:0000/64 {
    };
    RDNSS fd42:ffee:ff12:0aff:0101:0000:0000:0001 {
    };
};
EOF
root@gw03:~# sed -i -e 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' -e 's/#net.ipv6.conf.all.forwarding=1/net.ipv6.conf.all.forwarding=1/g' /etc/sysctl.conf
root@gw03:~# /sbin/iptables -t  mangle -A PREROUTING -i br-ffgt -j MARK --set-xmark 0x1/0xffffffff
root@gw03:~# /etc/init.d/iptables-persistent save
root@gw03:~# echo -e "42\tffgt" >>/etc/iproute2/rt_tables 
root@gw03:~# sed -i -e 's%^exit 0%# Freifunk\n/sbin/ip route add unreachable default table 42\n/sbin/ip rule add from all fwmark 0x1 table 42\nexit 0%g' /etc/rc.local

Zum guten Schluß noch die Trafficseite anlegen und per Proxy-Zugriff auf der Hauptwebseite verfügbar machen, fertig ist Gateway Nummer 3.

(Seit Beginn dieses Artikels (Juli 2014) hat sich einiges getan; die Grundlagen sind zwar noch die gleichen, aber im Detail hat sich, auch bei uns, einiges getan. Dazu in Kürze mehr …)