Mehr Sicherheit fuer die eigenen Daten – vollverschluesselte Festplatten auf Servern

Dieses ist der neunte Teil einer Serie von Blogeintraegen, die sich als Reaktion auf die NSA Affaere um den Kontext Sicherheit fuer die eigenen Daten und Verschluesselung drehen.

Links zu den ersten acht Artikeln befinden sich am Ende des Blogposts. Im neunten Teil moechte ich meine Ueberlegungen zu selbstgehosteten Servern und deren Sicherheit im Kontext Verschluesselung der Festplatten vorstellen.

Wenn ich eine verschluesselte Verbindung zu einem anderen Rechner / Dienst im Internet aufbaue kann ich das ungewollte Mitlesen der Kommunikation erschweren bis verhindern. Speichere ich nun die Daten auf eigenen Servern und vertraue sie nicht Firmen wie Google (Mail, Drive), Microsoft (Outlook.com, Skydrive) oder Amazon Cloud (Dropbox) an, dann erschwere ich auch erst einmal das ungewollte Lesen meiner Daten. Ich bin ja schliesslich kein Administrator auf dem anderen Server und weiss nicht wann sich wo auf deren Seite jemand potentiell dazwischen schaltet.

Meine Daten liegen also auf einem selbstgehosteten Server und ich baue eine verschluesselte Verbindung dahin auf. Die Daten auf dem Server selbst sind aber immer noch unverschluesselt gespeichert. Es kann also potentiell jemand ins Rechenzentrum gehen, sich den Server schnappen, analysieren und die Daten dort herunter ziehen. Was liegt da naeher als die Festplatten zu verschluesseln.

Mit LUKS (klick) steht dafuer unter Linux auch eine gute Loesung zur Verfuegung. Auf meinem Laptop oder meinem Arbeitsplatzrechner setze ich sie bereits ein. Ist ja auch kein Problem beim Booten das Passwort einzugeben. Das bei einem Server zu tun ist es schon sehr viel umstaendlicher, denn man sitzt ja eigentlich nie direkt davor…

Ich werde hier nun keine Anleitung schreiben wie man die Schritte 1:1 geht um seine Festplatte mit LUKS zu verschluesseln. Davon gibt es bereits genuegend im Netz. Einige Distributionen wie Debian bieten es sogar im Installer gleich an die Festplatte mit LVM zu erzeugen und dann mit LUKS zu verschluesseln. Die Stichworte beim Suchen nach entsprechenden Dokumentationen sind Distributionsname + „LUKS“ oder „cryptsetup“ oder „encrypted filesystem“. Nicht zu vergessen auch unter /usr/share/doc/cryptsetup/ nach zuschauen!

Der Clou an der Geschichte ist nun, das man einen dropbear SSH Server in die initramfs seines Servers hinzufuegen kann. So ist es moeglich waerend des Bootvorgangs eine SSH Verbindung in die initramfs aufzubauen und dort das Passwort zum entschluesseln der Festplatte einzugeben. Damit das ganze komfortabel wird, nutze ich dafuer SSH-Keys ohne Passwort in Verbindung mit einem Miniskript pro Maschine.

Boese boese mag sich nun mancher denken, aber alles halb so wild. Ich habe eine Maschine die ist unverschluesselt. Einfach, weil Sie es nicht benoetigt und dort nichts wichtiges abgespeichert ist. Auf dieser Maschine habe ich einen Ordner mit ecryptfs verschluesselt (klick fuer Anleitung). In diesem Ordner bewahre ich folgendes auf:

  1. private Keys fuer die Verbindung zu dem Dropbear Servern im initramfs der virtuellen Maschinen
  2. eigene known_hosts Datei dafuer
  3. Ein Skript pro VM das mir die Eingabe des Passworts erleichtert.

Das Skript sieht schematisch wie folgt aus:

#!/bin/bash
 
ssh -o "UserKnownHostsFile=known_hosts/known_hosts.initramfs" -i "keys/servername" root@1.2.3.4 "echo -ne "**TOPSECRET**" >/lib/cryptsetup/passfifo"

Wenn ich nun einen Server neu starte bei dem die Festplatte verschluesselt ist, dann melde ich mich auf der unverschluesselten Maschine an, mounte den ecryptfs verschluesselten Ordner und muss dann nur noch das entsprechende Skript starten, z.B. ./unlock_servername und schon bootet die Maschine durch.

In diesem Kontext sicherlich noch einmal spannend ist auf einen drei Jahre alten Blogeintrag „Howto: virsh console“ zu verweisen um sich das ganze auch vom physikalischen Server aus anzuschauen ;-)

Vorherige Blogposts:

  • Der erste Teil war fuer mich das Aufraeumen, einen Ueberblick zu bekommen sowie Strukturen zu schaffen, auf denen ich aufbauen kann.
  • Der zweite Teil bestand darin einen Ort zu schaffen, in dem ich Keys und Passwoerter sicher aufbewahren und gleichzeitig alles in ein vernuenftiges Backup schieben kann.
  • Der dritte Teil bezog sich auf das erzeugen von Zertifikaten und Einrichten von verschluesselten Verbindungen zu Apache vHosts.
  • Der vierte Teil drehte sich um das Thema Komfort im Webbrowser und verwies in dem Kontext auf einen Artikel zum selbst gehosteten Firefox Sync Server.
  • Im fuenften Teil habe ich etwas zu meinen Ueberlegungen zu sicheren Zugangsdaten und Passwoertern geschrieben.
  • Im sechsten Teil dreht es sich darum, wie man sich auf seinen Servern mit SSH aber ohne Passwort sicher authentifizieren kann.
  • Der siebte Teil behandelt das Thema Backup und zeigt eine Moeglichkeit wie man selbiges einfach konfiguriert und verschluesselt auf einem externen Speicher ablegen kann.
  • Der achte Teil stellt webbasierte Dienste vor, die man selber hosten kann und dadurch die eigenen Daten unter mehr Kontrolle hat.

Mehr Sicherheit fuer die eigenen Daten – verschluesseltes Backup

Dieses ist der siebte Teil einer Serie von Blogeintraegen, die sich als Reaktion auf die NSA Affaere um den Kontext Sicherheit fuer die eigenen Daten und Verschluesselung drehen.

Links zu den ersten sechs Artikeln befinden sich am Ende des Blogposts. Dieser siebte Teil behandelt das Thema Backup und zeigt eine Moeglichkeit wie man selbiges einfach konfiguriert und verschluesselt auf einem externen Speicher ablegen kann.

Natuerlich moechte ich von meinem Server ein Backup machen. Es waere aber dumm, wenn ich alle meine Daten die ich dort sammle und verschluesselt dorthin transportiere, anschliessend unverschluesselt auf einen Speicherplatz lege, den ich nicht selber ueberwache.
Bei mir ist es nun so, dass mir der Hostinganbieter (Hetzner) 100GB kostenlosen FTP Speicherplatz fuer Backups anbietet. Wenn ich den nutzen moechte muss ich also das Backup verschluesseln. Viele Jahre habe ich mit Backup Manager dort ein unverschluesseltes Backup abgelegt und war damit immer zufrieden. Das Projekt scheint inzwischen eingeschlafen zu sein, und durch meinen Arbeitskollegen bin ich auf duply hingewiesen worden. Ich moechte an dieser Stelle das Setup vorstellen, mit dem ich Full und Incremental Backups mit duply erzeuge und GPG verschluesselt auf dem Hetzner FTP Speicher ablege.

duply installieren

duply kann aus den Standardrepositories installiert werden:

aptitude install duply

Damit die Konfigurationsdateien unter /etc/duply/ und nicht unter ~/.duply/ liegen muss das Verzeichnis unter /etc angelegt werden:

mkdir /etc/duply

Als naechster Schritt wird ein neues Profil erzeugt. Ich habe dafuer den Hostname genommen:

duply create HOSTNAME

Die Konfigurationsdatei des Profils befindet sich nun unter /etc/duply/HOSTNAME/conf

GPG Key generieren und duply konfigurieren

Nun wird fuer die Verschluesselung des Backups ein GPG Key benoetigt. Mit dem folgenden Befehl wird ein neuer Key erzeugt. Ich habe alle voreingestellten Werte beibehalten:

gpg --gen-key

Wenn der Vorgang abgeschlossen ist wird etwas gesagt nach dem Motto: „Schluessel ABC123D4 ist als uneingeschraenkt vertrauenswuerdig gekennzeichnet“. Die Schluessel ID in diesem Fall merken und zusammen mit dem vergebenen Passwort in die /etc/duply/HOSTNAME/conf eintragen:

GPG_KEY='ABC123D4'
GPG_PW='B1-r6UF9s:Mb<%'

Der naechste wichtige Schritt ist in der Konfigurationsdatei anzugeben wo das Backup gespeichert werden soll. Dafuer gibt man – in diesem Fall den Hetzner FTP – wie folgt ein:

TARGET='ftp://u12345:abc123def456ghj7@u12345.your-backup.de/backup_HOSTNAME'

Ich habe bewusst einen Unterordner backup_HOSTNAME angegeben, damit ich auf den gleichen Speicher mehrere Hosts sichern kann und dabei nicht durcheinander gerate. Weiter habe ich die folgenden Optionen gesetzt, die ich hier inklusive Kommentare aus der Konfigurationsdatei aufliste::

# base directory to backup
SOURCE='/'
 
# Time frame for old backups to keep, Used for the "purge" command.  
# see duplicity man page, chapter TIME_FORMATS)
# defaults to 1M, if not set
MAX_AGE=3M
 
# Number of full backups to keep. Used for the "purge-full" command. 
# See duplicity man page, action "remove-all-but-n-full".
# defaults to 1, if not set 
MAX_FULL_BACKUPS=2
 
# verbosity of output (error 0, warning 1-2, notice 3-4, info 5-8, debug 9)
# default is 4, if not set
VERBOSITY=5
 
# activates duplicity --full-if-older-than option (since duplicity v0.4.4.RC3) 
# forces a full backup if last full backup reaches a specified age, for the 
# format of MAX_FULLBKP_AGE see duplicity man page, chapter TIME_FORMATS
# Uncomment the following two lines to enable this setting.
MAX_FULLBKP_AGE=1M
DUPL_PARAMS="$DUPL_PARAMS --full-if-older-than $MAX_FULLBKP_AGE "
 
# sets duplicity --volsize option (available since v0.4.3.RC7)
# set the size of backup chunks to VOLSIZE MB instead of the default 25MB.
# VOLSIZE must be number of MB's to set the volume size to.
# Uncomment the following two lines to enable this setting. 
VOLSIZE=256
DUPL_PARAMS="$DUPL_PARAMS --volsize $VOLSIZE "

Damit aber nicht das gesamte System gesichert wird wie oben unter SOURCE=’/‘ definiert, muss eine exclude Datei definiert werden. Diese liegt neben der conf Datei und sieht bei mir wie folgt aus:

/bin
/cdrom
/lib
/lib64
/media
/selinux
/sys
/usr
/boot
/dev
/lib32
/lost+found
/mnt
/sbin
/tmp
/var/archives
/var/cache
/proc

Damit habe ich alles fuer mich wichtige wie /etc, /home oder auch /var/www gesichert.

MySQL Dump vor Backup erstellen

duply bietet weiter die Moeglichkeit vor und nach dem Backup Kommandos auszufuehren. Dafuer muss neben der conf Datei eine oder auch die beiden Dateien pre und/oder post liegen. Dies sind Skripte die ausgefuehrt werden, es ist wichtig dass sie das auch sind (chmod ug+x pre). Ich erzeuge vor dem Backup damit einen Dump der Datenbanken auf dem Server. Das Skript sieht wie folgt aus:

#!/bin/bash
 
## create backup directory if not exist
if [ ! -d "/opt/backup" ]; then mkdir /opt/backup; fi
 
## delete old backup files older than 1 month
find /opt/backup -name "*.gz" -type f -mtime +31 -delete
 
## create dump of all databases
mysqldump --opt --routines --add-drop-database --default-character-set=utf8 --create-options --events --all-databases | gzip > /opt/backup/$(date -I)-all-databases.sql.gz

Das MySQL Zugangspasswort habe ich in der /root/.my.cnf abgespeichert:

[client]
password=B1-r6UF9s:Mb<%

Es befinden sich nun die folgenden drei Dateien unter /etc/duply/HOSTNAME/:

host:/etc/duply/HOSTNAME# ll
insgesamt 16
-rw------- 1 root root 4633  1. Sep 17:20 conf
-rw-r--r-- 1 root root  168  7. Aug 21:26 exclude
-rwxr-x--- 1 root root  415  1. Sep 17:30 pre
host:/etc/duply/HOSTNAME#

cron Eintrag anlegen

Damit jede Nacht das Backup ausgefuehrt und gegebenfalls alte Backupsets geloescht werden, habe ich die Datei /etc/cron.daily/duply_HOSTNAME erstellt:

#
# nightly duply backup of profile "HOSTNAME"
#

5 4 * * * root /usr/bin/duply HOSTNAME backup_verify_purge --force

weitere duply Befehle

Die folenden Befehle finde ich wichtig:

  • Status des Backups:
    duply HOSTNAME status
  • Datei aus dem Backup wiederherstellen:
    duply HOSTNAME fetch /path/to/my/file /tmp/restore
  • Datei von vor einer Woche aus dem Backup wiederherstellen:
    duply HOSTNAME fetch /path/to/my/file /tmp/restore 7D
  • Alle Dateien im Backup auflisten von vor zwei Wochen die passwd enthalten:
    duply HOSTNAME list 2W | grep passwd

Monitoring mit Nagios

Wenn man nun ueber eine Nagios Installation verfuegt, moechte ich an dieser Stelle noch auf zwei Checks hinweisen. Der erste ist check_duply um zu pruefen, ob das Backup auch wie gewuenscht durchgelaufen ist. Bei einer Pruefung ueber NRPE kann der Eintrag wie folgt aussehen:

command[check_backup]=sudo /usr/lib/nagios/plugins/check_duply -P HOSTNAME -w 36 -W 32 -c 48 -C 36

Die Parameter bedeuten:

  -w WARNINC   Number of hours allowed for incremental backup warning level
  -W WARNFULL  Number of days allowed for full backup warning level
  -c CRITINC   Number of hours allowed for incremental backup critical level
  -C CRITFULL  Number of days allowed for full backup critical level
  -P PROFILE   duply profile name

Der zweite Check ist check_ftpspace um zu ueberwachen, dass der FTP Speicher nicht volllaeuft. Wenn der Check ebenfalls ueber NRPE ausgefuehrt wird ist das hier ein beispielhafter Eintrag:

command[check_backupspace]=/usr/lib/nagios/plugins/check_ftpspace ftp://u12345.your-backup.de u12345 abc123def456ghj7 7000 15000 100000

Die Reihenfolge der Parameter setzt sich wie folgt zusammen:

HOSTNAME USER PASS WARN CRIT TOTAL

wobei die Werte fuer WARN CRIT und TOTAL jeweils MB sind.

Am Ende sei noch darauf hingewiesen, dass ich mir das nicht alles selber aus den Fingern gesaugt habe, sondern mich bei den folgenden Quellen bedient habe:

Vorherige Blogposts:

  • Der erste Teil war fuer mich das Aufraeumen, einen Ueberblick zu bekommen sowie Strukturen zu schaffen, auf denen ich aufbauen kann.
  • Der zweite Teil bestand darin einen Ort zu schaffen, in dem ich Keys und Passwoerter sicher aufbewahren und gleichzeitig alles in ein vernuenftiges Backup schieben kann.
  • Der dritte Teil bezog sich auf das erzeugen von Zertifikaten und Einrichten von verschluesselten Verbindungen zu Apache vHosts.
  • Der vierte Teil drehte sich um das Thema Komfort im Webbrowser und verwies in dem Kontext auf einen Artikel zum selbst gehosteten Firefox Sync Server.
  • Im fuenften Teil habe ich etwas zu meinen Ueberlegungen zu sicheren Zugangsdaten und Passwoertern geschrieben.
  • Im sechsten Teil dreht es sich darum, wie man sich auf seinen Servern mit SSH aber ohne Passwort sicher authentifizieren kann.

Eigene Debian Pakete erstellen – preinst und postinst

Vor kurzem habe ich darueber geschrieben wie man eigene Debian-Pakete und ein eigenes Repository dafuer erstellt. Ich moechte nun hinzufuegen, wie man Skripte vor- und nach der Installation ausfuehrt. Basis ist hier das Debian-Paket fuer das pregoBackup.sh Skript was in dem verlinkten Post steht.

Um Skripte vor und nach der Installation auszufuehren werden die beiden Dateien

./DEBIAN/preinst
./DEBIAN/postinst

benoetigt. Dieses koennen einfach Bash-Skripte sein, die dann bei der Installation aufgerufen werden. Nehmen wir an, ich moechte vor der Installation eine 100MB grosse Datei erstellen, und nach der erfolgreichen Installation des Paketes diese Datei wieder loeschen, koennten die beiden Skripte z.B. wie folgt aussehen:

preinst:

    #!/bin/bash
    echo "creating 100mb file..."
    dd if=/dev/zero of=/tmp/100megsofzero bs=1024 count=100000

    postinst:

      #!/bin/bash
      echo "deleting 100mb file..."
      rm -f /tmp/100megsofzero

      Paket erzeugen und ausprobieren…

      Eigene Debian-Pakete und Repository erstellen

      Sobald als man Admin mehrere Server zu administrieren hat, kommt man in den Genuss ein- und das dasselbe auf viele Servern immer wieder machen zu muessen. Heute moechte ich mich dem Thema widmen auf vielen Servern z.B. eine neue Version des Backupskriptes einzuspielen. Dafuer brauche ich zwei Dinge

      1. ein Debian Paket mit meinem Skript
      2. ein Debian Repository ueber das das Paket verteilt wird

      Der hier im folgenden vorgestellte Weg ist sehr simpel und rudimentaer gehalten und behandelt explizit Dinge wie SecureApt nicht.

      Erstellen eines eigenen Debian-Paketes

      Zum Erstellen des eigenen Debian Paketes benoetige ich nun zwei Dinge. Einmal mein Backupskript pregoBackup.sh und einmal eine control-Datei, die Informationen ueber das Debian Paket enthaelt. Die control Datei koennte z.B. wie folgt aussehen:

      Package: pregoBackup
      Version: 0.5
      Section: server
      Priority: optional
      Architecture: all
      Essential: no
      Installed-size: 1024
      Maintainer: prego presto
      Description: pregos Backup Skript zum Sichern des Servers

      Das ganze vorgehen jetzt in Worte zu fassen waere sehr umstaendlich. Deswegen in kurz: die control Datei liegt in dem Unterordner ./DEBIAN und neben das DEBIAN Verzeichnis packe ich das Skript an die Stelle, wo ich es im Dateisystem liegen haben moechte:

      cd /tmp
      mkdir pregoBackup
      cd pregoBackup
      mkdir ./DEBIAN
      mkdir -p ./root/skripte
      cp control ./DEBIAN
      cp pregoBackup.sh ./root/skripte

      Als naechstes wird das Debian-Paket erstellt:

      cd /tmp
      dpkg-deb --build pregoBackup

      Danach sollten wir die Datei /tmp/pregoBackup.deb haben. Was darin enthalten ist koennen wir uns mit:

      dpkg-deb --contents pregoBackup.deb

      anzeigen lassen, und wer moechte kann es auch spasseshalber mal mit

      dpkg -i pregoBackup.deb
      aptitude show pregoBackup
      aptitude purge pregoBackup

      installieren, angucken und deinstallieren.

      Anlegen eines Debian Repositories

      An zweiter Stelle lege ich nun ein Repository an. Dafuer erstelle ich zuerst eine Verzeichnisstruktur dafuer:

      mkdir -p /srv/myrepository/{binary,source}

      Anschliessend lege ich einen simplen Apache vhost an mit einer Zugangsbeschraenkung fuer das Repository auf mein lokales Netz:

          ServerAdmin webmaster@example.net
          ServerName myrepository.example.net
          DocumentRoot /srv/myrepository/
       
                      AllowOverride None
                      Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
                      Order Deny,Allow
                      Deny from all
                      Allow from 192.168.0.0/255.255.0.0

      Nun kann ich mein frisch erstelltes Debian-Paket in die Repository Dateisystemstruktur kopieren:

      cp /tmp/pregoBackup.deb /srv/myrepository/binary/

      Zu guter letzt muss noch der Repository Index erstellt werden. Dafuer muss das Paket dpkg-dev vorhanden sein:

      aptitude install dpkg-dev
      cd /srv/myrepository
      dpkg-scanpackages binary /dev/null | gzip -9c > binary/Packages.gz
      dpkg-scansources source /dev/null | gzip -9c > source/Sources.gz

      Wenn das alles fertig ist, brauche ich nur noch auf meinem Server die entsprechenden Zeilen in die /etc/apt/sources.conf eintragen, die Liste der verfuegbaren Pakete von den apt-Quellen erneuern und dann kann das Paket installiert werden.

      ## my personal repository
      deb http://myrepository.example.net binary/
      deb-src http://myrepository.example.net source/
      aptitude update
      aptitude install pregoBackup