Verschlüsseltes NAS selber aufsetzen (Ubuntu, LUKS, ZFS, RAID)

Festplatte Unser File-Server ist an seine Grenzen gestoßen und wir mussten uns auf die Suche nach einer neuen Lösung machen. Klar war: es muss ein NAS werden, das verschlüsselt ist. Doch der Markt gab nix Passendes oder Bezahlbares her. Deswegen haben wir uns für die Do-It-Yourself-Version entschieden: ein Ubuntu-NAS mit LUKS-Verschlüsselung, ZFS-Dateisystem und RAIDZ. Nachfolgend will ich Euch erklären, wie man das aufsetzt. Folgende Features waren für uns beim Bau des NAS wichtig:
  • Stromsparend
  • Windows-Freigabe möglich
  • Voll verschlüsselt
  • Ausfallsicher
  • Performance
  • Einfache Pflege
  • Linux basiert (kein Solaris/BSD)
  • Erweiterbarkeit (Webserver, VPN, etc)
Wir haben uns daher für folgendes Setup entschieden:
  • Betriebssystem: ubuntu-server-12.10
  • Dateisystem: zfs
  • RAID: RAIDZ
  • Freigabe: Samba
  • Verschlüsselung: ecryptfs oder LUKS
Die Hardware sollte möglichst stromsparend und kostengünstig sein, da wir keine High-Performance Lösung benötigen. Sprich 1Gbit LAN zu 100% auslasten wäre zwar schön, ist aber nicht unbedingt nötig, 80% reichen auch ;-)

Hardware: Asus Mini ITX

  • 1 MBP ASUS E35M1-I – Mini-ITX
  • 1 2.5" OCZ 60GB Vertex 3 Series
  • 1 GEH Sharkoon Rebel 9 Pro Economy schwarz o.NT
  • 1 SPE 8GB CORSAIR CL9 Vengeance CMZ8GX3M2A1600C
  • 2 HI3 3.5" WD 2000GB Caviar Green WD20EARX 6GB/
  • 2 HI3 3.5" SEAGATE 2000GB Barracuda Green ST200
  • 1 NEZ 400W Seasonic X-Fanless X-400FL 80plus Go
Gesamtpreis: 905,91 € (Stand Anfang 2012) Immer daran denken: Ein ZetaFileSystem (ZFS) ist speicherhungrig.

Betriebssystem: OpenSolaris vs. BSD vs. Ubuntu

Hier haben wir es uns einfach gemacht und das System gewählt mit dem sich alle (hier) am besten auskennen. Sonst wäre sicherlich OpenSolaris oder BSD wegen des ZFS Supports die bessere Wahl gewesen. Die Entscheidung für ubuntu-server-12.10 lag hauptsächlich daran, das ab der Version 12.10 die LVM Verschlüsselung wieder mit im Installer ist und man nicht mehr alles per Hand machen muss, aber ältere Versionen und das aktuelle LTS gehen natürlich auch. Später bin ich auch über ein paar Probleme gestolpert, die 12.10 spezifisch sind. Doch dazu später mehr. Installiert wird das System auf eine 60GB SSD.

Dateisystem: ZFS

Die Entscheidung zugunsten von ZFS war eigentlich von vornherein klar. Ein Hardware RAID schied aus, da es bei Controller-Fehlern zu Dateiverlust kommen kann und Write Hole Probleme vorhanden sind. ZFS vereinigt einen Logical Volume Manager und ein Software RAID und kann dabei noch viel mehr. Doch der Artikel soll sich aber nicht um ZFS an sich drehen, sondern ist an die gerichtet die schon von ZFS überzeugt sind und es einsetzen möchten. Alle die nicht wissen was ZFS ist und was es kann empfehle ich diesen Podcast: http://cre.fm/cre049

Installation

Zunächst müssen wir sicher stellen, das de Befehl add-apt-repository vorhanden ist. sudo apt-get install python-software-properties Für 12.10 reicht dies aber nicht (zum Bugreport). Deswegen muss noch Folgendes installiert werden sudo apt-get install software-properties-common Jetzt können wir ZFS installieren. Wir entscheiden uns hier für das Kernelmodul und nicht die FUSE-Variante, da das Kernelmodul performanter ist. Server vorbereiten: sudo apt-get -y -q update && sudo apt-get -y -q upgrade Benötigte Programme installieren: sudo apt-get -y install build-essential gawk zlib1g-dev uuid-dev vim-nox Das PPA hinzufügen: sudo add-apt-repository ppa:zfs-native/stable und ZFS installieren: sudo apt-get install ubuntu-zfs Zum Zeitpunkt dieses Artikel gab es noch kein Release für 12.10 also müsste ich die Sourcen manuell hinzufügen: sudo nano /etc/apt/sources.list --- deb ppa.launchpad.net/zfs-native/stable/ubuntu precise main deb-src ppa.launchpad.net/zfs-native/stable/ubuntu precise main Danach noch ein Update: sudo apt-get -y -q update und es kann installiert werden: sudo apt-get install ubuntu-zfs Jetzt müssen noch die nötigen Module aktiviert werden sudo nano /etc/modules --- spl zavl znvpair zunicode zcommon zfs und intramfs aktualisieren: sudo update-initramfs -u Nach dem Neustart sollte ZFS zur Verfügung stehen.

Verschlüsselung mit LUKS

Bei LUKS wird die Verschlüsselung „unterhalb“ von ZFS gemacht und nicht wir bei ecryptfs (siehe unten) auf ZFS. Dazu muss zunächst LUKS installiert werden. sudo apt-get install cryptsetup dann sollte auf jeder Platte eine leere Partition angelegt werden: sudo fdisk /dev/sdaX Befehl (m für Hilfe): n Partition type: p primary (1 primary, 0 extended, 3 free) e extended Select (default p): Using default response p Partitionsnummer (1-4, Vorgabe: 2): Benutze den Standardwert 2 Es sind keine freien Sektoren verfügbar Befehl (m für Hilfe): w Jetzt wird der LUKS-Container für jede Festplatte angelegt: sudo cryptsetup --verify-passphrase luksFormat /dev/sdX1 -c aes -s 256 -h sha256 Danach werden alle Container geöffnet: sudo cryptsetup luksOpen /dev/sdX1 encryptedX Um die Platten nach den Neustart automatisch gemountet werden muss die /etc/crypttab angepasst werden: encrypted1 UUID=e8795884-1549-41f2-9aad-705d66716678 none luks Die UUID der jeweiligen Partition findet man folgendermaßen heraus: sudo blkid /dev/sdX1 Jetzt kann das ZRAID erstellt werden: sudo zpool create storage raidz /dev/mapper/encrypted1 /dev/mapper/encrypted2 /dev/mapper/encrypted3 /dev/mapper/encrypted4 In Storage können wir jetzt verschiedene Dateisysteme erstellen. Wir erstellen mal ein einfaches share sudo zfs create storage/share Jetzt erstellen wir noch einen Mountpoint für share: sudo mkdir /media/share Dieser muss noch in ZFS gesetzt werden: zfs set mountpoint=/media/share storage/share Sollte hier share nach dem Neustart nicht gemountet werden könnte es sich um dieses Problem handeln (ich hatte das zumindest.) Meistens reicht ein Versionswechsel von mountall: sudo apt-get install mountall=2.36.1-zfs1 Sollte es dann immer noch nicht gehen, mal folgendes Problem prüfen. ZFS versucht die mapper zu mounten, die aber zu diesem Zeitpunkt noch nicht existieren. Dies konnte ich mit folgen den Änderungen beheben: /etc/default/zfs: ZFS_MOUNT='yes'

Schlüssel Authentifizierung

Beim Neustarten muss jetzt jedes mal für jede Festplatte das LUKS Password eingegeben werden. Das ist nervig (ein ZRAID kann auch aus 20+ Platten bestehen ). Es ist daher sinnvoll einen Schlüssel auf der verschlüsselten Systemplatte zu hinterlegen, mit dem sich die RAID Platten öffnen lassen. Eine weitere Lösung ist es, diesen Schlüssel für alle Platten auf einen USB-Stick zu legen, dann lässt sich das System nur hochfahren und die Platten öffnen wenn der USB-Stick mit dem Schlüssel „eingesteckt“ ist. Ich bevorzuge jedoch Lösung eins, weil ich sie für sicherer halte. Und dies geht so. Erstellen des Schlüssels: sudo dd if=/dev/urandom of=/root/.key/key bs=512 seek=1 count=60 sudo chmod 0400 /root/.key/key Jetzt muss ich LUKS noch mitteilen, das die Platten sich auch durch diesen Schlüssel öffnen lassen (für jede Platte): sudo cryptsetup luksAddKey /dev/sdX1 /root/.key/key Es ist zu beachten, das sich die Platten bei Verlust der Schlüsseldatei auch noch durch das Passwort öffnen lassen. Ferner lassen sich nur die RAID Platten mit dem Schlüssel öffnen, nicht die Systemplatte. Dadurch kann System nicht in Betrieb genommen werden von jemanden, der die Schlüsseldatei gestohlen hat, es muss ebenfalls das Passwort bekannt sein. Damit die Schlüsseldatei auch beim Booten berücksichtigt wird, muss die /etc/crypttab angepasst werden (für jede Platte): encryptedX UUID=9e1923b6-97c7-4769-8139-18ecf2c7ebf7 /root/.key/key luks

Alternative zu LUKS: Verschlüsselung mit ecryptfs

Achtung: ecryptfs unterstützt nur 255 lange Dateinamen (https://bugs.launchpad.net/ecryptfs/+bug/344878) sollte das ein Problem sein empfiehlt es sich die LUKS Variante zu benutzen, siehe weiter unten. Bei ecrypfs ist es notwendig, das wir zunächst die Festplatten mit ZFS einrichten und dann erst die Verschlüsselung aktivieren. Ich erstelle ein RAIDZ Pool über 4 Festplatten mit dem Namen storage: sudo zpool create storage raidz /dev/sda /dev/sdb /dev/sdc /dev/sde In Storage können wir jetzt verschiedene Dateisysteme erstellen. Wir erstellen mal ein einfaches share sudo zfs create storage/share Jetzt erstellen wir noch einen Mountpoint für share: sudo mkdir /media/shareSollen share nach dem Neustart nicht gemountet werden könnte es sich um dieses Problem handeln (ich hatte das zumindest.) Meistens reicht ein Versionswechsel von mountall sudo apt-get install mountall=2.36.1-zfs1 Jetzt müssen wir ecryptfs installieren. sudo apt-get install ecryptfs-utils Jetzt wollen wir share verschlüsselt mounten. Dabei ist zu beachten, das share schon unter /storage/share unverschlüsselt gemountet ist. sudo mkdir /media/share sudo mount -t ecryptfs /storage/share /media/share Das ganze mit mit Enter bestätigen. Ich hab aber zusätzlich noch die filename encryption aktiviert: Passphrase: Select cipher: 1) aes: blocksize = 16; min keysize = 16; max keysize = 32 2) blowfish: blocksize = 8; min keysize = 16; max keysize = 56 3) des3_ede: blocksize = 8; min keysize = 24; max keysize = 24 4) twofish: blocksize = 16; min keysize = 16; max keysize = 32 5) cast6: blocksize = 16; min keysize = 16; max keysize = 32 6) cast5: blocksize = 8; min keysize = 5; max keysize = 16 Selection [aes]: Select key bytes: 1) 16 2) 32 3) 24 Selection [16]: Enable plaintext passthrough (y/n) [n]: Enable filename encryption (y/n) [n]: y Jetzt können in /media/share Dateien gespeichert werden diese werden dann verschlüsselt. In /storage/share sieht man nun nur verschlüsselte Dateien.

Performance

Im Anschluss ein paar Daten was das System so kann (gemessen mit bonnie++ und dd):

Performance ohne Verschlüsselung

[caption id="attachment_1096" align="alignnone" width="413"]ZFS Benchmark ohne Verschlüsselung ZFS Benchmark ohne Verschlüsselung[/caption] Schreiben: dd if=/dev/zero of=tempfile bs=1G count=1 oflag=dsync 1+0 Datensätze ein 1+0 Datensätze aus 1073741824 Bytes (1,1 GB) kopiert, 13,796 s, 77,8 MB/s

Performance mit Verschlüsselung

ecryptfs [caption id="attachment_1095" align="alignnone" width="413"]ZFS Bechchmark mit encryptfs ZFS Bechchmark mit encryptfs[/caption] Schreiben: dd if=/dev/zero of=tempfile bs=1G count=1 oflag=dsync 1+0 Datensätze ein 1+0 Datensätze aus 1073741824 Bytes (1,1 GB) kopiert, 40,5001 s, 26,5 MB/s Lesen: dd if=tempfile of=/dev/null 2097152+0 Datensätze ein 2097152+0 Datensätze aus 1073741824 Bytes (1,1 GB) kopiert, 3,29727 s, 36 MB/s LUKS [caption id="attachment_1094" align="alignnone" width="413"]ZFS Benchmark auf LUKS ZFS Benchmark auf LUKS[/caption] Schreiben: dd if=/dev/zero of=tempfile bs=1G count=1 oflag=dsync 1+0 Datensätze ein 1+0 Datensätze aus 1073741824 Bytes (1,1 GB) kopiert, 31,1532 s, 34,5 MB/s Lesen: dd if=tempfile of=/dev/null 2097152+0 Datensätze ein 2097152+0 Datensätze aus 1073741824 Bytes (1,1 GB) kopiert, 19,0477 s, 56,4 MB/s

Weiterführende Links:

Titelbild: Festplatte von Wikimedia

Kommentare

Danke, genau musste die Platte vorbereiten und dann hat alles super sauber funktioniert.

Das geht mit sudo zpool replace storage encrypted4.

Aber voer muss eine neue Platte vorbereitet werden und vorhanden sein. ZFS schnappt sich dann diese automatisch.

Hi,

du hast eine super Anleitung geschrieben.

Ich habe meinen Server vor ca. 2 Jahren nach der Anleitung aufgesetzt.

Und jetzt ist eine Platte von vier davon defekt. Und mein Pool ist degraded.

Wie kann ich mit einem verschlüsselten zpool die Platte ersetzen?

Gruß

Vitali

Hallo Samdo,

in der Tat habe ich dieses Setup noch vor ein paar Wochen genau so noch einmal aufgesetzt, allerdings mit ubuntu 14.04 und anderer Hardware.

Die Anleitung an sich kann aber immer noch eins zu eins übernommen werden. Ich würde allerdings nicht mehr encryptfs nehmen.

Zu Deiner zweiten Frage:

sdX1 hier steht das X für einen Buchstaben z.B. sba1, sbb1 etc.

encryptedX ist bei mir eine Nummer z.B. ecrypted1, Du kannst aber natürlich deine LUKS Container benennen wie du willst.

Um deinen Key auf einem USB-Stick abzulegen brauchst du ihn nur auf selbigen zu kopieren.

Dann musst Du cryptsetup aber noch mitteilen das er beim Hochfahren den Key auf dem USB-Stick suchen soll:

<a href="http://wiki.ubuntuusers.de/System_verschl%C3%BCsseln/Entschl%C3%BCsseln_mit_einem_USB-Schl%C3%BCssel" title="Entschlüsseln mit einem USB-Schlüssel" rel="nofollow"></a>

Hallo,

erst einmal vielen Dank für diese ausführliche Anleitung. Ich werde sie für mein NAS verwenden.

Drei Fragen habe ich dennoch:

1. Würdest Du auch heute noch nach dieser Anleitung vorgehen oder etwas ändern (erneuern) ?

2. Bei folgenden Zeilen kommt mir eine Frage:

"

Jetzt wird der LUKS-Container für jede Festplatte angelegt:

sudo cryptsetup --verify-passphrase luksFormat /dev/sdX1 -c aes -s 256 -h sha256

Danach werden alle Container geöffnet:

sudo cryptsetup luksOpen /dev/sdX1 encryptedX

"

und

"

Jetzt muss ich LUKS noch mitteilen, das die Platten sich auch durch diesen Schlüssel öffnen lassen (für jede Platte):

sudo cryptsetup luksAddKey /dev/sdX1 /root/.key/key

"

- muss ich hier das X von sdX1 durch den jeweiligen Buchstaben aller Daten-Platten ersetzen (nicht die OS SSD)? Also b bis e?

- was ist mit encryptedX - muss ich hier auch das X ersetzen?

3. Ich würde lieber den Schlüssel auf einen externen USB Stick auslagern. Muss ich dafür die folgende Zeile ändern und auf den USB Stick zeigen lassen (bei sdX1)? Wie muss diese dann aussehen?

"

Jetzt muss ich LUKS noch mitteilen, das die Platten sich auch durch diesen Schlüssel öffnen lassen (für jede Platte):

sudo cryptsetup luksAddKey /dev/sdX1 /root/.key/key

"

3b. Wie kann ich eine Sicherungskopie des USB Schlüssels anfertigen? Mittels DD oder reicht es, die "key" Datei auf einen anderen Stick zu kopieren?

Vielen Dank im Voraus für Deine Hilfe.

Liebe Grüße

Samdo

Das ist richtig. Die Schlüsseldatei enthält aber das Passwort für LUKS eh im Klartext. Wenn ich es mir recht überlege ist es besser den Schlüssel nicht nur mit Zahlen zu befüllen um broodforce zu erschweren:

<code>

tr -dc '0-9a-zA-Z' &lt;/dev/urandom | head -c 32 &gt; &lt;Schlüsseldatei&gt;

</code>

Allerdings kann /dev/random blockieren wenn nicht ausreichend Entopie vorhanden ist.

[&#8230;] [&#8230;]

Hi, die Anleitung hat mir viel geholfen, auch wenn ich wohl doch auf ein SW RAID5 gehe (spätere erweiterbarkeit um weitere Platten).

Eine Anmerkung zur Verschlüsselung:

Um (langlebige) Schlüssel zu erzeugen, sollte /dev/random und nicht /dev/urandom genutzt werden, da /dev/random nur Zufallszahlen ausgibt, wenn ausreichend Entropie vorhanden ist. Dadurch werden kryptografisch sicherere Keys erzeugt, bzw. die mit /dev/urandom erzeugten Keys sind potentiell schwach.

Quelle: http://manpages.ubuntu.com/manpages/jaunty/man4/random.4.html

Eben nicht. Da der Schlüssel von dem RAID ja auf der verschlüsselten Systemplatte liegt.

Die einzige Möglichkeit das RAID in Betrieb zu nehmen ist:

1. Man kennt das Password der Systemplatte

2. Man klaut im Betrieb den Schlüssel des RAID. Und nimmt dieses dann mit anderen Möglichkeiten (z.B. Live CD in Betrieb.)

Physikalischer Zugriff auf ein System ist immer unsicher.

Ferner lassen sich nur die RAID Platten mit dem Schlüssel öffnen, nicht die Systemplatte. Dadurch kann System nicht in Betrieb genommen werden von jemanden, der die Schlüsseldatei gestohlen hat, es muss ebenfalls das Passwort bekannt sein.

Schön und gut, dann kann derjenige halt die Systemplatte nicht decrypten, aber es hindert ihn auch niemand daran, einfach z.B. ein Live-Linux zu starten und nur die RAID-Platten einzuhängen. Dürften auch die interessanteren Daten drauf sein.

Also Keyfile immer sicher aufbewahren!

Hi. Did something similar with slightly other setup. ZFS on LUKS on ZRAID1-ZVOL. Got very good performance, which was not expected. My starting point, indeed, were all the setups similar to yours but I wanted to minimize encryption pipeline overhead (have only one luks device but a raidz of 6 disks).

Best regards

Ja die gibt es: Es geht nicht.

ZFS ist leider nur bis r28 Open Source. Die eingebaute Verschlüsselung ist aber erst ab r30 vorhanden. Um diese zu nutzen müsste man also Solaris kaufen. (Stand 2012)

Das ist halt leider das Problem, Oracle sein dank. Und da Oracle so eine tolle Open Source Mentalität hat (siehe Open Office) ist auch fraglich ob zukünftige Versionen überhaupt als Open Source herausgegebenen werden.

Alle Open Source Systeme benutzen andere Mechanismen (encfs, geli, LUKS) um ZFS zu verschlüsseln.

Ach ja FreeNAs 8.3.1 kann jetzt auch (wieder) ZFS Verschlüsselung (geli). Das wäre sich auch eine nette alternative wenn man mit FreeBSD gut kann.

Hallo, warum habt ihr nicht die bei zfs eingebaute verschlüsselung benutzt ? gibts es dafür gründe die dagegen sprechen?

Danke für das Lob.

Ist das NAS schon fertig? Würde mich über Erfahrungsberichte freuen. Besonders Hardwaresettings.

GELI Verschlüsselung war händisch auch schon vorher möglich. Ist es jetzt möglich dieses über das Webinterface zu konfigurieren?

LTS ist schon besser, aber da hätte ich die Systemplatten Verschlüsselung von Hand machen müssen. Na ja, vielleicht war ich da fault. Ich hagle mich bis 14.04 durch. ;-)

Im zur Zeit aktuellen FreeNAS 8.3.1 ist verschlüsselung (mit GELI - ähnlich LUKS) wieder drin.

Ansonsten gute anleitung. Aber ehrlich. Für einen Server würde ich IMMER LTS verwenden.

Vielen Dank. Ist genau das was ich brauche. Mein Router wurde erst vor kurzem mit openwrt ausgestattet. Jetzt wird ein Nas gebastelt. Verschlüsselungsoption ist das was ich gesucht habe.

Danke für das Lob, schön das Dir der Artikel gefallen hat.

So exotisch ist ZFS eigentlich gar nicht ;-)

Ach ja, wenn Du auf Verschlüsselung verzichten kannst, könntest Du Dir auch das mal <a href="http://www.freenas.org/" title="FreeNAS">FreeNas</a> anschauen.

Ich hatte das auch mal benutzt, aber mit der Version 8 ist die Verschlüsselung rausgefallen, benutzt aber auch ZFS.

wooow! Unglaublich Leute! Erst gestern habe ich mich auf die Suche nach einem neuen Dateisystem mit Dateiintegritätschecks gemacht und bin auf ZFS gestoßen. Jetzt lese ich diesen jungen SUPER Artikel! Klasse!

Das wird mir sehr helfen, da ich zu 90% das gleiche erreichen möchte wie ihr :) ZFS erscheint mir sehr "exotisch", aber die Features sind unvergleichbar.


Kommentar schreiben

* Diese Felder sind erforderlich