Posts mit dem Label OpenWrt werden angezeigt. Alle Posts anzeigen
Posts mit dem Label OpenWrt werden angezeigt. Alle Posts anzeigen

Donnerstag, 29. Dezember 2022

OpenWrt - sysupgrade ohne Bedenken

Es gibt ein (für mich) neues Feature bei OpenWrt: Attended SysUpgrade

Das vereinfacht den Vorgang ein neues Image einzuspielen erheblich, man hat quasi keine Nacharbeit mehr! 

Nachdem ich mich mal wieder mit hotplug und opkg-extras beschäftigt habe, entdeckte ich in dem Wiki Artikel ganz zum Schluss den entsprechenden Hinweis. 

Damit braucht man jetzt nur noch zwei Dinge beim sysupgrade: 

  1. eine angepasstes Backup Archiv Configuration
    • Pfade bzw. Dateien eintragen und mit "Open list" prüfen ob alle wichtigen Dateien im Archiv enthalten sind.
    • Obwohl das sysUpgrade genau diese Dateien von sich aus behält (Keep Settings...), sollte man immer ein Archiv separat erzeugen und herunterladen!
  2. Das installierte luci-app-attendedsysupgrade Package.

Im Menü System einfach Attended Sysupgrade auswählen, der Rest ist selbsterklärend. Im Reiter Configuration kann man den Advanced Mode einschalten. Damit kann man die Pakete verifizieren und eventuell noch etwas ändern. Man kann auch ein angepasstes Image der bereits installierten Version herunterladen. 

Hinweis: Am Ende bleibt irgendwie die UI hängen, man kann diese schließen und sich nach dem Neustart neu verbinden.

Ich habe z.B. um folgende Dateien/Pfade ergänzt:

/etc/wireguard/
/etc/adblock/ad*list
/root/speedtest
/root/.config

Hatte man hotplug-extras installiert, kann man die installierten Scripts wieder entfernen (auch oben in der Liste):

rm /etc/hotplug.d/iface/90-online
rm /etc/hotplug.d/online/10-sleep
rm /etc/hotplug.d/online/50-opkg-restore

Fehlt noch was?

Mittwoch, 31. August 2022

Wie funktioniert Wireguard im Detail

Ich habe pivpn mit wireguard installiert und das hat einfach funktioniert. Also wirklich einfach! Jetzt bin ich etwas tiefer vorgedrungen, um zu verstehen wie man die Konfiguration lesen muss und um Konfigurationen sichern und übertragen zu können. Für pivpn gibt es eine simple Backup/Restore Beschreibung (mit Stolperstellen siehe auch).

  • Wireguard unterscheidet in der Installation nicht zwischen Server und Client - nur die Konfiguration bestimmt: wer mit wem.
  • Wireguard implementiert im System ein vollwertiges Netzwerkinterface mit Tunnel - quasi eine virtuelle Netzkarte mit virtuellem Kabel. Die Netzwerkadministration erfolgt mit Standard Boardmitteln.
  • Die Endpunkte authentifizieren sich mit einer Public-Key-Authentifizierung.
  • Soll der Endpunkt ein VPN Router sein, muss er entweder schon der Router im Netzwerk sein oder NAT aktiviert haben.

Die Konfigurationsdatei für einen Endpunkt wird normal im INI Format erstellt - bei OpenWrt ist sie in der network config integriert. 

OpenWrt kann sowohl Server als auch Client Funktionalität abbilden, ich habe mich hier zunächst auf OpenWrt Router als VPN Einwahl Server beschränkt.

Nachtrag 7.9.2022: Während ich noch immer am Artikel schreibe bringt die neue Version OpenWrt 22.03 jede Menge Änderungen und meine ganzen Scripts für Wireguard sind hinfällig!?

Sonntag, 3. Oktober 2021

OpenWrt mit Scripts konfigurieren

Das neue Release openwrt-21.02. bringt unter Umständen eine neue Herausforderung: Beim Versuch des Updates kommt die Meldung:

Please wipe config during upgrade (force required) or reinstall. Reason: Config cannot be migrated from swconfig to DSA Image check failed.

Die weitere Recherche ergibt: Es gibt keinen wirklichen Upgrade Pfad: Baue das System einfach neu auf. Oh Mist: was hatte ich nochmal alles wie konfiguriert und installiert?

  1. Switch Konfiguration: VLANs für einen LAN und zwei WAN Anschlüsse
  2. Interface definieren: LAN als DHCP Server, WAN als DHCP Client, mehrere Wireless Netzwerke
  3. DHCP Reservierung für die wichtigen Server/Geräte einrichten.
  4. Software installieren, Loadbalancing, Adblocker, Advanced Reboot
  5. Einiges "fein" konfigurieren

Tja und nun? Immer auf Luci und "Keep Configuration" verlassen. Jetzt oder nie: Konfigurationsscripte sind die beste Dokumentation!

Zum Nachlesen: The UCI systemDistributed Switch Architecture

Achtung: Meine Codebeispiele konfigurieren nicht alles. Der Router ist in einem Grundzustand, der kann von Gerät zu Gerät unterschiedlich sein! Eine mehrfache Ausführung der hier gezeigten Scripte kann zu fehlerhaften Konfigurationen führen.

Dienstag, 25. Mai 2021

Linux Image in Hyper-V starten

Bekommt man ein x86-64 Linux Image direkt in Windows Hyper-V aktiviert?  (OpenWrt gibt es als .img.gz zum Download)

Ja das geht: mit einem Tool, und einem Powershell Script. (Quelle)

  1. openwrt.xx.xx.x-x86-64-combined-ext4.img.gz herunterladen.
  2. gzip auspacken
  3. Mit qemu-img das img nach vhdx konvertieren.
  4. Virtuelle Maschine definieren und die vorhandene vhdx Datei einbinden.

Freitag, 21. Mai 2021

OpenWrt Router - mehr als nur ins Internet

 Ich habe seit Jahren einen WRT 1900 ACS und zwei (langsame) DSL Leitungen. Zwei Themen stehen immer im Hinterkopf und ich will mal dazu wieder ein paar Informationen aufschreiben.

  1. Zwei WAN Anschlüsse bündeln und etwas intelligenter verwenden als nur mit ein paar Routing Einträgen.
  2. Jeweils getrennte WLAN und LAN Zugänge für IoT Geräte und für Gäste.
  3. Werbeblocker zentral mit adblock einrichten
Um sich in die Begriffe der Netzwerkthematik ein bisschen einzulesen, kann man die OpenWrt Wiki Hauptseite Firewall and Network Interfaces als Start nutzen.

Dienstag, 19. März 2019

Precence und OpenWrt - der 3. Versuch

Am Wochenende habe ich meinen OpenWrt Router WRT1900ACS mit neuer Firmware versorgt und dabei fiel dann relativ schnell auf, da war doch noch was...
Die beiden Varianten um festzustellen, ob bestimmte Geräte im Wlan angemeldet sind, die ich im Juni bzw. August 2018 schon mal getestet habe, haben einen ganz entscheidenden Nachteil: Sie überleben das Firmware Update nicht!
Ich hatte die Variante aus August zwar als Provisorium ohne Probleme laufen, aber so richtig zufrieden war ich damit sowieso nicht.
Der ssh Zugang zum OpenWrt Router überlebt das Firmware Update!
Deswegen eine neue Version. Ich beschreibe der Vollständigkeit halber an dieser Stelle auch noch einmal in Kurzfassung die Einrichtung des passwortlosen ssh Zuganges von fhem zum OpenWrt Router. Die Langfassung gab es ja schon in 2017.

Vorbemerkung

Das Tool ssh-copy-id kann nicht mit den speziellen Pfaden von dropbear (ssh OpenWrt) umgehen, deshalb kommt mein "Einzeiler" aus dem Artikel zum Einsatz.
Ich weiß, dass man prinzipiell die ssh Keys auch vom aktiven User auf den User fhem kopieren kann. Bei sicherheitsrelevanten Themen bin ich lieber für "ordentliches" und vielleicht etwas aufwendigeres Vorgehen.

ssh Zugang mit Public Key einrichten

Bitte diesen Artikel zur Einrichtung verwenden und dort in der Codebox den Abschnitt Ziel openwrt verwenden!

FHEM

Die Einrichtung in FHEM besteht aus einem Script und einem Presence Device.

Script

Meine Script liegen jetzt alle auch auf GitHub, wer das aktuelle Script einfach laden will kann das wie hier gezeigt tun, fhem braucht selbst nur Lese Rechte. Im Script muss normal nichts konfiguriert werden.
Dieser Befehl in der FHEM Kommandozeile lädt das Script ohne Umwege ins FHEM Verzeichnis:
"wget -O GetMacPresence.sh https://raw.githubusercontent.com/heinz-otto/scripts/master/Bash/GetMacPresence.sh"
Ich habe keinen anderen Benutzer in OpenWrt angelegt, sollte man aber vielleicht tun.
Das Script liefert lediglich, wie vom Modul gefordert, 0 oder 1 zurück, MAC Adresse und Routername werden als Parameter übergeben.
MAC=$1
host=$2
user="root"
ssh $user@$host '
    if (
      for m in $(
                 for w in $(iwinfo |grep -oE "wlan\d-\d|wlan\d")
                 do
                   iwinfo $w assoclist | grep -o -E "([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}"
                 done
                )
      do
        [ "$m" = '"$MAC"' ] && exit 0
      done
      exit 1
    )
  then
    echo 1
  else
    echo 0
  fi
'

Presence Device

Das Beispiel zeigt die einfachste Verwendung, neben der zu suchenden MAC Adresse wird noch der Name des OpenWrt Routers angegeben.
define WL_Dev1 PRESENCE shellscript "bash GetMacPresence.sh 11:22:33:AA:BB:CC wrt1900"

Erfahrung

Ein Problem tritt relativ schnell zu Tage: Man kann offenbar dieses Script nicht mehrfach starten, dann führt irgendeine Komponente zum Abbruch.

Mittwoch, 22. August 2018

QR Code für WiFi Zugang

Ohne viel zu tippen und eventuell falsche Zahlen und Buchstaben kommt man mit modernen Android und IOS Systemen per Scan ins Wlan. WiFi Zugang (WLAN) teilen heisst der Menüpunkt im Smartphone wenn man mit dem Wlan verbunden ist. Und das Smartphone zeigt in dem Moment genau einen QR Code, den man mit dem anderen Smartphone scannen kann und mit einem Klick kann man sich verbinden.

Also einfach einen QR Code fürs Wlan basteln!

Es gibt dazu einen standardisierten String der bereitgestellt werden muss. Die einzelnen Textelemente sind durch ; getrennt. Die "" können normalerweise entfallen.

WIFI:T:WPA;P:"password";S:"SSID Name";;

Unter debian Linux

sudo apt-get install qrencode
Unter OpenWrt gibt es auch das Paket qrencode allerdings mit Einschränkungen.

Diese Befehlszeile erzeugt die PNG Datei:

qrencode -t png -o ~/SSID_wifi_config.png 'WIFI:T:WPA;P:"password";S:"SSID Name";;'


Oder unter OpenWrt erzeugt man eine SVG Datei, da ist kein PNG verfügbar!

qrencode -t svg -o ~/SSID_wifi_config.svg 'WIFI:T:WPA;P:"password";S:"SSID Name";;'

Die fertige Datei drucken, oder anderweitig zur Verfügung stellen.

Mit dem "QR Code Reader - Ohne Werbung" von Sustainable App-Developer hatte ich guten Erfolg unter Android. Er will nur Bilder aufnehmen und braucht keine weiteren Rechte.

Freitag, 17. August 2018

Mit OpenWrt Presence Informationen ermitteln

Der zentrale Router weiß ja eigentlich am Besten was los ist im Netzwerk. Ich habe mal die Idee verfolgt auf dem OpenWrt einen Prozess zu starten, der aktuelle Information von Netzwerkgeräten nach "aussen" übermittelt. Als erstes Beispiel will ich mal einen bestimmten Wlan Client ermitteln.
Da die finale kurze Abfrage Schleife leicht unübersichtlich ist, erkläre ich erstmal die einzelnen Komponenten.

Ein paar Grundlagen

Je nach Wlan Hardware hat man unterschiedliche Tools um das Wlan abzufragen. Bei mir war iw und iwinfo vorhanden. Ich muss noch prüfen ob der Befehl ip auch (und ganz universell) zu gebrauchen wäre.
Die Ausgabe wird dann für die weitere Verarbeitung gefiltert. Diese beiden Befehle liefern das gleiche Ergebnis:
iwinfo |grep -oE "wlan\d-\d|wlan\d"
iw dev | grep Interface | cut -f 2 -s -d" "
Eine Liste der im Router definierten Wlan Netzwerke.
wlan0
wlan1
wlan1-1
wlan1-2
Eine List der angemeldeten Clients bekommt man mit einem dieser beiden Befehle:
iwinfo wlan1-1 assoclist
iw dev wlan1-1 station dump
In einer Schleife über alle Wlan Netzwerke und einem Ausgabe Filter bekommt man eine komplette Liste der MAC Adressen der aktiven Wlan Clients:
for w in $(iwinfo |grep -oE "wlan\d-\d|wlan\d"); do
   iwinfo $w assoclist | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'
done

Abfrage einer bestimmten MAC Adresse

Jetzt alles zusammengefasst mit einer Abfrage eine bestimmten MAC Adresse und als Resultat die Übergabe an einen Dummy in FHEM (API WEB ohne csrf Token!).
Das Script /root/loop.sh
#Die Verzögerungszeit der Abfrageschleife kann auch übergeben werden
WATCHDOG_SLEEP_SEC=${1:-2}
#Url zu FHEM
u=http://192.168.56.80:8088/fhem?cmd=set%20WL_Mi6%20
MAC_ADDRESS_1="80:AD:xx:xx:xx:xx"

while sleep $WATCHDOG_SLEEP_SEC; do
 if (
      for m in $(
                 for w in $(iwinfo |grep -oE "wlan\d-\d|wlan\d")
                 do
                   iwinfo $w assoclist | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'
                 done
                )
      do
        [ "$m" = "$MAC_ADDRESS_1" ] && exit 0
      done
      exit 1
    )
 then
   c=on
 else
   c=off
 fi

 # tue nur etwas wenn sich c geändert hat
 if [ "$c1" != "$c" ] ; then wget -qs $u$c ; c1=$c ; fi

done

Automatischer Start

Jetzt fehlt noch der automatische Start in OpenWrt. Dafür ist procd zuständig. Ich habe dazu ein init Script mit minimaler Funktion erstellt (siehe auch Erklärung unter dem Text):
cat <<EOF > /etc/init.d/loop
#!/bin/sh /etc/rc.common

USE_PROCD=1

START=99
STOP=01

start_service() {
    procd_open_instance
    procd_set_param command /bin/sh "/root/loop.sh"
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}
EOF 
Achtung! ich lerne ja selbst immer wieder dazu und habe diesen Code mal bewusst als Here Doc  dargestellt. Wenn man den Text, inklusive der ersten und letzten Zeile, einfach in die Eingabe des Terminals wirft, wird automatisch die Datei am richten Ort erzeugt, ohne das man einen Editor bemühen muss! 
Wer das nicht will, der kopiert den Text ohne die erste und letzte Zeile in den Editor seiner Wahl.

Das Ganze muss noch ausführbar gemacht und aktiviert werden:
chmod +x /etc/init.d/loop
/etc/init.d/loop enable
/etc/init.d/loop start 
Mit dem Befehl service kann man überprüfen ob der Dienst angekommen ist und ihn auch steuern.
root@wrt1900:~# service
service "" not found, the following services are available:
boot              dropbear          linksys_recovery  network           sysfixtime        uhttpd
cron              firewall          lm-sensors        odhcpd            sysntpd           umount
dnsmasq           gpio_switch       log               rpcd              system            urandom_seed
done              led               loop              sysctl            ucitrack

War es das schon?

Es gibt natürlich weitere Ideen:

  • Umstieg auf Eventbasierte Abarbeitung ähnlich wie im verlinkten Beispiel.
  • Konfigurierbare Abfrage mehrerer Clients
  • Auslesen aller Host und Übergabe an FHEM 
Aber jetzt will ich erstmal diesen Prozess eine Weile Probe laufen lassen und ein Monitoring des Routers einrichten.

Mittwoch, 8. August 2018

Lokale Namen OpenWrt

Mit der Fritzbox war es immer etwas mystisch: Wann klappt die Namens Auflösung von lokalen Geräten? Am Ende war nur noch Konfiguration mit IP Adressen anstatt Namen angesagt. Blöd wenn man mal etwas umstellen will. Mit OpenWrt sollte es doch jetzt alles klar beherrschbar sein!?

Erkenntnisse

Scheinbar werden von dnsmasq die lokalen Namen erst geliefert, wenn die DHCP Clients die Lease aktualisiert haben. Theoretisch überleben die Leases auch einen Neustart des Routers. Ich hatte aber oft die Situation, da war nach dem Start alles erstmal weg. Die Leasetime steht per Standard auf 12 h. Da dauert es dann ganz schön lange, wenn ein Client mal die Lease erneuern will. Irgendwo hatte ich mal gelesen, dass passiert nach der halben Leasetime (6 h). Dafür muss eine Lösung her.
Frage: Wo packt man jetzt Hostnamen hin, damit sie sofort zur Verfügung stehen?
Antwort: /etc/hosts

Code

Die static Leases sind schlecht lesbar wenn sie nur die IP und Mac enthalten, der Hostname sollte da schon mit in die Liste. Damit man nicht alles doppelt halten und konfigurieren muss, wäre es jetzt sinnvoll die static Leases einfach auszulesen und in die hosts Datei zu schreiben.
Teile des Codes habe ich aus dem Ubuntu Wiki.
Die Abschnitte im Code sind entsprechend kommentiert.

#!/bin/ash

# Perform work in temporary files
temphosts1=`mktemp`
temphosts2=`mktemp`
dom=$(uci get dhcp.@dnsmasq[0].domain)

# If this is our first run, save a copy of the system's original hosts file and set to read-only for safety
if [ ! -f ~/hosts-system ]
then
 echo "Saving copy of system's original hosts file..."
 cp /etc/hosts ~/hosts-system
 chmod 444 ~/hosts-system
fi

# Read Hostnames from DHCP
for i in $(uci show dhcp | grep -oE "host\[\d+\].ip"|grep -oE '\d+'); do
  ip=$(uci get dhcp.@host[$i].ip)
  name=$(uci get dhcp.@host[$i].name)
   if [ ! -z $name ]
   then
    echo $ip $name.$dom $name >>$temphosts2
   fi
done

echo -e "\n# Ad hosts from dhcp "`date` | cat ~/hosts-system - $temphosts2 > $temphosts1

cp $temphosts1 /etc/hosts

# Clean up temp files and remind user to copy new file
echo "Cleaning up..."
rm $temphosts1 $temphosts2

# The File must be readable for everyone
chmod 644 /etc/hosts

#Restart Service
/etc/init.d/dnsmasq restart
echo "Done."


Dienstag, 31. Juli 2018

Import static Leases in OpenWrt

OpenWrt kann mit speziellen Kommandos (uci) in der Shell konfiguriert werden.
Ich habe mir immer gewünscht, statische DHCP Reservierungen einfach durch Textdateien zu konfigurieren. OpenWrt kann zwar wenigsten in der Weboberfläche die MAC Adressen per Copy&Paste einfügen, aber ich hätte es gern komfortabler.
Wer spielen will, der macht zunächst nichts kaputt. Die Konfigurationsänderungen werden zunächst nur temporär ausgeführt.
Die dhcp Konfiguration anzeigen:
uci show dhcp
uci show dhcp | grep '@host\[0\]'
uci get dhcp.@host[0].ip
Die Host Einträge in der /etc/config/dhcp stehen dort am Ende und sind nicht indiziert. Das uci indiziert sie "fließend" für uns und einen direkten Zugriff:
  • [0] ist der erste, 
  • [-1] der letzte Eintrag.

Vorbemerkung

Ich habe ein paar Scripts als heredoc erstellt, die kann man einfach per copy&paste ins Terminal fallen lassen. Damit die $ Zeichen nicht als Variablen interpretiert werden, muss EOF in einfache ' ' gesetzt werden!
Die uci arbeitet temporär, man kann sich mit uci changes den Erfolg anzeigen lassen. Mit uci revert dhcp kann man alles immer wieder rückgängig machen.
Erst ein uci commit schafft Tatsachen.

Hosts hinzufügen

Will man einen neuen Host eintragen geht das mit folgendem Beispiel. Ein neuer Eintrag wird angefügt und ist damit der Letzte, dieser wird um die Werte ip und mac ergänzt:
script="addhost.sh"
cat <<'EOF' >$script
#!/bin/sh
if [ $# -eq 3 ]
  then
    echo "name=$1 ip=$2 mac=$3"
  else
    echo "Fehler: Bitte name ip und mac angeben."
    exit
fi
uci add dhcp host
uci set dhcp.@host[-1].name=$1
uci set dhcp.@host[-1].ip=$2
uci set dhcp.@host[-1].mac=$3
EOF
chmod +x $script
Jetzt kann man eine existierende Lease Zeile aus dem Browser kopieren und als Reservierung einfügen
./addhost.sh HPF43909586B94 192.168.56.111 F4:39:09:58:6B:94
Mit einer Schleife kann man Zeilenweise den stdin lesen und und pro Zeile einen neuen Hosteintrag erstellen. Damit die static Leases lesbar bleiben sollte ein Hostname mit in die Tabelle.
Read Host per Line -> rhpl.sh
script="rhpl.sh"
cat <<'EOF' >$script
#!/bin/sh
while read line; do
./addhost.sh $line
done
EOF
chmod +x $script
Dazu eine Datei mit Wertepaaren -> wp.txt
host1 192.168.1.1 aa:bb:cc:dd:ee:d1
host2 192.168.1.2 aa:bb:cc:dd:ee:d2
host3 192.168.1.3 aa:bb:cc:dd:ee:d3
Das Ganze mit der Pipe verknüpft und fertig ist der Import!
./rhpl.sh <wp.txt
Nachtrag 2021: Hat man mehrere Dateien, kann man diese gemeinsam lesen, die MAC Adressen in Großbuchstaben wandeln, sortieren, Doubletten entfernen und einlesen
cat leases.txt wpo.txt |awk '{ print( $1,$2,toupper($3) ) }'|sort|uniq|./rhpl.sh
Noch ist nichts aktiv!

Hosts löschen

Will man vor dem Import aufräumen, kann man mit einem (nicht perfekten) Einzeiler erst einmal alle Hosts löschen:
while uci delete dhcp.@host[0]; do :;done
Die Schleife läuft einmal zu viel, deswegen gibt es einen Fehler. Aber alle Hosts sind gelöscht.

Host auslesen

Damit man die Liste der Werte Paar nicht komplette per Hand erstellen muss, kann man existierende Daten auslesen. Die entstandenen Dateien kann man bei Bedarf bearbeiten und anschließend importieren.

Static Leases auslesen

Um alle Hosts in eine Datei zu exportieren, braucht man eine formatierte Ausgabe
printf "$(uci get dhcp.@host[-1].name) $(uci get dhcp.@host[-1].ip) $(uci get dhcp.@host[-1].mac)\n"
Und ein Array mit den vorhandenen Indizes. Ein doppelter "Eierkuchen" liefert uns dies aus dem show Befehl.
echo $(uci show dhcp | grep -oE "host\[\d+\].ip"|grep -oE '\d+')
Eine simple Schleife liefert uns die Wertepaare als Ausgabe.
script="wrlp.sh"
cat <<'EOF' > $script
#!/bin/sh
for i in $(uci show dhcp | grep -oE "host\[\d+\].ip"|grep -oE '\d+'); do
  printf "$(uci get dhcp.@host[$i].name) $(uci get dhcp.@host[$i].ip) $(uci get dhcp.@host[$i].mac)\n"
done
EOF
chmod +x $script
Die schreibt man einfach in eine Datei.
./wrlp.sh >wpo.txt

Aktuelle Leases auslesen

Nachtrag 2021: Ich habe noch eine bessere Variante zum Auslesen der aktiven Leases gefunden, lasse aber den alten Code bewusst noch stehen.
cat /tmp/dhcp.leases| awk '$4 != "*" { print( $4,$3,$2 ) }'
Um einfach mal alle existierenden Leases auszulesen genügt ein Einzeiler. Allerdings ist das Ausgabeformat anders als im Beispiel oben: mac IP Host (Darstellung im Browser Host IP mac)
cat /tmp/dhcp.leases |grep -oE '([a-f0-9]{2}:){5}[a-f0-9]{2}\s[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}\s[A-Z,a-z,0-9,-,_]*'
Das Script macht ein match auf mac Adresse, IP Adresse und String (Hostname)

Ich habe noch eine vereinfachte Form "experimentell" gefunden (\s.*\s passt auf IP Adresse und Hostname - warum? Der Rest wird abgeschnitten).
Aus der Ausgabe kann man noch per Pipe mit grep die Zeilen mit unbekannten Hostnamen (*) entfernen und mit awk formatieren.

grep -oE '([a-f0-9]{2}:){5}[a-f0-9]{2}\s.*\s' /tmp/dhcp.leases|grep -v "*"|awk '{print $3,$2,$1}'

Finale

Das uci System arbeitet temporär, will man seine Änderungen fest machen, muss man diese speichern und das jeweilige System(dhcp) neu starten. 
Achtung: Scheinbar wird seit einiger Zeit nicht mehr dnsmasq sondern odhcpd für den DHCP Service verwendet. Offenbar genügt aber ein commit Befehl den restart & reload kann man sparen?
uci commit dhcp
/etc/init.d/dnsmasq restart
luci-reload

Die uci Schnittstelle ist auch über JSON erreichbar.
wiki.teltonika.lt

Mittwoch, 27. Juni 2018

OpenWrt Router abfragen

Dieser Beitrag im Forum gab den Ansatz für eine Abfrage des OpenWrt Routers nach angemeldeten Wlan Clients. Für mich als Halbwissender war es mal wieder gar nicht einfach den kurzen Artikel umzusetzen. Deswegen hier etwas ausführlicher.

Vorbereitung des Routers

Für das cgi Script braucht man die Komponente bash auf dem Router, das ist schnell installiert.
System / Software im Feld "Download and install package:" einfach bash eintippen und Ok drücken.
Im Pfad /www/cgi-bin/ muss man jetzt eine Datei wifi-client mit folgendem Inhalt anlegen (z.B. mit WinsSCP).
Ich habe gegenüber dem Original Artikel noch die Umwandlung von Gross in Kleinbuchstaben eingebaut.
Die Zeile im Code unterhalb dem Hinweis  # Pfade anpassen je nach AP-Config!! muss man unbedingt anpassen!
Je nach dem welche Wlan Hardware verbaut ist:
  • radio0 -> phy0 
  • radio1 -> phy1
Und welche Wlans definiert sind (Beispiel):
  • wlan1 -> netdev:wlan1
  • wlan1-2 ->  netdev:wlan1-2
Die Benennung war hier nicht ganz konsequent ableitbar, also unbedingt im Pfad /sys/kernel/debug/ieee80211 nachschauen! Oder mit dem Befehl iwinfo die Liste der Wlan Namen ausgeben.
#!/bin/bash

# Decodes an URL-string
# an URL encoding has "+" instead of spaces
# and no special characters but "%HEX"
function urlDec() {
  local value=${*//+/%20}                   # replace +-spaces by %20 (hex)
  for part in ${value//%/ \\x}; do          # split at % prepend \x for printf
    printf "%b%s" "${part:0:4}" "${part:4}" # output decoded char
  done
}

# For all given query strings
# parse them an set shell variables
function setQueryVars() {
  local vars=${*//\*/%2A}                      # escape * as %2A
  for var in ${vars//&/ }; do                  # split at &
    local value=$(urlDec "${var#*=}")          # decode value after =
    value=${value//\\/\\\\}                    # change \ to \\ for later
    value=${value,,}                           # upper in lower case 
    eval "CGI_${var%=*}=\"${value//\"/\\\"}\"" # evaluate assignment
  done
}

# Execute the evaluation
# set all variables for both, POST and GET data
# $QUERY_STRING ist part of the environment and contain the part after ?
setQueryVars $QUERY_STRING $(</dev/stdin)

# Set formatting the Response to plain Text
echo Content-type: text/plain
echo
# for the Query ?dev=xxxxxx&test=yyyyyy
# Query dev= -> $CGI_dev contain value after dev=
# Query test= -> $CGI_test contain value after test= 
# Test the string contain only numbers,lower letters and :
case $CGI_dev in
        *[!0-9a-f:]*|"") echo "NOK MAC"; exit 0;;
esac

# Pfade anpassen je nach AP-Config!!
if [ -d "/sys/kernel/debug/ieee80211/phy1/netdev:wlan1/stations/$CGI_dev" ] || [ -d "/sys/kernel/debug/ieee80211/phy1/netdev:wlan1-1/stations/$CGI_dev" ] || [ -d "/sys/kernel/debug/ieee80211/phy1/netdev:wlan1-2/stations/$CGI_dev" ] || [ -d "/sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/$CGI_dev" ]; then
       echo "connected"
else
       echo "no device"
fi
Diese Datei braucht jetzt nur noch das Ausführen (x) Recht für Alle, kann man auch gleich mit WinSCP machen.

Ohne Weiteres kann man sofort die Funktion testen:
http://wrt1900/cgi-bin/wifi-client?dev=11:22:33:aa:bb:cc
Bei bekannter MAC Adresse erscheint ein connected als Quittung, ansonsten eine entsprechende Ausgabe.

Funktion in 99_myUtils.pm

Um diese Abfrage in einem PRESENCE Device zu verwenden, braucht man noch eine kleine Perlfunktion.
sub wlan_det($) {
use LWP::UserAgent;
my ($client)= @_;
        my $ua = new LWP::UserAgent;
        my $response = $ua->get('http://wrt1900/cgi-bin/wifi-client?dev='.$client);

        unless ($response->is_success) {
                              return 99;
        }

        my $content = $response->decoded_content();

        if ($content =~ m/connected/) {
                              return 1;
        } else {
                              return 0;
        }
}
Ich musste gegenüber dem Originalbeitrag noch die Zeile mit "use LWP:.." ergänzen. Es ist eigentlich besser diese einmalig am Anfang der 99_myUtils.pm nach der Zeile
"# Enter you functions below _this_ line."
und vor allen eigenen Subs zu platzieren.
Die Definition in FHEM ist wie gewohnt:
defmod iPhone PRESENCE function {wlan_det("11:22:33:aa:bb:cc")}

Nacharbeit

Das war jetzt quick&dirty -  man kann noch
  • die Übergabe oder Definition der Router IP besser machen.
  • die Definition der abzufragenden Pfade im Router verbessern.
  • Prüfen was genau passiert wenn der Router nicht erreichbar ist (FHEM blockiert?)
  • Die Abfrage funktioniert so nur für Wifi, LAN Clients ermitteln? 

Dienstag, 19. Juni 2018

RaspberryPi mit OpenWrt/Lede

Auch für den Raspberry gibt es ein fertiges Image des Router Systems. Ob man den Raspberry wirklich als Router betreiben will sei mal dahin gestellt, als Testsystem oder DHCP Server taugt er aber allemal.
Das Image gibt es jeweils getrennt im Zweig brcm2708 im Unterpfad

  • bcm2708 -> B und B+
  • bcm2709 -> B2
  • bcm2710 -> B3

Für den B3+ muss man derzeit ein Image aus dem Snapshot Bereich nehmen.

Das gepackte Image (img.gz) muss zunächst entpackt werden (z.B. 7-Zip) und wird dann wie beim Pi üblich, mit einem passenden Programm (Win32DiskImager) auf die SD Card geschrieben.

Partition vergößern

Die resultierende Partition ist nur 256 MB groß. Wer etwas mehr auf dem Pi machen will als nur "Router" sollte die Partition von Beginn an vergrößern, online und innerhalb von OpenWrt geht das schwierig. Ich habe etwas herum probiert und bin zu folgendem Weg gekommen:

  • SD Card mit dem Kartenleser an einen vorhandenen Linux PC (z.B. Raspberry) anschließen.
  • der Stick wird als /dev/sda aktiviert und nicht gemounted
  • parted (oder parted /dev/sda) aufrufen
  • mit p(rint) vergewissern das richtige Laufwerk zu haben.

(parted) p
Model: SABRENT SD (scsi)
Disk /dev/sda: 15,8GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  25,2MB  21,0MB  primary  fat16        boot, lba
 2      29,4MB  298MB   268MB   primary  ext2

(parted)

  • resizepart 2 eingeben
  • Das neue Ende der Partition eingeben, z.B. 3GB
  • quit für exit
  • mit resize2fs muss das Filesystem angepasst werden
resize2fs /dev/sda2
resize2fs 1.43.4 (31-Jan-2017)
Die Größe des Dateisystems auf /dev/sda2 wird auf 725254 (4k) Blöcke geändert.
Das Dateisystem auf /dev/sda2 is nun 725254 (4k) Blöcke lang.


  • Mit e2fsck -f /dev/sda2 muss jetzt das Filesystem nochmal überprüft und repariert werden obwohl beim einfachen Test und auch beim Test vor der Vergrößerung alles "sauber" gemeldet wird.
e2fsck -f /dev/sda2
e2fsck 1.43.4 (31-Jan-2017)
Durchgang 1: Inodes, Blöcke und Größen werden geprüft
Inode 7, i_size ist 62963712, sollte 67178496 sein.  Reparieren? ja
Durchgang 2: Verzeichnisstruktur wird geprüft
Durchgang 3: Verzeichnisverknüpfungen werden geprüft
Durchgang 4: Referenzzähler werden überprüft
Durchgang 5: Zusammengefasste Gruppeninformation wird geprüft

/dev/sda2: ***** DATEISYSTEM WURDE VERÄNDERT *****
/dev/sda2: 1064/188416 Dateien (0.0% nicht zusammenhängend), 14433/725254 Blöcke

Erster Start

Der Router Pi läuft jetzt mit der Adresse 192.168.1.1 im Netzwerk. Um ihn für eine Konfiguration erreichbar zu machen, müssen wir dem PC zur Konfiguration einen IP Adresse z.B. 192.168.1.5 geben. Eine Variante Windows Powershell zeige ich hier.
Die Anmeldung erfolgt mit root ohne Passwort. Nicht vergessen: Als erstes ein Passwort vergeben.
Im Menü über / Network / Interfaces / Edit / das Protocol auf DHCP Client stellen, den Knopf "switch protocol" drücken und abschließend "Save & Apply" drücken.
 


Der Router bekommt jetzt eine Adresse aus dem lokalen Netzwerk und die lokale Adresse des Konfiguration PC kann zurück gestellt werden.
Damit später alle Zeiten im Log stimmen, sollte die Zeitzone auf Europe/Berlin gestellt werden.

Der Pi kann mit zusätzlichen Interfaces (USB LAN oder USB WLAN oder internes WLAN) arbeiten.
Achtung:! Mit der Version 18.06 hat sich das Verhalten verändert. Es wurde eine neue Sicherheit gegen Fehlkonfiguration eingebaut. Die führt leider dazu, das innerhalb 30 sec die Konfiguration zurückgerollt wird, wenn das Webinterface nicht erreichbar war.
Ich weiß noch nicht, wie man wirklich damit umgeht. Einzig mir bekannt bisher ist: warten bis dieses Fenster kommt, den roten Knopf drücken und erst dann die IP-Konfiguration des PC zurückstellen.

Zusätzliches Netzwerkinterface installieren

In der bisherigen Konfiguration ist das System nicht zu viel mehr zu gebrauchen als DHCP Server und um mit der Oberfläche zu spielen. Es empfiehlt sich das Software Paket usbutils zu installieren, damit hat man auf Kommandozeile den Befehl lsusb zur Verfügung und kann zumindest schauen ob der USB Adapter erkannt wird.

LAN Interface

Mit diesem Adapter hatte ich bisher gute Erfahrungen beim Pi:
I-Tec USB 2.0 Advance 10/100 Fast Ethernet LAN Network Adapter USB 2.0 auf RJ45
Er hat einen Asix AX88772B Chip. Durch die Installation des Packages kmod-usb-net-asix wird der Adapter problemlos in Betrieb genommen. Falls noch nicht geschehen muss als erstes der Knopf Update lists gedrückt werden!


Der USB Netzadapter wird sofort erkannt und in Betrieb genommen.
Im Menü Network/Interfaces -> New Interface steht er als eth1 zur Auswahl:

Nachdem Submit gedrückt wurde kann man die IP Adresse und die Subnet Mask eingeben. Hier wird normalerweise kein Gateway eingetragen!
Da dieser Anschluss in Zukunft der interne LAN1 Anschluss ist, wird er der Firewall Zone "grün - lan" zugeordnet.

Wir haben jetzt einen Router mit zwei LAN Segmenten ohne NAT.

Routing vs Forwarding/NAT

Damit das LAN1 Segment aus dem LAN Segment erreichbar wird, muss der vorhandene Internetrouter eine zusätzliche Route für das Netzwerk LAN1 mit dem Gateway LAN bekommen.

Will man Router ohne Veränderung des existierendes Netzwerk betreiben braucht man NAT. NAT wird einfach durch die Firewall Zone WAN aktiviert, aber Vorsicht! Damit passieren zwei Dinge:

  • NAT wird aktiviert
  • Die Firewall Regeln sehen den Anschluss LAN dann sofort als Internetanschluss. Jeglicher eingehender Verkehr wird blockiert.

Wir greifen derzeit über den Anschluss (LAN) zu, dieser wird nach dieser Konfiguration nicht mehr aus dem Netzwerk LAN erreichbar sein! Also besser jetzt gleich zum Test und zur Konfiguration "das Notebook" an den LAN1 Anschluss verbinden und neu anmelden.
Interface LAN / Edit / Firewall Settings / WAN auswählen. So sieht das Ergebnis aus:

NAT wird innerhalb weniger Sekunden aktiviert und der Zugriff ins Netzwerk LAN und auch ins Internet sollte ohne Änderungen im existierenden Netzwerk funktionieren. Allerdings hat man jetzt meist doppeltes NAT, das verkraften nicht alle Anwendungen (z.B. VPN)

WLAN Interface

Auswahl des richtigen Adapters

Das ist gar nicht so einfach! Diese beiden Adapter habe ich nicht zum Laufen bekommen:
  • TP-LINK TL-WN725N v2 mit Realtek RTL8188EUS Chip
  • "Conrad" RE150U-PA-1T1R mit Realtek RTL8188SU Chip
Offenbar verhindern inkompatible Treiber den Betrieb als Routerinterface, im normalen Raspbian werde beide Adapter als Client unterstützt.
Diesen Adapter gab es preiswert und der hat auf Anhieb funktioniert. Er verleiht dem Ganzen durch seine beiden Antennen auch einen Router-mäßigen Eindruck:
  • CSL USB 2.0 WLAN Adapter 300Mbit (2,4/5GHz) mit Ralink RT5572 Chip
Nicht zu viel erwarten: der Adapter hat aber nur ein Radiointerface und kann 2,4 oder 5 GHz und nicht beides gleichzeitig!
Den Adapter stecken und lsusb gibt uns die entsprechende Information aus:
Bus 001 Device 004: ID 148f:5572 Ralink Technology, Corp. RT5572 Wireless Adapter
Der Chipsatz braucht das Softwarepaket kmod-rt2800-usb nach der Installation ist aber zunächst nicht viel passiert. Im Systemlog sollte aber eine Meldung in der Art auftauchen
kern.info kernel: [  624.833819] ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 5592, rev 0222 detected
Ich habe Wireless im Menü zum Leben erweckt, in dem ich mutig auf der Seite System /Startup den network "Restart" Knopf gedrückt habe. Nach kurzem selbsttätigem Refresh der Oberfläche war der Punkt Network / Wireless sichtbar.
Bei einem neuerlichen Versuch mit OpenWrt 22.03 reicht der restart von network nicht, man muss das System neu starten.
Jetzt kann man das Wireless Netzwerk wie gewohnt einrichten.
Allerdings ist das Bild trügerisch. Es funktioniert noch nicht richtig!
OpenWrt braucht offenbar dafür noch etwas Software. Ich habe nur dieses Paket installiert, die anderen aus der dem Link waren nicht notwendig, obwohl die im Image von meinem WRT1900ACS von Hause aus drin waren. Ich werde das noch untersuchen, siehe Zusammenfassung.
  • block-mount
Danach kann man sich zumindest im 2,4 GHz Modus verbinden, wenn man einfach eine default Konfiguration wählt und bei Device Configuration/Advanced Settings Country Code DE auswählt.

Für eine funktionierende 5 GHz Konfiguration darf Channel nicht auf auto stehen - Bug oder Feature?

Zusammenfassung meiner minimalen Konfiguration

  • Beim Download das ext4 Image nehmen, mit dem squashfs Image bin ich nicht klar gekommen.
  • primäres LAN Interface: switch Protocol to DHCP Client
  • Zeitzone: Europe/Berlin
  • Software installieren: Update List
    • usbutils (optional)
    • kmod-usb-net-asix
    • kmod-rt2800-usb
    • block-mount - offenbar mit Version 18.06 obsolet?
Zumindest mit der neuen Version 18.06 funktioniert damit alles erst einmal. Der 5GHz Modus funktioniert nur mit fester Kanalwahl!

Doku OpenWrt Wireless overview
Doku OpenWrt WiFi configuration

Mittwoch, 1. Februar 2017

EasyBox zerflashed - und nun?

Ich wollte schon immer mal OpenWrt auf einen alten Router flashen. Um zu sehen wie OpenWrt so geht ...
Man kann ja die alten Dinger durchaus einfach noch zum AccessPoint umkonfigurieren. Sie liegen eh in der Kiste und bevor man was neues kauft!?
Ok, die kleinen Repeater verbrauchen nur um die 2 Watt, so eine EasyBox verbraucht ca. 7 Watt. Die Wirtschaftlichkeit schwindet also innerhalb von 2 Jahren.
Die Anleitungen zum EasyBox 803A flashen sind schon etwas alt, nicht mehr ganz aktuell und die Quellen zu manchen Dateien ziemlich versteckt. Aber nicht nur das, ich habe auch erstmal nicht richtig kapiert was zu tun ist. Ein falscher Befehl und Box bootet nicht mehr, deswegen ein kurzes HowTo mit dem was ich getan habe.
Aktuell Juni 2018: Es gibt eine neues OpenWrt Seite und einen überarbeiteten Artikel, der ist wesentlich besser lesbar als der Alte und ich hoffe die Links sind aktuell.