Eine Freifunk-Rückweg-Maschine aufsetzen

Der TP-Link WR1043ND ist ein Wireless-Router mit 32Mb RAM, 8Mb Flash und einem USB2-Anschluss. Dieses Gerät ist recht beliebt bei uns Freifunkern und daher weit verbreitet. Dieses kleine Howto beschreibt, wie man für dieses Gerät die Festplattenverschlüsselung LUKS aufsetzt. Anschließend wird die verschlüsselte Festplatte für ein Systembackup eines Servers / PCs mit Hilfe von rsync/rsnapshot verwendet.

Hintergrund

Es gibt heute für kleines Geld USB-Festplatten mit ansprechenden Größen. Diese kann man z.B. als Dateiserver oder für Backups mit Rsync einsetzen. Nicht überall wo ein Freifunk-Router installiert ist, kann der physische Zugang zu dem Gerät beschränkt werden. Will man also verhindern, dass jedermann die Daten von der Festplatte mitnehmen kann, sollte man die Festplatte verschlüsseln. Leider sind die passenden Programme und Kernel-Module dafür standardmäßig in OpenWrt-Backfire nicht enthalten. In diesem Verzeichnis findest du die benötigten Zusatzmodule (*.ipk-Dateien), um eine LUKS-Festplattenverschlüsselung auf dem Router verwenden zu können.

Zusätzlich sollen inkrementelle Backups mit Hilfe des Programms Rsync erstellt werden. Dazu gibt es zwar das Skript-Programm Rsnapshot, allerdings müsste damit der Router vollen Root-Zugriff auf den PC / Server erhalten. Darum soll hier ein anderes Skript vorgestellt werden, das die gleiche Aufgabe anders herum ausführen kann: der PC / Server hat vollen Zugriff auf den Router und erzeugt inkrementelle Backups auf der am Router angeschlossenen und verschlüsselten Festplatte.

Update: Seit dem August 2012 sind die benötigten Kernel-Pakete (kmod-crypto-*) in den Pberg-Firmware-Paketquellen enthalten.

Voraussetzungen

Hinweis: Man kann ein USB-Speichermedium auch auf dem Router selbst initialisieren und verschlüsseln. Bei einer Festplatte mit 750Gb ist der Router allerdings gnadenlos überfordert. Alleine das Anlegen des Dateisystems braucht wesentlich mehr RAM-Speicher und CPU als das Gerät zur Verfügung hat. Von daher sollten die Initialisierungsschritte auf einem PC ausgeführt werden.

Festplattenverschlüsselung einrichten

Zunächst müssen die passenden Software-Pakete auf dem Router installiert werden. Rufe dazu eine Root-Shell via SSH auf und führe die folgenden Schritte aus.

  1. Die Paketlisten für die installierte Firmware herunterladen: opkg update. Dazu muss nötigenfalls die Datei /etc/opkg.conf angepasst werden.
  2. Das Programm Cryptsetup mit folgenden Befehlen installieren. Hinweis: Um Speicherplatz zu sparen, wird für LVM ein Dummy-Paket installiert. Falls du tatsächlich LVM auf dem Router benutzen willst, muss das komplette Paket (ohne -dummy) installiert werden.
  3. Das Luks-Skript herunterladen und installieren: cd /etc/;wget http://sven-ola.dyndns.org/luks/luks;chmod +x luks

Im Prinzip ist nun bereits alles auf dem Router eingerichtet. Die USB-Festplatte solltest du auf einem Linux-PC initialisieren. Ein Beispiel mit dazu notwendigen Befehlen kannst du dir auch auf dem Router mit /etc/luks setup anzeigen lassen.

  1. Zunächst solltest du die Festplatte mit Hilfe des Programms Fdisk in mehrere Partitionen aufteilen. Eine Swap-Partition mit 128Mb, eine Hilfspartition mit 384Mb und eine große Datenpartition mit dem Rest ist eine günstige Konfiguration. Der Swap-Speicher wird später für das recht hungrige Rsync benötigt und auf einer Hilfspartition können später zusätzliche Programme oder Daten ohne Verschlüsselung abgelegt werden. Auf einer 750Gb Festplatte sieht das dann so aus:
    root@pclinux:~# fdisk -l -u /dev/sdc
       Device Boot      Start         End      Blocks   Id  System
    /dev/sdc1              63      273104      136521   82  Linux swap / Solaris
    /dev/sdc2          273105     1044224      385560   83  Linux
    /dev/sdc3         1044225  1465144064   732049920   83  Linux
  2. Jetzt wird die 3. Partition mit LUKS verschlüsselt. Tipp: Ein passendes Kennwort kann man z.B. mit apg oder wahlweise mit apg -M SNCL -m 32 erzeugen. Zuerst die USB-Festplatte einmal aus- und dann wieder einstecken, damit die neue Partitionstabelle garantiert neu eingelesen wird. Dann die folgenden Befehle ausführen (dabei das X gegen das richtige Gerät/Partition ersetzen, im obigen Beispiel sdc3):
  3. Die Festplattenverschlüsselung testen. Dazu die USB-Festplatte erneut aus- und dann wieder einstecken. Ein typischer Linux-Desktop zeigt nun einen Kennwortdialog. Nach der Eingabe des Kennwortes kannst du z.B. ein paar Testdateien auf die verschlüsselte Festplattenpartition kopieren. Danach die Festplatte wieder sperren, aushängen und anschließend an den Router stecken.
  4. Prüfe, ob die USB-Festplatte auf dem Router erkannt wird. Dazu mit dmesg -c die Kernelmeldungen anzeigen. Wahlweise mit opkg install fdisk und fdisk -l /dev/sda prüfen.
  5. Jetzt kommt der spannende Moment. Gib ein /etc/luks open. Nach der Eingabe des Kennwortes sollte unter /tmp/LUKS ein entschlüsselter Festplattenspeicher zur Verfügung stehen. Zum Beenden des Zugriffs kannst du /etc/luks close eingeben.

Hinweis 1: Wenn du eine andere Festplatten-Aufteilung oder einen anderen Einhängpunkt als /tmp/LUKS bevorzugst, musst du das Skript /etc/luks auf dem Router anpassen.

Hinweis 2: Falls du eine von anderen aufgesetzte Festplattenverschlüsslung benutzen willst, musst du die benötigten Algorithmen zusätzlich installieren. Beispiel: eine mit den Default-Optionen erzeugte Verschlüsselung (cbc-essiv:sha256) kann so verwendet werden: opkg install kmod-crypto-misc und insmod sha256_generic.

Rückweg-Maschine aufsetzen

Unter Linux kann mit Hilfe von Hard-Links ein und dieselbe Datei mehrfach in einem Verzeichnisbaum vorkommen. Damit ist es möglich, beispielsweise das vollständige Backup des Vortages in einen neuen Verzeichnisbaum zu kopieren der nur wenig zusätzlichen Platz auf der Festplatte benötigt. Der neue Verzeichnisbaum wird anschließend mit Rsync geändert - damit werden dann nur die auf dem Original gelöschten, geänderten oder verschobenen Verzeichnisse und Dateien in dem neuen Verzeichnisbaum aufgenommen. Diese Idee wurde ursprünglich von Mike Rubel unter Easy Automated Snapshot-Style Backups with Linux and Rsync veröffentlicht, dies fand später Eingang in das Programm Rsync (Parameter: --link-dest). Daraus wiederum entstand das Perl-Skript Rsnapshot, mit dessen Hilfe regelmäßige Backups erstellt werden können.

Leider sind Rsnapshot bzw. der Rsync-Parameter --link-dest darauf angewiesen, dass der Backup-Router vollen kennwortlosen Zugriff auf das Original-System erhält (Backup herunterladen). Besser wäre der umgekehrte Fall: das Original-System hat vollen kennwortlosen Zugriff auf den Backup-Router (Backup hochladen). Deshalb wird hier ein neues Programm eingesetzt: Rsyncsnap ist als Shell-Skript realisiert, dass z.B. auch mit der Busybox-Ash-Shell ausgeführt werden kann und auch das Hochladen von inkrementellen Backups unterstützt.

Du kannst das Rsnapshot-Skript aus diesem Verzeichnis herunterladen. Um es in Betrieb zu nehmen müssen folgende Schritte ausgeführt werden. Hinweis: Der Backup-Router hat in diesem Beispiel die IP-Adresse 192.168.1.1.

  1. Du musst einen kennwortlosen SSH-Zugriff von dem Original-System auf den Backup-Router einrichten. Dazu auf dem PC die folgenden Schritte ausführen:
  2. Nun das Rsyncsnap-Skript in einem Texteditor öffnen. Die Einstellungen snapshot_root und sub_backups an dein System anpassen. Wahlweise zusätzliche Einstellungen ändern (siehe Tabelle weiter unten) und das Skript speichern. Dann einen Probelauf starten: ./rsyncsnap. Dies sollte eine Fehlermeldung ausgeben, wenn das Zielverzeichnis auf dem Backup-Router noch nicht existiert.
  3. Nun auf dem Backup-Router sicherstellen, dass die verschlüsselte Backup-Partition eingehängt ist und das Backup-Zielverzeichnis anlegen. In der Beispielkonfiguration geht das mit /etc/luks open und mkdir /tmp/LUKS/backups.
  4. Außerdem wird auf dem Backup-Router das Programm Rsync benötigt: opkg update;opkg install rsync.
  5. Abschließend auf dem Original-System das erste Backup mit ./rsyncsnap anlegen.

Tipp: Das erste Backup ist möglicherweise sehr umfangreich und dauert bei heutigen Festplatten unter Umständen eine ganze Woche oder mehr. Wenn du das erste Backup lokal ausführen willst, stecke die Festplatte an das Original-System und ändere die Einstellung cmd_ssh= (leer) und snapshot_root=/media/LUKS_HDD/backups (Zielverzeichnis ohne Rechnernamen und ohne Doppelpunkt).

Diese Tabelle zeigt die verschiedenen Einstellungen im Rsyncsnap-Skript.

Einstellung Erläuterung
cmd_ssh Das Kommando und die zusätzlichen Parameter für den SSH-Befehl, mit dessen Hilfe eine gesicherte Verbindung vom Original-System zum entfernten Backup-Router aufgebaut wird. Vorgabe: ssh -C (mit Kompression). Tipp: Diese Einstellung leer lassen, um ein lokales Backup anzulegen.
snapshot_root Der Hostname bzw. die IP-Adresse des Backup-Routers und (nach einem Doppelpunkt) das Verzeichnis auf dem Backup-Router, in dass das Backup geschrieben werden soll. Vorgabe: 192.168.1.1:/tmp/LUKS/backups (der Backup-Router ist unter 192.168.1.1 zu erreichen und das Backup wird in ein Verzeichnis unter /tmp/LUKS geschrieben). Tipp: Diese Einstellung auf ein lokales Verzeichnis ohne Doppelpunkt setzen, um ein lokales Backup anzulegen.
sub_backups Ein oder mehrere durch Zeilenumbruch getrennte Einträge von Teilbackups. Mit dem Rsync-Befehl werden keine eingehängten Unterverzeichnisbäume berücksichtigt (Parameter -x), es sind daher möglicherweise mehrere Teilbackups nötig um alle gewünschten Verzeichnisbäume zu übertragen. Jeder Eintrag wiederum enthält 5 oder mehr durch Doppelpunkt getrennte Felder, die in den nächsten Tabellenzeilen erläutert sind. Beispiel: /:root-backup::::/tmp/:/var/tmp:/var/log/.
sub_backups(1) Quelle Teilbackup: Feld für die Angabe des Quellverzeichnisses für das Teilbackup, üblicherweise mit einem Slash (/) am Ende. Ein einzelnes Slash (/) bezeichnet das Wurzelverzeichnis. Dieses Verzeichnis muss auf dem Original-System vorhanden sein.
sub_backups(2) Ziel Teilbackup: Feld für die Angabe des Zielverzeichnisses unterhalb des durch snapshot_root bezeichneten Verzeichnisbaums auf dem Backup-Router. DIeses Feld ohne führendes Slash (/) und ohne Slash am Ende. Darauf achten, dass Teilbackups sich nicht überlappen können.
Beispiel: Teilbackup-Einträge mit /:root, /home/:home und /usr/:usr führen zu
/tmp/LUKS/backups/$(date).00000.daily/root
/tmp/LUKS/backups/$(date).00000.daily/home
/tmp/LUKS/backups/$(date).00000.daily/usr
sub_backups(3) LVM Datenträgergruppe (Volume Group, VG): Dieses Feld leer lassen um LVM nicht zu benutzen. Es besteht die Möglichkeit mit Hilfe eines LVM-Schnappschusses einen konsistenten Datenstand zu sichern (z.B. eine MySQL-Datenbank mit mehreren zugehörigen Dateien). Dazu muss sich das zu sichernde Dateisystem auf einen logischen Datenträger innerhalb einer Datenträgergruppe befinden. Der zu sichernde logische Datenträger und der Schnappschussdatenträger müssen zur gleichen Datenträgergruppe gehören. Achtung: In der Datenträgergruppe muss freier Speicherplatz vorhanden sein, damit zur Laufzeit des Backups bei eventuellen Schreibvorgängen die Originaldaten auf dem Schnappschussdatenträger zwischengespeichert werden können.
sub_backups(4) LVM Datenträger (Logical Volume, LV): Der Name des zu sichernden Datenträgers. Der Datenträger enthält ein Dateisystem, dass über die zugehörige Gerätedatei (/dev/$vg/$lv) in das Dateisystem eingehängt ist. Der Schnappschussdatenträger wird schreibgeschützt angelegt und trägt den mit .rsyncsnap erweiterten Namen (also /dev/$vg/$lv.rsyncsnap). Der Schnappschuss wird unterhalb des durch sub_backup(1) bezeichnete Quellverzeichnis eingehängt. Darauf achten, dass zur Backup-Laufzeit durch diesen Einhäng-Vorgang keine vorhandenen Teilbäume überdeckt werden. Beispiel: Original-Datenträger unter /mnt/data eingehängt, dann könnte die Quelle des Teilbackups mit /mnt/data-backup angeben (nicht /mnt/data verwenden!)
sub_backups(5) LVM Snapshot Size: Größe des Schnappschussdatenträgers. Beispiel: 256M oder 50G. Dieser Platz muss in der Datenträgergruppe noch frei sein. Zudem dürfen während des Backups nicht zuviele Daten auf den Original-Datenträger geschrieben werden, andernfalls wird das Backup abgebrochen.
sub_backups(6...) Ausschlüsse: Alle weiteren Felder des Teilbackup-Eintrages enthalten Angaben, welche Verzeichnisse oder Dateien vom Backup ausgeschlossen werden sollen. Details siehe man rsync, suche nach --exclude.
log_file In diese Datei wird eine Liste der ausgeführten Backup-Befehle geschrieben. Vorgabe: /var/log/rsyncsnap.log
lock_file Diese Datei dient mit Hilfe der Systemfunktion flock dazu, ein laufendes Backup gegen Unterbrechungen durch weitere Backups zu schützen. Tipp: Diese Einstellung kann auch gegen übermäßige Schreibaktionen während des Backups schützen. Wenn hier beispielsweise /var/run/vzdump.lock eingetragen wird, können während des Backups keine OpenVZ-Backups angelegt werden.
lock_wait Falls das lock_file belegt ist, wird das neu gestartete Backup nach dieser Wartezeit (in Sekunden) abgebrochen.
retain_config Schema, nach dem inkrementelle Backups entweder für längere Zeit gespeichert oder verworfen werden. Die Perioden-Bezeichner und Perioden-Anzahlen können willkürlich gewählt werden, sollten aber mit der Aufruf-Frequenz von Rsyncsnap korrelieren. Mit der Vorgabe werden bis zu 7 daily-Backups vorgehalten. Jedes 7. daily-Backup wird zu einem weekly-Backup umbenannt, während überzählige daily-Backups gelöscht werden. Mit der Vorgabe entstehen 7+4+13 Backups, die anschließend als yearly-Backups dauerhaft gespeichert bleiben.
no_create_root Verhindert ein Backup, wenn das Zielverzeichnis auf dem Backup-Router nicht vorhanden oder nicht eingehängt ist. Vorgabe: 1

Die folgenden Ausgaben erhalte ich auf einem Backup-Router, wenn ein inkrementelles Backup läuft. Das inkrementelle Backup dauert hier wegen der umfangreichen Verzeichnisbäume (ein duzend OpenVZ-Maschinen!) mit etwa 2 Stunden recht lange. Einen guten Teil der Zeit benötigt die Verzeichnisbaumkopie mit cp -al.

root@tplink:~# df -h
              total         used         free       shared      buffers
  Mem:        29444        28460          984            0         2784
 Swap:       136512        49600        86912
Total:       165956        78060        87896
root@tplink:~# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 2.4M      2.4M         0 100% /rom
tmpfs                    14.4M    644.0K     13.8M   4% /tmp
tmpfs                   512.0K         0    512.0K   0% /dev
/dev/mtdblock3            4.3M      3.7M    520.0K  88% /overlay
mini_fo:/overlay          2.4M      2.4M         0 100% /
/dev/mapper/LUKS        687.2G     42.7G    609.5G   7% /tmp/LUKS

Tipps: Wenn alles läuft, kann das Rsyncsnap-Skript nach /etc/cron.daily kopiert werden. Die hier hochgeladenen *.ipk-Dateien kann man mit dem Makefile unter ./ff-pberg/ erzeugen. Dazu evnt. im Download-Verzeichnis der Firmware die Datei VERSION.txt konsultieren und die Git-Hashes im Makefile anpassen. Danach sollte ein make die gewüschten Dateien erzeugen.

Sicherheitshinweise

Prinzipbedingt kann eine Festplatte natürlich entwendet werden. Sobald allerdings die Festplatte entfernt wurde, müsste man schon eines der LUKS-Kennwörter kennen, um auf die Daten zuzugreifen. Der kritische Moment ist gekommen, wenn nach einer Weile Backup-Betrieb der Router bzw. die Festplatte aus irgendwelchen Gründen neu gestartet ist und du das LUKS-Kennwort neu eingeben musst.

Nebenbemerkung: Die Jungs mit den scharzen Brillen und dem flüssigen Stickstoff im Handgepäck wird das hier nicht sonderlich beeindrucken. Diese Typen haben ja auch die Lizenz zum Serverklau: sie nehmen notfalls das Originalsystem mit. In diesem Sinne: man muss das mit der Sicherheit nicht übertreiben, aber gegen einfach auszuführende Hacks sollte man vorbauen.

Die folgenden Maßnahmen helfen:

Hinweis: Wirklich sicher kannst du nur sein, wenn du die Unversehrtheit des Routers vor Ort prüfen kannst. Es ist für einen Angreifer immer noch möglich, eine Router-Simulation z.B. mit qemu herzustellen. Du könntest dich mit iwlist wlan0-1 scan wehren. Der Angreifer könnte auch über den Reset-Taster den Failsafe-Modus erreichen um anschließend mit wüsten Tricks einen normalen Startvorgang zu simulieren, wenn du reboot eingibst. Jeweils noch abwarten bis das Kennwort von dir kommt. Zudem ist die hier vorgeschlagene Verschlüsselung aus Performanzgründen ohne ESSIV, mithin verwundbar gegen einen Wasserzeichenangriff. Aber für diese Dinge muss man schon einige Motivation aufbringen (siehe oben, die mit den schwarzen Brillen)...