Um BATMAN verwalten zu können müssen wir nun noch „batctl“ installieren.
# apt-key adv --keyserver hkps://keyserver.ubuntu.com --recv-key 04EE7237B7D453EC
# apt-key adv --keyserver hkps://keyserver.ubuntu.com --recv-key 648ACFD622F3D138
# echo "deb http://deb.debian.org/debian bullseye-backports main contrib non-free" | tee /etc/apt/sources.list.d/bullseye-backports.list
# apt update
# apt-get -t bullseye-backports install batctl
Anschließend überprüfen wir ob alles korrekt geladen wurde.
# batctl ra
Selected routing algorithm (used when next batX interface is created):
=> BATMAN_IV
Available routing algorithms:
* BATMAN_IV
* BATMAN_V
Nachdem bei Freifunk München BATMAN_V verwendet wird, sehen wir dass aktuell der falsche Routing Algorithmus ausgewählt ist. Das korrigieren einmal sofort manuell.
# batctl ra BATMAN_V
Eine erneute Abfrage zeigt nun auf den korrekten Routing Algorithmus BATMAN_V.
# batctl ra
Selected routing algorithm (used when next batX interface is created):
=> BATMAN_V
Available routing algorithms:
* BATMAN_IV
* BATMAN_V
Nun kommen wir zur Interface Konfiguration. In diesem Beispiel werden wir den RPi-Offloader im Segment „welt“ ansiedeln, deswegen benennen wir das zugehörige Interface br-welt
auch entsprechend. Hierzu benötigen wir noch die bridge-utils
, die wir uns noch installieren:
# apt install bridge-utils -y
Wir können mit nachfolgendem Befehl überprüfen, ob die Version von batctl
auch zur installierten Version von batman-adv
passt.
# batctl -v
batctl debian-2021.4-2~bpo11+1 [batman-adv: 2021.4]
Da beides in der Version 2021.4 vorliegt, können wir mit der weiteren Installation und Konfiguration wie gewohnt fortfahren.
In unserem Konfigurationsbeispiel wollen wir unseren Offloader im Segment ffmuc_welt betreiben und uns mit dem Gateway gw04 von Freifunk München verbinden. Demnach lauten die Daten für den VPN-Tunnelendpunkt:
Qualifier |
Value |
Domain: |
ffmuc_welt |
Hostname/Endpoint: |
gw04.ext.ffmuc.net |
Port: |
40011 |
(remote) publickey: |
BJHuqV8mXsS9AlAY+x/oi1AsQCm5aMTLOQvLprNZLRo= |
link-local-Adresse: |
errechnet sich aus dem nachfolgenden client_public.key |
(client) privatekey: |
wird mit Hilfe des binaries wg local generiert und in /etc/wireguard/client_private.key gespeichert. |
(client) publickey: |
wird mit Hilfe des binaries wg local generiert und in /etc/wireguard/client_public.key gespeichert. |
Wir erzeugen nun im ersten Schritt das Schlüsselpaar (private-/public-key) für unseren VPN-Client.
# wg genkey | tee /etc/wireguard/client_private.key | wg pubkey | tee /etc/wireguard/client_public.key
Im Konfigurationsverzeichnis von WireGuard finden wir nun beide Schlüssel. Die Dateiberechtigungen passen wir gleich mal noch an, damit nur der User root auf diese zugreifen kann.
# chmod 600 /etc/wireguard/*.key
Die link-local IPv6-Adresse unseres lokalen VPN-Entpunktes ermitteln wir mit Hilfe folgenden Befehls, nachdem wir den public.key zuvor erfolgreich erstellt hatten.
# cat /etc/wireguard/client_public.key | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/fe80::02\1:\2ff:fe\3:\4\5/' > /etc/wireguard/link-local
In unserem Konfigurationsbeispiel ergibt sich also aus dem öffentlichen Schlüssel HjDRCwE4Q7UPAKXrmM4s6VOgMK+HJZCixWTaVC8KiRU=
die link-local-Adresse fe80::02c5:ddff:fee7:823b
.
Zusammengefasst haben wir also nunmehr folgende Konfigurationsparameter:
Qualifier |
Value |
Domain: |
ffmuc_welt |
Hostname: |
gw04.ext.ffmuc.net |
Port: |
40011 |
(remote) publickey: |
BJHuqV8mXsS9AlAY+x/oi1AsQCm5aMTLOQvLprNZLRo= |
lokale link-local-Adresse: |
fe80::02c5:ddff:fee7:823b |
(client) privatekey: |
WOzTMy6u2Tad4hqBK9jn1KR5aMiu1ZDcD0KLHWlK9nY= |
(client) publickey: |
HjDRCwE4Q7UPAKXrmM4s6VOgMK+HJZCixWTaVC8KiRU= |
WICHTIG:
Der private Schlüssel unseres Clients (privatekey) ist natürlich nicht publik zu machen und ist nur hier im Rahmen dieses How2s abgedruckt, damit die weitere Konfiguration leichter zu verstehen ist. Im Relalife-Betrieb hüten wir diesen Schlüssel natürlich wie immer „wie unseren Augapfel“!
Damit nun das Gateway auch VPN-Verbindungen unseres WireGuard-clients akzeptieren kann benötigt dieses natürlich unseren public-key, den wir nun an das Gateway schicken müssen:
# wget -q -O- --post-data='{"domain": "ffmuc_welt","public_key": "HjDRCwE4Q7UPAKXrmM4s6VOgMK+HJZCixWTaVC8KiRU="}' http://broker.ffmuc.net/api/v1/wg/key/exchange
{"Message":"OK"}
Die Bestätigung „Message“:„OK“
zeigt uns, dass der Broker auf der Zielseite, also auf den Gatewasy unseren Pblic-key akzeptiert hat und diesen beim nachfolgenden Tunnelaufbau auch verwenden wird!
Damit nun der Broker vor dem Starten unseres Tunnels auch immer unseren öffentlichen Schlüssel hat, stellen wir nun noch sicher, dass dieser automatisiert vor dem Starten des WireGuard-Daemon einmal zum Broker|Gateway übertragen wird. Hierzu legen wir uns ein systemd-Startscript an.
# vim /etc/systemd/system/broker.service
- /etc/systemd/system/broker.service
# Django : 2020-12-15
[Unit]
# see man systemd.unit
Description=Inform tunnel about our wireguard-public key
Documentation=https://wiki.mailserver.guru/doku.php/centos:ansible:ffmuc-rpb4-ol
Before=wg-quick.target
[Service]
# see man systemd.service, systemd.exec
ExecStart=/usr/bin/wget -q -O- --post-data='{"domain": "ffmuc_welt","public_key": "HjDRCwE4Q7UPAKXrmM4s6VOgMK+HJZCixWTaVC8KiRU="}' http://broker.ffmuc.net/api/v1/wg/key/exchange
StandardOutput=syslog
StandardError=syslog
[Install]
WantedBy=default.target
Damit systemd von unserem neuen Startscript Kenntnis hat, führen wir einen relaod des selbigen durch.
# systemctl daemon-reload
Zum Starten verwenden wir den bekannten Mechanismus von systemd
. Den manuellen Start führen wir mit Hilfe des nachstehenden Befehls aus.
# systemctl start broker.service
Damit der Daemon beim Neustart entsprechend automatisch gestartet wird, setzen wir den Dienst auf enabled
# systemctl enable broker.service
Created symlink /etc/systemd/system/default.target.wants/broker.service → /etc/systemd/system/broker.service.
Was unser Client noch benötigt ist eine rudimentäre Konfigurationsdatei für unseren WireGuard-client, die wir nun als nächstes anlegen müssen.
# vim /etc/wireguard/wg-welt.conf
- /etc/wireguard/wg-welt.conf
# Django : 2020-12-15
[Interface]
PrivateKey = WOzTMy6u2Tad4hqBK9jn1KR5aMiu1ZDcD0KLHWlK9nY=
Address = fe80::02c5:ddff:fee7:823b
[Peer]
PublicKey = TszFS3oFRdhsJP3K0VOlklGMGYZy+oFCtlaghXJqW2g=
AllowedIPs = fe80::27c:16ff:fec0:6c74
Endpoint = gw04.ext.ffmuc.net:40011
PersistentKeepalive = 2
Als ersten Test starten wir nun den WireGuard-Tunnel und fahren diesen mit Hilfe des Befehls wg-quick up
hoch.
# wg-quick up wg-welt
[#] ip link add wg-welt type wireguard
[#] wg setconf wg-welt /dev/fd/63
[#] ip link set mtu 1412 up dev wg-welt
[#] ip -6 route add fe80::27c:16ff:fec0:6c74/128 dev wg-welt
Den Status unseres WireGuard-clients können wir mit Hilfe der Option show beim Aufruf von wg
bzw. nur dur Aufruf von wg
ermitteln
# wg show
oder einfach nur
# wg
zeigen uns den Status des VPN-Tunnels:
interface: wg-welt
public key: HjDRCwE4Q7UPAKXrmM4s6VOgMK+HJZCixWTaVC8KiRU=
private key: (hidden)
listening port: 45032
peer: TszFS3oFRdhsJP3K0VOlklGMGYZy+oFCtlaghXJqW2g=
endpoint: 5.1.66.3:40011
allowed ips: fe80::27c:16ff:fec0:6c74/128
latest handshake: 18 seconds ago
transfer: 55.46 MiB received, 212 MiB sent
persistent keepalive: every 25 seconds
Da sowohl bei transfer
wie auch bei received
die Werte steigen sobald wie den Status erneut abfragen, können wir im ersten Schritt davon ausgehen, dass der WireGuard-Tunnel steht und auch benutzt werden kann.
Wir sollten auch nun den Tunnelenpunkt am Gateway anpingen können. In unserem Konfiguratiosnbeispiel wäre dies demnach die Ziel-IP-Adresse fe80::27c:16ff:fec0:6c74
auf dem Netzwerk-Device wg-welt
.
# ping6 -c4 fe80::27c:16ff:fec0:6c74%wg-welt
PING fe80::27c:16ff:fec0:6c74%wg-welt(fe80::27c:16ff:fec0:6c74%wg-welt) 56 data bytes
64 bytes from fe80::27c:16ff:fec0:6c74%wg-welt: icmp_seq=1 ttl=64 time=29.2 ms
64 bytes from fe80::27c:16ff:fec0:6c74%wg-welt: icmp_seq=2 ttl=64 time=28.9 ms
64 bytes from fe80::27c:16ff:fec0:6c74%wg-welt: icmp_seq=3 ttl=64 time=28.4 ms
64 bytes from fe80::27c:16ff:fec0:6c74%wg-welt: icmp_seq=4 ttl=64 time=28.10 ms
--- fe80::27c:16ff:fec0:6c74%wg-welt ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 7ms
rtt min/avg/max/mdev = 28.426/28.884/29.201/0.308 ms
Möchten wir den Tunnel wieder per Hand stoppen, verwenden wir die Option down beim Aufruf des Befehls wg-quick
.
# wg-quick down wg-welt
[#] ip link delete dev wg-welt
Zum Starten und Stoppen verwenden wir aber besser die Mechanismen von systemd
. Den manuellen Start führen wir mit Hilfe des nachstehenden Befehls aus.
# systemctl start wg-quick@wg-welt
Der Stop des WireGuard-Deamon erfolgt entsprechend mit:
# systemctl stop wg-quick@wg-welt
Den Status des WireGuard-Client-daemon fragen wir mit der Option status ab.
# systemctl status wg-quick@wg-welt
● wg-quick@wg-welt.service - WireGuard via wg-quick(8) for wg/welt
Loaded: loaded (/lib/systemd/system/wg-quick@.service; disabled; vendor preset: enabled)
Active: active (running) since Wed 2020-12-16 18:20:05 GMT; 10s ago
Docs: man:wg-quick(8)
man:wg(8)
https://www.wireguard.com/
https://www.wireguard.com/quickstart/
https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
Process: 6664 ExecStart=/usr/bin/wg-quick up wg-welt (code=exited, status=0/SUCCESS)
Main PID: 6664 (code=exited, status=0/SUCCESS)
Dec 16 18:20:05 rpb4-wg-ol systemd[1]: Starting WireGuard via wg-quick(8) for wg/welt...
Dec 16 18:20:05 rpb4-wg-ol wg-quick[6664]: [#] ip link add wg-welt type wireguard
Dec 16 18:20:05 rpb4-wg-ol wg-quick[6664]: [#] wg setconf wg-welt /dev/fd/63
Dec 16 18:20:05 rpb4-wg-ol wg-quick[6664]: [#] ip link set mtu 1412 up dev wg-welt
Dec 16 18:20:05 rpb4-wg-ol wg-quick[6664]: [#] ip -6 route add fe80::27c:16ff:fec0:6c74/128 dev wg-welt
Dec 16 18:20:05 rpb4-wg-ol systemd[1]: Started WireGuard via wg-quick(8) for wg/welt.
Damit der Daemon beim Neustart entsprechend automatisch gestartet wird, setzen wir den Dienst auf enabled
# systemctl enable wg-quick@wg-welt
Created symlink /etc/systemd/system/multi-user.target.wants/wg-quick@wg-welt.service → /lib/systemd/system/wg-quick@.service.
Im Betrieb kann es ab und an passieren, dass der WireGuard-Tunnel zusammenbricht, weil z.B. die Netzwerkverbindung abgerissen sit, oder ein Rebot der Gateways notwendig war. Damit in einem solchen Fall unser Offloader nicht offload geht, müssen wir die Verfügbar- und Nutzzbarkeit deer Tunnelverbindung in regelmäßigen Abständen prüfen und ggf. einschreiten und die Verbindung neu aufbauen.
Da wir das ntürlich nict manuell erledigen wollen und können, legen wir uns ein kleines bash-Script hierzu an.
# vim /usr/local/bin/checkup
- /usr/local/bin/checkup
#!/bin/bash
# Django : 2020-12-15
# Check connectivity to supernode
HTTP_STATUS_CODE=(`curl --silent --interface wg-welt --get --ipv6 --connect-timeout 5 --write-out '%{http_code}' --output /dev/null 'http://[fe80::27c:16ff:fec0:6c74]:80'`)
if [ ${HTTP_STATUS_CODE} != "200" ]; then
logger -t checkuplink "curl --silent --interface wg-welt --get --ipv6 --connect-timeout 5 --write-out '%{http_code}' --output /dev/null 'http://[fe80::27c:16ff:fec0:6c74]:80' faild with HTTP-errorcode: ${HTTP_STATUS_CODE}"
logger -t checkuplink "... better we restart the wireguard-tunnel!"
ip link set nomaster bat-welt dev vxlan-mesh &> /dev/null
ip link del dev mesh-vpn &> /dev/null
ip link del wg-welt &> /dev/null
systemctl stop wg-quick@wg-welt
systemctl restart networking
logger -t checkuplink "Sending public-key to the broker."
/usr/bin/wget -q -O- --post-data='{"domain":"ffmuc_welt","public_key":"HjDRCwE4Q7UPAKXrmM4s6VOgMK+HJZCixWTaVC8KiRU="}' http://broker.ffmuc.net/api/v1/wg/key/exchange
logger -t checkuplink "Starting wireguard-daemon."
systemctl start wg-quick@wg-welt
logger -t checkuplink "Starting vxlan-meshing."
vxlan
else
#logger -t checkuplink "wiregurad-tunnel is up an running : HTTP-statuscode: ${HTTP_STATUS_CODE}"
fi
Zum Ausführen statten wir das Script mit den x
-Rechten aus.
# chmod +x /usr/local/bin/checkup
Damit das Script nun münütlich ausgeführt wird, legen wir noch einen hierzu benötigten Eintrag in der /etc/crontab
an.
# vim /etc/crontab
- /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
# Django : 2020-12-15
# check wireguard-connection
* * * * * root /usr/local/bin/checkup 2>&1 /dev/null
Sollte der WireGuard-Tunnel nun zusammenbrechen, aus welchen Gründen das auch immer passieren möge, wird die Verbindung automatisch wieder aufgebaut und im syslog des Raspberry entsprechend dokumentiert.
Dec 16 19:40:09 rpb4-wg-ol checkuplink curl --silent --interface wg-welt --get --ipv6 --connect-timeout 5 --write-out '%{http_code}' --output /dev/null 'http://[fe80::27c:16ff:fec0:6c74]:80' faild with HTTP-errorcode: 500
Dec 16 19:40:10 rpb4-wg-ol checkuplink "... better we restart the wireguard-tunnel!"
Dec 16 19:40:12 rpb4-wg-ol checkuplink "Sending public-key to the broker."
Dec 16 19:40:16 rpb4-wg-ol checkuplink "Starting wireguard-daemon."
Dec 16 19:40:18 rpb4-wg-ol checkuplink "Starting vxlan-meshing."
WireGuard selbst transportiert lediglich Layer-3-Verbindungen und keine Layer-2-Verbindungen, welches wir aber für das von uns eingesetzte Meshprotokoll, B.A.T.M.A.N.-Advanced batman-adv, benötigen. Hierzu transportieren wir nun durch den WireGuard-Tunnel ein Virtual eXtensible LAN (VXLAN, siehe RFC 7348) und in diesem VXLAN läuft dann batman-adv.
WICHTIG:
Die hierzu nötige vxlan id darf nicht mit der VX-LAN-ID verwechselt werden, die wir ggf. später zum Meshen hinter unserem Offloader anbieten möchten.
Die mesh vpn vxlan id berechnet sich aus dem domain_seed
(siehe obige Tabelle).
Um die VXLAN ID aus einem domain_seed zu berechnen haben wir ein kleines Python Skript
geschrieben.
- get_mesh_vpn_vxlan_id_from_domain_seed.py
import sys
domain_seed = sys.argv[1]
def domain_seed_bytes(key, length):
import hashlib
ret = ''
v = ''
i = 0
while len(ret) < 2 * length:
i = i + 1
hash_this = v + key + domain_seed + str(i)
v = hashlib.md5(hash_this.encode('utf-8')).hexdigest()
ret = ret + v
return ret[: 2 * length]
stuff = int(domain_seed_bytes('gluon-mesh-vpn-vxlan', 3), 16)
print(stuff)
Im Beispiel Vom Segment ffmuc_welt ergibt bei einem domain-seed von 1f0b31cecdf980317f453b162ac476ee09cf9997b03e684d4f2f484e75d9cd26
, die vxlan id von 4831583
:
$ python3 get_vxlan_id_from_domain_seed.py 1f0b31cecdf980317f453b162ac476ee09cf9997b03e684d4f2f484e75d9cd26
4831583
Zum Aktivieren der Mesh-Verbindung per vxlan legen wir uns nun ein kleines Bash-Script an.
# vim /usr/local/bin/vxlan
- /usr/local/bin/vxlan
#!/bin/bash
# Django : 2020-12-15
# Bring up VXLAN
ip link add mesh-vpn type vxlan id 4831583 local fe80::02c5:ddff:fee7:823b remote fe80::27c:16ff:fec0:6c74 dstport 8472 dev wg-welt
ip link set up dev mesh-vpn
# Bind mesh-vpn to BATMAN-Device
/usr/sbin/batctl meshif bat-welt if add mesh-vpn
# If we have a BATMAN_V env we need to correct the throughput value now
/usr/sbin/batctl hardif mesh-vpn throughput_override 10000
Damit das Script später direkt ausgeführt werden kann statten wir es noch mit den x
-Rechten aus.
# chmod +x /usr/local/bin/vxlan
Damit das vxlan-Meshing automatisch beim Starten unseres Offloaders gestartet wird, legen wir uns auch hier ein entsprechendes systemd-Startscript an.
# vim /etc/systemd/system/vxlan.service
- /etc/systemd/system/vxlan.service
# Django : 2020-12-15
[Unit]
# see man systemd.unit
Description=Bringing up VXLAN Interface
Documentation=https://wiki.mailserver.guru/doku.php/centos:ansible:ffmuc-rpb4-ol
After=wg-quick@wg-welt.service
[Service]
# see man systemd.service, systemd.exec
Type=oneshot
ExecStart=/usr/local/bin/vxlan
StandardOutput=syslog
StandardError=syslog
[Install]
WantedBy=multi-user.target
Wie schon zuvor bei unserem Broker-Informations-systemd-Startscript informieren wir hier nun systemd über unsere neue systemd-Startupdatei.
# systemctl daemon-reload
Nun können wir das vxlan-Meshing via systemd starten.
# systemctl start vxlan.service
Für den automatischen Start beim Hochfahren unseres Offloaders aktivieren wir nun noch das entsprechende Script.
# systemctl enable vxlan.service
Created symlink /etc/systemd/system/multi-user.target.wants/vxlan.service → /etc/systemd/system/vxlan.service.
Dieser Teil ist wichtig, da es sein kann dass man gegen die Nutzungsbedingungen seiner Community verstößt, wenn man sich nicht als Knoten im Netz meldet. Außerdem trägt es generell zur Netzhygiene bei, wenn alle Knoten in den Statistiken auftauchen.
Wir ermitteln also am einfachsten die Geo-Koordinaten aus der Freifunk München Karte: https://map.ffmuc.net
Qualifier |
Value |
Breitengrad: |
48.198104112 |
Längenggrad: |
11.798404455 |
Kontaktadresse: |
hier entlang => https://bit.ly/3ajjQC0 |
hostname: |
🧠 wiki-demo 🧠 |
model: |
Raspberry Pi 4B |
Nachdem wir auch auf der Knotenkarte auftauchen wollen, installieren wir auch noch ext-respondd.
# apt install git python3-netifaces -y
# git clone https://github.com/freifunkMUC/ext-respondd /opt/ext-respondd/
# cp /opt/ext-respondd/ext-respondd.service.example /etc/systemd/system/ext-respondd.service
# systemctl daemon-reload
# systemctl enable ext-respondd
Bevor wir den Daemon starten, müssen wir diesen noch die Konfigurationsdateien von ext-respondd entsprechend anpassen.
WICHTIG:
Darauf achten, dass die Daten inklusive dem Segmentnamen korrekt eingetragen werden. Eine Übersicht der Segmentnamen gibt es hier.
Wir tragen demnach folgende Daten ein:
Qualifier |
Value |
Breitengrad: |
48.198104112 |
Längenggrad: |
11.798404455 |
Kontaktadresse: |
hier entlang => https://bit.ly/3ajjQC0 |
hostname: |
🧠 wiki-demo 🧠 |
model: |
Raspberry Pi 4B |
# vim /opt/ext-respondd/alias.json
- /opt/ext-respondd/alias.json
{
"nodeinfo": {
"hostname": "🧠 wiki-demo 🧠",
"hardware": {
"model": "Raspberry Pi 4B"
},
"owner": {
"contact": "hier entlang => https://bit.ly/3ajjQC0"
},
"system": {
"site_code": "ffmuc_welt",
"role": "client"
},
"location": {
"latitude": 48.198104112,
"longitude": 11.798404455
}
},
"firstseen": "2020-12-15T12:15:18"
}
# vim /opt/ext-respondd/config.json
- opt/ext-respondd/config.json
{
"batman": "bat-welt",
"bridge": "br-welt",
"mesh-vpn": [ "fastd-welt" ],
"wan": "eth0",
"rate_limit": 30,
"rate_limit_burst": 10
}
Nun starten wir unseren Daemon ext-respondd.
# systemctl start ext-respondd.service
Den Status des Daemon fragen wir wie folgt ab.
# systemctl status ext-respondd.service
● ext-respondd.service - ext-respondd (respondd status for servers)
Loaded: loaded (/etc/systemd/system/ext-respondd.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-12-16 20:40:11 GMT; 59s ago
Main PID: 2184 (python3)
Tasks: 1 (limit: 4915)
CGroup: /system.slice/ext-respondd.service
└─2184 python3 /opt/ext-respondd/ext-respondd.py
Dec 16 20:40:11 rpb4-wg-ol systemd[1]: Started ext-respondd (respondd status for servers).
Dec 16 20:40:11 rpb4-wg-ol ext-respondd.py[2184]: Warning - option -m was deprecated and will be removed in the future
Dec 16 20:40:31 rpb4-wg-ol ext-respondd.py[2184]: Warning - option -m was deprecated and will be removed in the future
Dec 16 20:40:31 rpb4-wg-ol ext-respondd.py[2184]: Warning - option -m was deprecated and will be removed in the future
Dec 16 20:40:31 rpb4-wg-ol ext-respondd.py[2184]: Warning - option -m was deprecated and will be removed in the future
Dec 16 20:40:31 rpb4-wg-ol ext-respondd.py[2184]: Warning - option -m was deprecated and will be removed in the future
Dec 16 20:40:31 rpb4-wg-ol ext-respondd.py[2184]: Warning - option -m was deprecated and will be removed in the future
Dec 16 20:40:31 rpb4-wg-ol ext-respondd.py[2184]: Warning - option -m was deprecated and will be removed in the future
Nach kurzer Zeit taucht unser Node dann auch auf der Karte auf.
Nun wollen wir auch prüfen welche Verbindungen unser Offloader hält.
# ip addr show dev br-welt
6: br-welt: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1280 qdisc noqueue state UP group default qlen 1000
link/ether dc:a6:32:5c:46:07 brd ff:ff:ff:ff:ff:ff
inet 10.80.204.2/21 brd 10.80.207.255 scope global dynamic br-welt
valid_lft 409sec preferred_lft 409sec
inet6 2001:678:e68:109:dea6:32ff:fe5c:4607/64 scope global dynamic mngtmpaddr
valid_lft 7118sec preferred_lft 3518sec
inet6 fe80::dea6:32ff:fe5c:4607/64 scope link
valid_lft forever preferred_lft forever
Wie sehen also, dass unser Node die Adressen 10.80.204.2
sowie 2001:678:e68:109:dea6:32ff:fe5c:4607
hält.
Das Gleiche erreichen wir mit Hilfe dieses Befehls:
# ip -br a | grep br-welt
br-welt UP 10.80.204.2/21 2001:678:e68:109:dea6:32ff:fe5c:4607/64 fe80::dea6:32ff:fe5c:4607/64
Wir sehen somit die Adressen auf unseren Interfaces aus dem gewählten Segment.
Als nächstes prüfen wir, ob die beiden Interfaces dummy-welt
und mesh-vpn
aktiv sind.
# batctl meshif bat-welt if
dummy-welt: active
mesh-vpn: active
Den Neighbor unseres Nodes finden wir wie folgt heraus:
# batctl meshif bat-welt n
[B.A.T.M.A.N. adv 2020.4, MainIF/MAC: dummy-welt/dc:a6:32:5c:46:07 (bat-welt/dc:a6:32:5c:46:07 BATMAN_V)]
IF Neighbor last-seen
8a:5d:44:50:c3:f8 0.220s ( 10.0) [ mesh-vpn]
Zu guter Letzt sehen wir uns noch die Gateway-Liste an über bzw. mit denen unser Offloader verbunden ist.
# batctl meshif bat-welt gwl
[B.A.T.M.A.N. adv 2020.4, MainIF/MAC: dummy-welt/dc:a6:32:5c:46:07 (bat-welt/dc:a6:32:5c:46:07 BATMAN_V)]
Router ( throughput) Next Hop [outgoingIf] Bandwidth
* f2:00:25:10:00:00 ( 10.0) 8a:5d:44:50:c3:f8 [ mesh-vpn]: 1000.0/200.0 MBit
f2:00:26:10:00:00 ( 10.0) 8a:5d:44:50:c3:f8 [ mesh-vpn]: 1000.0/200.0 MBit
Möchte man per Kabel meshen, so ist dies auf Grund dessen, dass unser Raspberry nur eine Netzwerkschnittstelle hat, im Grunde nur per VLAN realisierbar.
Dazu ist es erforderlich, dass zuerst ein VLAN Interface in /etc/network/interfaces
angelegt und an das BATMAN Interface anghängt wird.
# vim /etc/network/interfaces
- /etc/network/interfaces
auto eth0.666
iface eth0.666 inet manual
post-up /usr/sbin/batctl ra BATMAN_V
post-up /usr/sbin/batctl meshif bat-welt if add eth0.666
Bitte beachten:
Das Setup funktioniert nur in Umgebungen ohne VXLAN Meshing. Mit VXLAN Meshing braucht es auch noch ein VXLAN Interface. Details hierzu finden sich im Nachgang!
Für andere Communities benötigt man die entsprechenden VXLAN IDs zum Meshen - also bei Bedarf bei der lokalen Community nachhaken!
Um meshing per Kabel nutzen zu können, muss bei manchen Communities (wie zum Beispiel bei FFMUC) VXLAN benutzt werden.
Bei uns gibt es momentan folgende VXLAN IDs, diese werden von GLUON dynamisch aus dem domain_seed erzeugt.
Domain | vxlan id |
ffmuc_muc_cty | 10758607 |
ffmuc_muc_nord | 15521492 |
ffmuc_muc_ost | 2948862 |
ffmuc_muc_sued | 8599288 |
ffmuc_muc_west | 7318933 |
ffmuc_uml_nord | 5705961 |
ffmuc_uml_ost | 4892713 |
ffmuc_uml_sued | 16544703 |
ffmuc_uml_west | 16677749 |
ffmuc_gauting | 16175732 |
ffmuc_freising | 12937858 |
ffmuc_welt | 16306234 |
ffmuc_augsburg | 10700201 |
Um die VXLAN ID aus einem domain_seed zu berechnen haben wir ein kleines Python Skript geschrieben.
python3 get_vxlan_id_from_domain_seed.py domain_seed
Die Konfiguration in /etc/network/interfaces sieht so aus, um per VLAN666 VXLAN Meshing für das Segment Welt zu machen. Wie ihr seht, wird dafür die ID aus der obigen Tabelle benötigt.
- /etc/network/interfaces
auto eth0.666
iface eth0.666 inet manual
pre-up /sbin/ip link add vxlan-mesh type vxlan id 16306234 group ff02::15c dstport 4789 port 32768 61000 no udpcsum udp6zerocsumtx udp6zerocsumrx dev eth0.666 || true
up /sbin/ip link set vxlan-mesh up
post-up /usr/sbin/batctl ra BATMAN_V
post-up /usr/sbin/batctl -m bat-welt if add vxlan-mesh
down ip link set vxlan-mesh down
post-down ip link del vxlan-mesh || true
Damit das vxlan-mesh Interface auch der bevorzugte Meshingpoint in BATMAN_V wird noch folgendes in die /etc/rc.local
hinzufügen.
# vim /etc/rc.local
- /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
# Django : 2020-12-15
/usr/sbin/batctl hardif vxlan-mesh throughput_override 1000000
exit 0
Zum Aktivieren unserer Konfigurationsänderung fahren wir entweder das Netzwerkiinterface hoch oder starten unseren Offloader einfach einmal neu:
# systemctl reboot
Wenn alles geklappt hat und ihr bereits einen Router zum Meshen in diesem VLAN habt, sollte danach folgendes in batctl zu sehen sein.
batctl meshif bat-welt n
[B.A.T.M.A.N. adv 2020.4, MainIF/MAC: dummy-welt/dc:a6:32:5c:46:07 (bat-welt/dc:a6:32:5c:46:07 BATMAN_V)]
IF Neighbor last-seen
8e:89:98:45:6c:70 0.380s ( 1.0) [vxlan-mesh]
a2:ca:66:65:30:40 0.050s ( 1.0) [vxlan-mesh]
9a:9b:66:30:d9:38 0.110s ( 1.0) [vxlan-mesh]
6a:b4:d0:73:15:47 0.100s ( 10.0) [ mesh-vpn]
Sollte sich kein Client am Mesh VLAN befinden, wird die vxlan-mesh Zeile nicht angezeigt.
Außerdem sollten die Interfaces wie folgt aussehen:
# batctl -m bat-welt if
dummy-welt: active
vxlan-mesh: active
fastd-welt: active
Leider ist der Link zum Gateway auf der Map nicht zu sehen.
Soll der Offloader auch ein WiFI-Clientnetz ausstrahlen, müssen wir hostapd
installieren und konfigurieren. Bei der Vergabe der SSID ist zu beachten:
WICHTIG:
Das Abändern der zum Segment passenden SSID ist gemäß der Nutzungsbedingungen nicht gestattet!
Die Liste der SSIDs findet ihr hier:
Aktuell2) gibt es folgende Segmente:
SSID | Segment-Name | IPv4-Prefix | IPv6-Prefix Wien | IPv6-Prefix München |
muenchen.freifunk.net/muc_cty | ffmuc_muc_cty | 10.80.128.0/21 | 2001:678:e68:100::/64 | 2001:678:ed0:100::/64 |
muenchen.freifunk.net/muc_nord | ffmuc_muc_nord | 10.80.136.0/21 | 2001:678:e68:101::/64 | 2001:678:ed0:101::/64 |
muenchen.freifunk.net/muc_ost | ffmuc_muc_ost | 10.80.144.0/21 | 2001:678:e68:102::/64 | 2001:678:ed0:102::/64 |
muenchen.freifunk.net/muc_sued | ffmuc_muc_sued | 10.80.152.0/21 | 2001:678:e68:103::/64 | 2001:678:ed0:103::/64 |
muenchen.freifunk.net/muc_west | ffmuc_muc_west | 10.80.160.0/21 | 2001:678:e68:104::/64 | 2001:678:ed0:104::/64 |
muenchen.freifunk.net/uml_nord | ffmuc_uml_nord | 10.80.168.0/21 | 2001:678:e68:105::/64 | 2001:678:ed0:105::/64 |
muenchen.freifunk.net/uml_ost | ffmuc_uml_ost | 10.80.176.0/21 | 2001:678:e68:106::/64 | 2001:678:ed0:106::/64 |
muenchen.freifunk.net/uml_sued | ffmuc_uml_sued | 10.80.184.0/21 | 2001:678:e68:107::/64 | 2001:678:ed0:107::/64 |
muenchen.freifunk.net/uml_west | ffmuc_uml_west | 10.80.192.0/21 | 2001:678:e68:108::/64 | 2001:678:ed0:108::/64 |
muenchen.freifunk.net/welt | ffmuc_welt | 10.80.200.0/21 | 2001:678:e68:109::/64 | 2001:678:ed0:109::/64 |
muenchen.freifunk.net/gauting | ffmuc_gauting | 10.80.208.0/21 | 2001:678:e68:10a::/64 | 2001:678:ed0:10a::/64 |
muenchen.freifunk.net/freising | ffmuc_freising | 10.80.216.0/21 | 2001:678:e68:10b::/64 | 2001:678:ed0:10b::/64 |
muenchen.freifunk.net/augsburg | ffmuc_augsburg | 10.80.224.0/21 | 2001:678:e68:10c::/64 | 2001:678:ed0:10c::/64 |
muenchen.freifunk.net/ulm | ffmuc_ulm | 10.86.16.0/21 | 2001:678:e68:182::/64 | 2001:678:ed0:182::/64 |
Freifunk-Donau-Ries | ffdon_mitte | 10.86.128.0/21 | 2001:678:e68:190::/64 | 2001:678:ed0:190::/64 |
Freifunk-Donau-Ries | ffdon_nordwest | 10.86.136.0/21 | 2001:678:e68:191::/64 | 2001:678:ed0:191::/64 |
Freifunk-Donau-Ries | ffdon_sued | 10.86.144.0/21 | 2001:678:e68:192::/64 | 2001:678:ed0:192::/64 |
wertingen.freifunk.net | ffwert_city | 10.86.0.0/21 | 2001:678:e68:180::/64 | 2001:678:ed0:180::/64 |
wertingen.freifunk.net | ffwert_events | 10.86.8.0/21 | 2001:678:e68:181::/64 | 2001:678:ed0:181::/64 |
# apt install hostapd -y
# echo 'DAEMON_OPTS="-d"' >> /etc/default/hostapd
Nun legen wir uns eine entsprechende Konfigurationsdatei an.
# vim /etc/hostapd/hostapd.conf
- /etc/hostapd/hostapd.conf
# Django : 2020-12-15
ssid=muenchen.freifunk.net/welt
country_code=DE
interface=wlan0
driver=nl80211
macaddr_acl=0
logger_syslog=0
logger_syslog_level=4
logger_stdout=-1
logger_stdout_level=0
hw_mode=a
wmm_enabled=1
# N
ieee80211n=1
require_ht=1
ht_capab=[MAX-AMSDU-3839][HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]
# AC
ieee80211ac=1
require_vht=1
ieee80211d=0
ieee80211h=0
vht_capab=[MAX-AMSDU-3839][SHORT-GI-80]
vht_oper_chwidth=1
channel=36
vht_oper_centr_freq_seg0_idx=42
Anschließend aktivieren und starten wir den hostapd
-Daemon.
# systemctl unmask hostapd
# systemctl enable hostapd
# systemctl start hostapd
Das Netzwerkinterface wlan0
müssen wir nun noch in die Bridge packen. Dazu passen wir die /etc/rc.local
an.
# vim /etc/rc.local
- /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
# Django : 2020-12-15
sleep 10; /sbin/brctl addif br-welt wlan0
exit 0
Am Besten nochmal rebooten um sicher zugehen, dass alles passt, danach einfach mit dem ClientWifi verbinden.
# systemctl reboot
Will man LAN Clients versorgen, so erstellt man am einfachsten ein VLAN getaggtes Clientnetz. Dazu erstellt man in der Konfigurationsdatei /etc/network/interfaces
die zugehörige Konfiguration. Im folgenden Beispiel nutzen wir die VLAN-ID 333
und definieren zunächst einmal das VLAn-Interface und fügen es anschließend in der vorhandenen Bridge hinzu.
# vim /etc/network/interfaces
- /etc/network/interfaces
auto eth0.333
iface eth0.333 inet manual
auto br-welt
iface br-welt inet dhcp
bridge-ports bat-welt eth0.333
Nun zur wichtigsten Frage, welche Performance kann man erwarten.
Hier ein paar Speedtest Ergebnisse:
WiFi Client an VDSL 100:
Kabel Client an VDSL 100:
Kabel Client an 1Gbit/s Glas:
$ wget -O /dev/null https://speed.hetzner.de/10GB.bin --report-speed=bits
--2019-07-01 09:12:45-- https://speed.hetzner.de/10GB.bin
Resolving speed.hetzner.de (speed.hetzner.de)... 88.198.248.254
Connecting to speed.hetzner.de (speed.hetzner.de)|88.198.248.254|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10485760000 (9.8G) [application/octet-stream]
Saving to: ‘/dev/null’
/dev/null 2%[===> ] 288.96M 115Mb/s eta 14m 34s
Nebenbei gibt es noch die Möglichkeit, Tethering z.B. mit iOS Geräten zu machen. Dazu muss usbmuxd installiert werden. Und in der /etc/network/interfaces
ein Interface angelegt werden.
# apt install usbmuxd libimobiledevice6 -y
# vim /etc/network/interfaces
- /etc/network/interfaces
...
allow-hotplug eth1
iface eth1 inet dhcp
...
Am Besten rebootet man den Raspberry Offloader einmal. Danach steckt ihr euer iOS Gerät per USB an während ihr im Hotspot Menü seid und werdet gefragt, ob das PI Zugriff bekommen kann. Das beantwortet ihr mit „Ja“.
Euer PI bezieht sich nun eine IP per DHCP vom iOS Gerät und kann darüber Verbindungen zu den Freifunk Gateways aufbauen.
Und so sieht ein Mobile PI mit iPad als Uplink aus:
Im nachfolgenden Beispiel verwenden wir ein OLED Display von AZDelivery mit 128×64 Pixeln. Das schöne an dem Display ist, es funktioniert auch mit 5V und ist damit noch einfacher anzuschließen.
Angeschlossen wird das Ganze wie folgt:
OLED Pin | GPIO Pin | Notes |
---|
Vcc | 4 | 5V |
Gnd | 6 | Ground |
SCL | 5 | I2C SCL |
SDA | 3 | I2C SCA |
Als nächstes aktivieren wir die I2C Schnittstelle und installieren die notwendige Software.
# echo i2c-bcm2708 >> /etc/modules
# echo i2c-dev >> /etc/modules
# apt install python3-dev python3-smbus i2c-tools python3-pil python3-pip python3-setuptools python3-rpi.gpio -y
Bevor wir nun einen Reboot durchführen kontrollieren wir noch, ob in der /boot/config.txt das I2C-Interface auch gestartet wird.
root@raspberrypi:~# vim /boot/config.txt
...
# Uncomment some or all of these to enable the optional hardware interfaces
# Django : 2020-12-15 - für OLED Display Support aktiviert
# default: # dtparam=i2c_arm=on
dtparam=i2c_arm=on
...
Nun am Besten einmal rebooten.
# systemctl reboot
Danach überprüfen wir ob das Display erkannt wird.
# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Wie man sieht meldet sich das Display unter der Adresse 3c.
Jetzt installieren wir die notwendige Python Bibliotheken um das Display ansteuern zu können.
# apt install git fonts-freefont-ttf -y
# cd /usr/local/src/
# git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
# cd Adafruit_Python_SSD1306
# python3 setup.py install
Anschließend können wir mit ein paar Beispielen probieren ob das Display korrekt funktioniert.
# cd examples
# python3 /usr/local/src/Adafruit_Python_SSD1306/examples/stats.py
Auf dem Display werden ein paar Systemdaten angezeigt:
Nachdem alles alles soweit funktioniert, können wir als nächstes das Bandbreiten Skript installieren, welches auch gleichzeitig die verbundenen BATMAN Clients anzeigt.
Anschließend das Python Skript, welches das Display steuert installieren und anpassen.
# cd /usr/local/src
# git clone https://github.com/awlx/raspberry-oled-bandwidth
# cd raspberry-oled-bandwidth
Nun passen wir in dem Script folgende Variabelen unseren Gegebenheiten an:
# vim /usr/local/src/raspberry-oled-bandwidth/bandwidth.py
- /usr/local/src/raspberry-oled-bandwidth/bandwidth.py
#
# Inspired by https://github.com/DarrenBeck/rpi-oled-bandwidth and https://photochirp.com/r-pi/use-raspberry-pi-oled-bandwidth-monitor/
#
# Maintained by awlnx - aw@awlnx.space
#
import subprocess
import time
import re
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import math
# Adjust to your needs
wifi = 'wlan0'
vpn = 'fastd-welt'
batman = 'bat-welt'
# Django : 2020-12-15
# default: primary_mac = 'dc:a6:32:00:6b:59'
primary_mac = 'dc:a6:32:01:7f:f0'
# We assume 100mbit/s max bandwidth
maxRateIn = 10000000
maxRateOut = 10000000
PImaxRateIn = 10000000
PImaxRateOut = 10000000
### DO NOT EDIT BELOW THIS POINT ###
# Raspberry Pi pin configuration:
# Django : 2020-15-12
# default: RST = 24
RST = 'P9_15'
# 128x64 display with hardware I2C:
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)
# Initialize library.
disp.begin()
# Clear display.
disp.clear()
disp.display()
# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = disp.width
height = disp.height
image = Image.new('1', (width, height))
# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)
font = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSans.ttf', 12)
fontsmall = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSans.ttf', 10)
fontverysmall = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSans.ttf', 8)
fontmedium = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSans.ttf', 12)
#Display Image
disp.image(image)
disp.display()
#Functions
def get_network_bytes(interface):
for line in open('/proc/net/dev', 'r'):
if interface in line:
data = line.split('%s:' % interface)[1].split()
rx_bytes, tx_bytes = (data[0], data[8])
return (int(rx_bytes), int(tx_bytes))
def drawBar (x, barHeight):
# parameters are x, y, end x, end y
# draw.rectangle ((x, height - barHeight, x + 10, height -1), outline=255, fill=255)
draw.rectangle ((x, 32 - barHeight, x + 8, height - 32), outline=255, fill=255)
def drawBarLOW (x, barLOWHeight):
# parameters are x, y, end x, end y
draw.rectangle ((x, 32 + barLOWHeight, x + 8, height - 32), outline=255, fill=255)
def textRate(rate):
# rate -> raw bitrate
# Returns: SI formatted bitrate
if rate == 0:
return "0B"
rate = rate * 8
size_name = (
"b/s", "kb/s", "mb/s", "gb/s", "tb/s", "pb/s", "eb/s")
i = int(math.floor(math.log(rate , 1024)))
p = math.pow(1024, i)
s = round(rate / p, 1)
return "%s %s" % (s, size_name[i])
lastInBytes = get_network_bytes(vpn)[0];
lastOutBytes = get_network_bytes(vpn)[1];
lastPIInBytes = get_network_bytes(wifi)[0];
lastPIOutBytes = get_network_bytes(wifi)[1];
lastTime = time.time()
#timed array vars
timerTime = time.time()
highestSpeedIn = 0
highestSpeedOut = 0
PIhighestSpeedIn = 0
PIhighestSpeedOut = 0
speedArrayIn = []
speedArrayOut = []
PIspeedArrayIn = []
PIspeedArrayOut = []
inMax = 0
outMax = 0
PIinMax = 0
PIoutMax = 0
while (1):
time.sleep(2)
draw.rectangle((0, 0, width, height), outline=0, fill=0)
now = time.time()
elapsed = now - lastTime
lastTime = now
#calculate rates in and out
inBytes = get_network_bytes(vpn)[0]
currInBytes = (inBytes - lastInBytes) / elapsed
lastInBytes = inBytes
outBytes = get_network_bytes(vpn)[1]
currOutBytes = (outBytes - lastOutBytes) / elapsed
lastOutBytes = outBytes
PIinBytes = get_network_bytes(wifi)[0]
currPIInBytes = (PIinBytes - lastPIInBytes) / elapsed
lastPIInBytes = PIinBytes
PIoutBytes = get_network_bytes(wifi)[1]
currPIOutBytes = (PIoutBytes - lastPIOutBytes) / elapsed
lastPIOutBytes = PIoutBytes
#max rate last 24 hours calculations
if currInBytes > highestSpeedIn:
highestSpeedIn = currInBytes
if currOutBytes > highestSpeedOut:
highestSpeedOut = currOutBytes
if currPIInBytes > PIhighestSpeedIn:
PIhighestSpeedIn = currPIInBytes
if currPIOutBytes > PIhighestSpeedOut:
PIhighestSpeedOut = currPIOutBytes
if now > timerTime + 3600:
print('----------------------------------------------------------------- time expired')
timerTime = now
speedArrayIn.append (highestSpeedIn)
if len (speedArrayIn) > 23:
del speedArrayIn[0]
inMax = max(speedArrayIn)
speedArrayOut.append (highestSpeedOut)
if len (speedArrayOut) > 23:
del speedArrayOut[0]
outMax = max(speedArrayOut)
highestSpeedIn = 0
highestSpeedOut = 0
PIspeedArrayIn.append (PIhighestSpeedIn)
if len (PIspeedArrayIn) > 23:
del PIspeedArrayIn[0]
PIinMax = max(PIspeedArrayIn)
PIspeedArrayOut.append (PIhighestSpeedOut)
if len (PIspeedArrayOut) > 23:
del PIspeedArrayOut[0]
PIoutMax = max(PIspeedArrayOut)
PIhighestSpeedIn = 0
PIhighestSpeedOut = 0
#adjust these in each loop in case we find a faster speed
inMax = max(inMax, highestSpeedIn)
outMax = max(outMax, highestSpeedOut)
PIinMax = max(PIinMax, PIhighestSpeedIn)
PIoutMax = max(PIoutMax, PIhighestSpeedOut)
#draw graph
inHeight = 0.0
outHeight = 0.0
PIinHeight = 0.0
PIoutHeight = 0.0
if currInBytes > 0:
inHeight = float(currInBytes / maxRateIn) * 32
if currOutBytes > 0:
outHeight = float(currOutBytes / maxRateOut) * 32
if currPIInBytes > 0:
PIinHeight = float(currPIInBytes / PImaxRateIn) * 32
if currPIOutBytes > 0:
PIoutHeight = float(currPIOutBytes / PImaxRateOut) * 32
drawBar (0, inHeight)
drawBar (10, PIinHeight)
drawBarLOW (0, outHeight)
drawBarLOW (10, PIoutHeight)
#write rates
draw.text((26,38), textRate(currInBytes), font=font, fill=255)
draw.text((26,50), textRate(currOutBytes), font=font, fill=255)
draw.text((81,38), textRate(currPIInBytes), font=font, fill=255)
draw.text((81,50), textRate(currPIOutBytes), font=font, fill=255)
# Batman Clients
clients = subprocess.check_output("batctl -m " + batman + " tl | egrep -v '(MainIF|" + primary_mac + ")' | egrep -o '([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})' | wc -l", shell=True).split().pop()
draw.text((0,48), "Clients", font=fontverysmall, fill=255)
draw.text((10,55), clients.decode("utf-8"), font=fontverysmall, fill=255)
#max rates
draw.text((36,0), "VPN", font=fontsmall, fill=255)
draw.text((26,10), textRate(inMax), font=fontsmall, fill=255)
draw.text((26,20), textRate(outMax), font=fontsmall, fill=255)
draw.text((90,0), "Wifi", font=fontsmall, fill=255)
draw.text((81,10), textRate(PIinMax), font=fontsmall, fill=255)
draw.text((81,20), textRate(PIoutMax), font=fontsmall, fill=255)
disp.image(image)
disp.display()
Nun können das Script erst einmal manuell anstarten und prüfen ob die gewünschten Informationen richtig angezeigt werden.
# /usr/bin/python3 /usr/local/src/raspberry-oled-bandwidth/bandwidth.py
Um nun nicht jedes mal beim Starten des Offloaders/Gateways manuell starten müssen, legen wir uns noch ein systemd-Script an.
# vim /etc/systemd/system/oled-bandwidth.service
- /etc/systemd/system/oled-bandwidth.service
# Django : 2020-12-15
[Unit]
After=network.target
[Service]
ExecStart=/usr/bin/python3 /usr/local/src/raspberry-oled-bandwidth/bandwidth.py
[Install]
WantedBy=default.target
Anschließend informieren wir unser System über unser definiertes Daemon-Startscript und aktivieren dies auch gleich noch.
# systemctl daemon-reload
# systemctl enable oled-bandwidth.service
Zu guter Letzt rebooten wir nun unseren Rechner.
# systemctl reboot