Backup, HiDrive und rsync

Ich habe vor einiger Zeit in diesem Artikel einmal erklärt, wie man Daten mit encfs verschlüsseln kann. Leider ist der darin verlinkte Artikel nicht mehr verfügbar.

Ich selbst betreibe ein ausgelagertes Backup, in das ich Daten lade, die für mich wichtig sind – also eine gewissen Wert haben und nicht einfach wieder beschafft werden können. Ich verwende dafür „HiDrive“ von Strato. Aber Achtung, ich habe noch einen der alten Tarife. Zwar habe ich bisher noch keine Nennenswerten Ausfälle mit Strato gehabt, aber inzwischen muss man sich die hier verwendeten Übertragungsprotokolle extra zu dem Paket dazubuchen. Dafür finde ich die aktuellen Angebote schlicht zu teuer.
Ich habe kein Problem damit für meinen Onlinespeicher zu bezahlen, immerhin zahle ich dann im Gegensatz zu den vielen „kostenlosen“ Anbietern und kann daher auf Leistung bestehen – trotzdem halte ich von dem „jede dazugebuchte Option kostet Geld“ mal gar nichts. Das war am Anfang, als ich HiDrive gebucht habe, nicht so. Da gab es das Rundumpaket. Und ich sehe keinen Sinn darin Übertragungsprotokolle teuer zu verkaufen. Ehrlich, ist ja nicht so, dass die Brot fressen.
Das ist also eine deutliche Negativentwicklung bei Strato.
Dazu kommt aber vielleicht noch einmal ein extra Artikel, weil mir da so einige Sachen eher seltsam vorkommen.
Wenn ihr also nicht schon Strato-Kunde seid und rsync im Paket habt: Ich rate von einem aktuellen Wechsel zu Strato ab.

So, warum aber dieser Artikel?
Ich habe es durch einen dummen Fehler geschafft mir die Config vom HiDrive und die Daten darauf zu zerlegen. Und meine lokale Einrichtung des Backup-Scripts. Das war doof, und ich musste mir die ganzen Infos wieder suchen. Daher das ganze hier für mich auch als Notiz.

Natürlich kann man das mit etwas umfrickeln für jeden Anbieter verwenden, der die Kommunikation via rsync und webDav (Wiederherstellung) erlaubt.

Das Problem

Ich möchte Daten, die für mich einen gewissen Wert haben, gerne extern verschlüsselt sichern. „Wert“ heißt in diesem Fall, dass diese Daten für mich nicht einfach neu beschafft werden können. Also zum Beispiel Fotos.

Das ganze möchte ich möglichst „automatisch“ erledigt wissen, denn ich kenne mich – passiert es nicht automatisch, dann passiert es gar nicht.

Die Lösung

Ich verwende einen Raspberry Pi, der die Daten von meinem lokalen NAS verschlüsselt und anschließend via rsync zu einem Speicherort im Internet synchronisiert.
Der Vorgang soll automatisch gestartet werden, damit ich mich damit garn nicht beschäftigten muss.

Einrichtung

Das Ziel

Ich möchte die zu sichernden Daten in ein zentrales Verzeichnis einhängen und dieses dann mit rsync auf das HiDrive speichern.

Installation der Software

Ich installiere die Software auf einem Raspberry Pi mit „raspbian“. Die Installation und das Vorgehen funktioniert aber auch mit jedem anderen Betriebssystem, das von Debian abstammt (zum Beispiel Ubuntu und seine Derivate).

Für das von mir verwendete Vorgehen benötigen wir encfs und rsync. Falls noch nicht installiert, dann müssen wir das jetzt tun.
Außerdem legen wir das Verzeichnis /tmp/crypted an. Das wird unser Verzeichnis, das wir auf das HiDrive synchronisieren. Darin werden wir Unterverzeichnisse anlegen, die entsprechend die eigentlichen, verschlüsselten Daten enthalten werden.

sudo apt-get install rsync encfs

So, und für den ganzen Rest habe ich ein Python-Script geschrieben. Klar, das geht bestimmt auch direkt auf der Bash. Das kann ich aber nicht. Nein, das ist nicht ganz richtig. Ich könnte das schon, aber das Terrain auf dem ich mich sicher bewege, das ist Python.

Anlegen der verschlüsselten Verzeichnisse

Bevor wir die Verzeichnisse per Script automatisch sichern können, müssen wir die Grundlagen dafür sorgen, dass die entsprechenden Metadaten angelegt werde.

Ich habe das grundlegende Vorgehen bereits einmal beschrieben.

Wir müssen die entsprechende Verschlüsselungen mit encfs –reverse anlegen. Denn wir wollen ja unsere Klardaten behalten und nur eine verschlüsselte Sicht darauf haben, die wir dann sichern.

Und wir dürfen auf keinen Fall vergessen die .encfs6.xml aus dem Stammverzeichnis zu sichern. Ohne diese Datei ist ein entschlüsseln der Daten nicht mehr möglich!
Also entweder rauskopieren und ab damit auf das HiDrive (muss man dann aber manuell machen) oder an sicherer Stelle verwahren.

Das Backup-Script

Das folgende Python-Script als backup.py (oder ähnlich) speichern. Der Aufruf muss mit sudo erfolgen, da encfs root-Rechte benötigt.

sudo python backup.py

Das Script macht folgendes: Die in SOURCES aufgeführten Verzeichnisse (from) mittels encfs –reverse zu verschlüsseln und unter /tmp/crypted als Unterverzeichnisse (to) zur Verfügung zu stellen. Dass Passwort für die Verschlüsselung wird hier mit angegeben. Das ist natürlich ein Sicherheitsrisiko, wenn die Datei in falsche Hände gerät, dafür ist so aber keine manuelle Eingabe nötig. Und das stände einer automatischen Ausführung im Wege.
Nach dem Mounten der verschlüsselten Verzeichnisse wird das Backup mit rsync durchgeführt. Kommt es zu einem Fehler, zum Beispiel durch einen Disconnect, wird nach SLEEP_AFTER_FAIL Sekunden der nächste Vorgang gestartet.
(Ich nehme übrigens Verbesserungen am Script gerne entgegen, falls jemanden etwas auffällt. Es ist schlicht die Version, die ich verwende. Daher keine großartige Fehlerbehandlung oder Benachrichtigung.)

from __future__ import unicode_literals

# =================================================
# Festlegen einiger Variablen
# Muessen angepasst werden

# Verzeichnisse, die verschluesselt eingehaengt werden sollen
# Je Eintrag: "from"     ist das Quellverzeichnis
#             "to"       ist der Name des Zielverzeichnisses unter "CRYPTED_DIR"
#             "password" ist das Passwort fuer die Verschluesselung
SOURCES = (
{"from": "/home/name/fotos/", "to": "f", "password": 'deinPasswort'},
)

# Rsync-Ziel bei einem Hidrive. "benutzername" muss hier ausgetauscht werden
RSYNC_TARGET = "benutzername@rsync.hidrive.strato.com:/users/benutzername/backup"

# Wenn bei dem rsync etwas schief geht (24 Stunden Disconnect, etc.)
# wird so viele Sekunden vor einem erneuten Versuch gewartet:
SLEEP_AFTER_FAIL = 60

# =================================================


# Variablen die wir nicht anpassen muessen:

CRYPTED_DIR = "/tmp/crypted"
LOCKFILE = "/tmp/backup.lock"

# Ende der Variablen

from subprocess import call, PIPE, Popen
import fcntl
import os, sys, time

def check_lock(lockfile):
    if os.access(lockfile, os.F_OK):
        with open(lockfile, "r") as pidfile:
            old_pid = pidfile.readline()
            if old_pid != "" and os.path.exists("/proc/{0}".format(old_pid)):
                log("Programm is allready running with PID {0}".format(old_pid))
                return False
            else:
                os.remove(lockfile)
    with open(lockfile, "w") as pidfile:
        pidfile.write(str(os.getpid()))
    return True

def create_crypted_dir(d):
    log("Create {0} (if not exists)...".format(d))
    if not os.path.exists(d):
        os.makedirs(d)

def do_rsync(source_dir, target):
    while True:
        log("Starting sync...")
        command = ["rsync", "-rltDvzre", '"ssh"', source_dir, target]
        log("  '{0}'".format(" ".join(command)))
        ret = call(command)
        if ret == 0:
            break
        else:
            time.sleep(SLEEP_AFTER_FAIL)

def log(text, newline=True):
    sys.stdout.write(text)
    if newline:
        sys.stdout.write("\n")

def mount_encfs_dirs(sources, crypted_dir):
    for source in sources:
        source_dir = source["from"]
        target_dir = os.path.join(crypted_dir, source["to"])
        if not os.path.exists(target_dir):
            log("Creating '{0}'...".format(target_dir))
            os.makedirs(target_dir)
        log("Mount '{0}' to '{1}'...".format(source_dir, target_dir))
        if not test_allready_mounted(target_dir):
            command = ("encfs", "--reverse", "--stdinpass", source_dir, target_dir)
            log("  command: {0}".format(" ".join(command)))
            p = Popen(command, stdin=PIPE, stdout=PIPE)
            c = p.communicate(source["password"])
            r = p.wait()
            if r != 0:
                raise Exception("Failed to mount {0} to {1}".format(source_dir, target_dir))
        else:
            log("  seems allready mounted...")

def test_allready_mounted(target_dir):
    p = Popen(("mount"), stdin=PIPE, stdout=PIPE)
    for line in p.stdout.readlines():
        parts = line.split()
        if parts[2] == target_dir:
            return True
    return False


def main():
    if not check_lock(LOCKFILE):
        sys.exit(1)
    create_crypted_dir(CRYPTED_DIR)
    mount_encfs_dirs(SOURCES, CRYPTED_DIR)
    do_rsync(CRYPTED_DIR, RSYNC_TARGET)


if __name__ == "__main__":
    main()

Wiederherstellung

Das beste Backup nützt nichts, wenn man die Daten nicht wiederherstellen kann.

Es ist wichtig, dass man die Möglichkeit der Wiederherstellung in regelmäßigen Abständen prüft. Es ist einfach die Daten in die Wolke zu schieben. Der Schrecken ist groß, wenn man bemerkt, dass die Verschlüsselung nicht wiederherstellbar ist.
Gut, wenn das passiert, wenn man es ausprobiert. Schlecht, wenn man das Backup tatsächlich braucht.

Wir hängen das HiDrive per WebDav ein und sorgen für eine entsprechende Entschlüsselung.

Laut ubuntuuser-Wiki braucht man folgende Pakete um WebDav als Dateisystem mounten zu können:

sudo apt-get install ca-certificates davfs2

Wir legen ein Verzeichnis unter /tmp/ an und mounten dann mittels davfs2 dort das HiDrive:

sudo mkdir /tmp/hidrive_crypted/
sudo mount -t davfs https://webdav.hidrive.strato.com /tmp/hidrive_crypted

Benutzername und Passwort werden anschließend abgefragt. Wenn alles klappt steht der Inhalt vom HiDrive anschließend unter /tmp/hidrive_crypted zur Verfügung.

Jetzt müssen wir den Inhalt natürlich noch entschlüsseln. Wenn wir bei unserem Beispiel aus dem Script bleiben, müssen wir wie folgt vorgehen, wobei der Ort für die encfs6.xml angegeben werden muss – je nachdem wo sie liegt. Ich habe ja bereits weiter oben geschrieben, dass ohne Datei keine Entschlüsselung möglich ist.
‚benutzername‘ müssen wir wieder durch unseren Benutzernamen auf dem HiDrive ersetzen.

ENCFS6_CONFIG=/tmp/encfs6.xml encfs /tmp/hidrive_crypted/users/benutzername/backup/crypted/f/ /tmp/fotos

Wenn alles geklappt hat, können wir uns nun unter /tmp/fotos unser Fotos anschauen. Entschlüsselt auf unserem Rechner mit Livedaten aus dem HiDrive.

— der Würschlmann

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s