Verschlüsselte Remote-Dateisysteme

Zum Jah­res­an­fang ein klein wenig Ad­min-Fu... ge­le­gent­lich kommt man in die Ver­le­gen­heit, auf einem ent­fern­ten Rech­ner Daten ab­le­gen zu wol­len, die vom je­wei­li­gen Admin nicht les­bar sein sol­len (bei­spiels­wei­se weil man die­sem nicht hin­rei­chend ver­traut). An­stoß für meine Über­le­gun­gen war die Not­wen­dig­keit, ein Back­up übers Netz zu ma­chen, wobei die Daten auf dem ent­fern­ten Rech­ner nicht les­bar (sprich: ver­schlüs­selt ab­ge­legt) sein soll­ten.
Da es sich hier­bei nur um ein "Re­ser­ve­back­up" han­deln soll­te, hätte ei­gent­lich eine ein­fa­che Kopie der Da­tei­en (ohne eine Back­up-His­to­ry) ge­nügt - daher ging mein ers­ter Ge­dan­ke in Rich­tung eines ver­schlüs­sel­ten Da­tei­sys­tems. Gleich vor­ne­weg: Der Ge­dan­ke stell­te sich als Irr­weg her­aus - wes­halb er­klä­re ich im Ab­schnitt über die nun ein­ge­setz­te Al­ter­na­ti­ve, näm­lich du­pli­ci­ty. Trotz­dem möch­te ich die be­nö­tig­ten Schrit­te zur Ein­rich­tung hier kurz do­ku­men­tie­ren.

Ein­rich­ten ssh

Als Basis für den si­che­ren Zu­griff auf den ent­fern­ten Rech­ner habe ich ssh ge­wählt. Mit Au­then­ti­sie­rung über Pu­blic-Pri­va­te-Key­paa­re läßt sich der Zu­griff auch schön au­to­ma­ti­sie­ren - ent­we­der indem man den Pri­va­te Key auf dem zu si­chern­den Sys­tem un­ver­schlüs­selt hin­ter­legt oder durch Spei­chern des zu­ge­hö­ri­gen Pass­phra­ses in einer Key­a­gent-In­stanz, die dann na­tür­lich nach einem Sys­tem­start ma­nu­ell neu ein­zu­ge­ben ist.
Der Zu­griff auf das Ziel­sys­tem soll­te je­doch so ein­ge­schränkt sein, daß der In­ha­ber des Back­up-Ac­counts zwar Daten si­chern, aber keine in­ter­ak­ti­ve Shell öff­nen kann. Glück­li­cher­wei­se läßt sich dies in­zwi­schen bei opens­sh recht kom­for­ta­bel kon­fi­gu­rie­ren.
Da ich die Da­ten­ab­la­ge für meh­re­re Rech­ner nut­zen möch­te, habe ich die Kon­fi­gu­ra­ti­on gleich ent­spre­chend ge­ne­risch ge­macht. Jeder Back­up-Ac­count wird Mit­glied der Grup­pe re­mo­te­bak, die zu­ge­hö­ri­gen Back­up-Ver­zeich­nis­se lie­gen in in /var/back­ups/re­mo­te/user­na­me.
In ssh­d_­con­fig des Ziel­sys­tems wird mit fol­gen­der Kon­fi­gu­ra­ti­on nur der Zu­griff via sftp auf das ei­ge­ne Da­ten­ver­zeich­nis er­laubt, wenn der Be­nut­zer Mit­glied der Grup­pe re­mo­te­bak ist:

Match Group re­mo­te­bak
        Chroot­Di­rec­to­ry /var/back­ups/re­mo­te/%u
        Force­Com­mand in­ter­nal-sftp
        Al­lowTcpFor­war­ding no
        X11­For­war­ding no

Für mei­nen ers­ten Ser­ver habe ich einen User ser­ver1 an­ge­legt, ihn der Grup­pe re­mo­te­bak zu­ge­wie­sen und für ihn ein Ver­zeich­nis /var/back­ups/re­mo­te/ser­ver1 an­ge­legt. Die­ses Ver­zeich­nis muß dem Be­nut­zer root ge­hö­ren, sonst ver­wei­gert sich opens­sh an beim chroot-Kom­man­do. In das Ver­zeich­nis habe ich (eben­falls als root, so daß der Be­nut­zer keine Än­de­run­gen vor­neh­men kann) ein Ver­zeich­nis .ssh und darin eine Datei aut­ho­ri­ze­d_keys für die Schlüs­sel­au­then­ti­sie­rung an­ge­legt. Zu guter letzt bekam das Ver­zeich­nis noch einen Un­ter­ord­ner data, wel­cher nun dem User ser­ver1 ge­hört - hier­in hat er nun Schreib­rech­te.

Moun­ten als ver­schlüs­sel­tes Da­tei­sys­tem

Mein ers­ter Ver­such war, das Ver­zeich­nis mit ecryptfs zu ver­schüs­seln; dazu mußte ich es zu­nächst lokal zur Ver­fü­gung stel­len, um an­schlie­ßend mit ecryptfs ein ver­schlüssl­tes Un­ter­ver­zeich­nis an­zu­le­gen.

Ver­bin­dung via sshfs

Am ein­fachs­ten er­folgt eine sol­che Ein­bin­dung via sshfs. Als Vor­be­rei­tung für das Moun­ten habe ich die ssh-Kon­fi­gu­ra­ti­on in der .ssh/con­fig zu­sam­men­ge­schrie­ben:

Host mein.​backup.​server
User ser­ver1
Iden­ti­ty­Fi­le /root/.ssh/id_d­sa-back­up

Das Moun­ten auf den Mount­point /mnt/re­mo­te­back­up er­folgt nun mit dem Be­fehl
sshfs mein.​backup.​server: /mnt/re­mo­te­back­up -C -o uid=0 -o gid=0

Ver­schlüs­se­lungs­over­lay mit ecryptfs

Nun be­steht zwar eine ver­schlüs­sel­te Ver­bin­dung zwi­schen Cli­ent und Ser­ver, je­doch wer­den die Daten auf dem Ser­ver un­ver­schlüs­selt ab­ge­legt. Ab­hil­fe kann ecr­pytfs schaf­fen, wel­ches ein ver­schlüs­sel­tes Over­lay über ein vor­han­de­nes Da­tei­sys­tem legt. Die Ein­rich­tung ge­schieht beim ers­ten Moun­ten:

mount -t ecryptfs /mnt/re­mo­te­back­up/data /mnt/re­mo­te­back­up/data
Pass­phra­se: (pass­wort ein­ge­ben)
Select ci­pher:
 1) aes: block­si­ze = 16; min key­si­ze = 16; max key­si­ze = 32 (not loa­ded)
 2) blo­w­fish: block­si­ze = 16; min key­si­ze = 16; max key­si­ze = 56 (not loa­ded)
 3) de­s­3_e­de: block­si­ze = 8; min key­si­ze = 24; max key­si­ze = 24 (not loa­ded)
 4) two­fish: block­si­ze = 16; min key­si­ze = 16; max key­si­ze = 32 (not loa­ded)
 5) cast6: block­si­ze = 16; min key­si­ze = 16; max key­si­ze = 32 (not loa­ded)
 6) cast5: block­si­ze = 8; min key­si­ze = 5; max key­si­ze = 16 (not loa­ded)
Selec­tion [aes]:
Select key bytes:
 1) 16
 2) 32
 3) 24
Selec­tion [16]:
Enable plain­text passth­rough (y/n) [n]:
Enable file­na­me en­cryp­ti­on (y/n) [n]:
At­temp­t­ing to mount with the fol­lo­wing op­ti­ons:
  ecryptfs_un­lin­k_­sigs
  ecryptfs_key­_­bytes=16
  ecryptfs_ci­pher=aes
  ecryptfs_­sig=hashwert
WARNING: Based on the con­tents of [/root/.ecryptfs/sig-cache.​txt],
it looks like you have never moun­ted with this key
be­fo­re. This could mean that you have typed your
pass­phra­se wrong.
Would you like to pro­ceed with the mount (yes/no)? : yes
Would you like to ap­pend sig [hashwert] to
[/root/.ecryptfs/sig-cache.​txt]
in order to avoid this warning in the fu­ture (yes/no)? : yes
Suc­cess­ful­ly ap­pen­ded new sig to user sig cache file
Moun­ted eCryptfs

Ich habe je­weils die Stan­dard­ein­stel­lun­gen ver­wen­det. Um diese Fra­gen nicht je­des­mal neu ein­ge­ben zu müs­sen, kann man die Pa­ra­me­ter in der Datei ~/.ecryptfs­rc spei­chern. Wich­tig ist hier­bei den an­ge­ge­be­nen Hashwert zu über­neh­men. Au­ßer­dem be­steht hier die Mög­lich­keit, die Quel­le für das Pass­wort aus einer Datei zu beh­zie­hen. Letz­te­re kann bei­spiels­wei­se auf einem USB-Stick ge­spei­chert sein, in mei­nem Fall ging es ja nur darum, die Da­tei­en auf dem Ziel­sys­tem un­les­bar zu ma­chen, wes­halb ich den Schlüs­sel mit auf dem Rech­ner ab­leg­te.
key=pass­phra­se:pass­phra­se_passw­d_­file=/root/.ecryptfs-back­up
ecryptfs_­sig=hashwert
ecryptfs_ci­pher=aes
ecryptfs_key­_­bytes=16
ecryptfs_passth­rough=n
ecryptfs_enable_­file­na­me_­cryp­to=n

Die er­wähn­te Schlüs­sel­da­tei .ecryptfs-back­up sieht fol­gen­der­ma­ßen aus:

pass­phra­se_passwd=(pass­wort)

Back­up mit du­pli­ci­ty

Das Pro­ce­de­re stell­te sich lei­der für ein Back­up mit rsync als un­ge­eig­net her­aus: Nor­ma­ler­wei­se ver­wen­det rsync für den Da­tei­ab­gleich über das Netz ein Ver­fah­ren, wel­ches die Dif­fe­ren­zen zwi­schen den Da­tei­en fest­stellt (und an­schlie­ßend nur diese über­trägt). Dafür wird auf der Ge­gen­sei­te eben­falls ein rsync-Pro­zeß ge­star­tet, die bei­den Pro­gramm­in­stan­zen han­deln dann die zu über­tra­gen­den Daten aus. In die­sem Fall ist das Back­up-Ziel aber ein (ver­meint­lich lo­ka­les) Da­tei­sys­tem; das be­deu­tet, daß rsync für die Suche nach ver­än­der­ten Da­tei­en sämt­li­che Daten vom ent­fern­ten Rech­ner lesen muß, was eine Über­tra­gung über das Netz plus den Over­head durch die Ent­schlüs­se­lung be­deu­tet. Dazu kommt noch, daß ei­ni­ge At­tri­bu­te wie Owner oder Zeits­tem­pel nicht ohne wei­te­res ab­ge­gli­chen wer­den kön­nen. Für meine Back­up­zwe­cke war das Vor­ge­hen also un­ge­eig­net; für an­de­re Ein­satz­zwe­cke ("er­wei­ter­tes Home­di­rec­to­ry" auf einem ent­fern­ten Ser­ver, Ver­schlüs­se­lung der ei­ge­nen Daten in der Drop­box) taugt der An­satz je­doch si­cher­lich.
Letzt­lich habe ich für das Back­up doch wie­der auf du­pli­ci­ty zu­rück­ge­grif­fen. Du­pli­ci­ty ver­schlüs­selt das Back­up mit gpg; in­tern nutzt Du­pli­ci­ty die Bi­blio­the­ken von rdiff, je­doch ohne eine in­ter­ak­ti­ve Ge­gen­stel­le zu be­nö­ti­gen. Man er­hält so eine voll­stän­di­ge ver­schlüs­sel­te Back­u­plö­sung mit in­kre­men­ti­el­len Back­ups. Ei­gent­lich woll­te ich auf den Platz­ver­brauch durch die In­kre­ments ver­zich­ten... nun habe ich ein Skript am Start, wel­ches per Cron-Job nächt­lich läuft und alle drei Mo­na­te ein neues Voll­back­up er­stellt:

RE­MO­TE_­DEST="scp://​server1@​mein.​backup.​server/data"
RE­MO­TE_­OP­TI­ONS='--en­crypt-key=0xerster­schlüs­sel --en­crypt-key=0x­zwei­ter­schlüs­sel --ssh-op­ti­ons="-oIden­ti­ty­Fi­le=/root/.ssh/id_d­sa-back­up"'

for dir in /etc /home /root ; do
        DEST­DIR=`echo $dir | sed "s/^\///;s/\/$//;s/\//_/g"'
        LOG­FI­LE="/var/log/du­pli­ci­ty/${DEST­DIR}.log"
        (
                echo "++++++++++++++++++++++++++++++++++++++++"
                date
                echo "++++++++++++++++++++++++++++++++++++++++"
                du­pli­ci­ty --full-if-ol­der-than=3M $RE­MO­TE_­OP­TI­ONS $dir ${RE­MO­TE_­DEST}/${DEST­DIR}
                du­pli­ci­ty re­mo­ve-ol­der-than 4M --force $RE­MO­TE_­OP­TI­ONS ${RE­MO­TE_­DEST}/${DEST­DIR}
                echo
                echo
        ) 2>&1 | tee $LOG­FI­LE
done

Ge­si­chert wer­den die Ver­zeich­nis­se der for-Schlei­fe (etc, home und root); ver­schlüs­selt wird das Back­up ex­em­pla­risch für zwei gpg-Schlüs­sel, deren Key-IDs in der Va­ria­ble RE­MO­TE_­OP­TI­ONS an­ge­ge­ben wer­den.

So­viel zu den Re­cher­che-Er­geb­nis­sen des Tages zum Thema ver­schlüs­sel­te Daten auf ent­fern­ten Sys­te­men, ohne dort das Schlüs­sel­ma­te­ri­al de­po­nie­ren zu müs­sen :-) In einem wei­te­ren Ar­ti­kel wird be­schrie­ben, wie man den Da­ten­ab­la­ge-Ser­ver wei­ter ab­si­chern kann (und soll­te), um die­sen im Fall eines Sys­tem­ein­bruchs nicht mit­zu­ge­fähr­den.