Minimalistisches NAS mit SSHFS

Vor ein paar Tagen habe ich Nextcloudpi auf meinem Raspberry 4B installiert. Das hat problemlos funktioniert, aber es hat mich beeindruckt, dass eine gefühlte Viertelstunde Software heruntergeladen und installiert wurde. Eigentlich wollte ich doch nur ein paar Dateien zentral halten.

Das hat mich bewogen, mich einmal im Netz umzuschauen, welche Alternativen es gibt. Ähnlich war die Installation von Openmediavault. Da wurde auch ziemlich viel Software nachgeladen und am Ende ging es aber auch nur darum, User und Speicher zu verwalten.

Mit OMV konnte ich zum Beispiel NFS-Shares bereitstellen, aber das kann ich doch auch so? Gesagt, getan. Aber NFS hat mich nicht überzeugt: Es hat erstmal keine Verschlüsselung. Wenn ja, wird es langsamer. Im Haus brauche ich das auch nicht, aber es wäre doch schön, wenn ich die gleiche Technologie, die ich zuhause nutze, auch einfach über das Internet nutzen könnte. Das geht so mit NFS nicht out-of.the-box und auch nicht mit Samba.

Zuletzt stieß ich auf sshfs, also ein Filesystem, was ssh als unterliegende Technik nutzt. Nach dem, was ich so las, sollte es von der Geschwindigkeit in einer ähnlichen Liga spielen, wie NFS ohne Verschlüsselung. Also habe ich es einfach mal ausprobiert.

Wie kann ich mit minimalem Aufwand an Software ein NAS konfigurieren? Nun, ssh bringt jede Linuxdistribution für den Server schon mit. Man muss es allenfalls noch anschalten.

Auf dem zugreifenden Client ist es noch zu installieren, auf Debian bzw. Arch-Linux so:

apt install sshfs

bzw.

pacman -S sshfs

Performance-Messung

Ich habe jetzt einige Tests gemacht und dabei ein Benchmark-Script von Michał Turecki benutzt, welches für verschiedene Ciphers, also Verschlüsselungstechniken, die Zeit misst, mit der zwei Geräte über ssh Daten austauschen können. Hier spielt alles eine Rolle: Welche Hardware-Unterstützung Client und Server haben, wie das Netz ist, die im Netzwerkinterface gesetzte maximale Transfereinheit (MTU), ob WLAN, LAN oder PowerLAN und so weiter. Hier das Script. Um es sinnvoll laufen zu lassen muss auf dem gegenüberliegenden SSH-Server die Public-Key-Unterstützung möglich sein und wir sollten vorher den ssh-agent benutzen, um unseren privaten Schlüssel vor zu laden. Auf dem Client:

ssh-agent
ssh-add

Nun ist unser Schlüssel im Speicher und wir werden nicht ständig nach der Passphrase gefragt, was ja unsere Messungen verfälschen würde. Hier jetzt also das Script, user@sshserver bitte ersetzen:

#!/bin/bash
for i in `ssh -Q cipher`; do dd if=/dev/zero bs=1M count=100 2> /dev/null \
  | ssh -c $i user@sshserver "(time -p cat) > /dev/null" 2>&1 \
  | grep real | awk '{print "'$i': "100 / $2" MB/s" }'; done

Ich habe damit folgende Messungen gemacht:

Messergebnisse

Der ziemlich enttäuschende Zugriff von meinem Notebook über WLAN an den Router, von dort ins PowerLAN über meine uralte 60er-Jahre Stromleitung in den Keller und rein in den Raspberry Pi 4B:

aes128-ctr: 4 MB/s
aes192-ctr: 4.16667 MB/s
aes256-ctr: 4.34783 MB/s
aes128-gcm@openssh.com: 4.16667 MB/s
aes256-gcm@openssh.com: 4.16667 MB/s
chacha20-poly1305@openssh.com: 4.34783 MB/s

Mit dem Raspberry Pi 3B im Keller war es vormals nochmal ein Drittel! Das ist wirklich schlecht, auch mit dem 4er. Als nächstes also in den Keller gelaufen und das Notebook via LAN direkt an den im PowerLAN eingebauten Switch angeschlossen:

aes128-ctr: 50 MB/s
aes192-ctr: 50 MB/s
aes256-ctr: 50 MB/s
aes128-gcm@openssh.com: 33.3333 MB/s
aes256-gcm@openssh.com: 33.3333 MB/s
chacha20-poly1305@openssh.com: 50 MB/s

Bumms, das sieht schon anders aus. Also ist das PowerLAN der Flaschenhals.

Jetzt ich wieder hoch und habe mein Notebook mit meinem zweiten Raspberry Pi 3B im Wohnzimmer via WLAN verbunden, der normalerweise nur meine Pleroma-Instanz beherbergt.

aes128-ctr: 9.09091 MB/s
aes192-ctr: 9.09091 MB/s
aes256-ctr: 10 MB/s
aes128-gcm@openssh.com: 10 MB/s
aes256-gcm@openssh.com: 10 MB/s
chacha20-poly1305@openssh.com: 10 MB/s

Das Gleiche jetzt nochmal mit LAN-Kabel, der Raspberry Pi 3B hängt direkt am Router und ich auch:

aes128-ctr: 12.5 MB/s
aes192-ctr: 12.5 MB/s
aes256-ctr: 12.5 MB/s
aes128-gcm@openssh.com: 12.5 MB/s
aes256-gcm@openssh.com: 12.5 MB/s
chacha20-poly1305@openssh.com: 12.5 MB/s

Tja, also der dreier Raspberry Pi ist wohl nicht all zu flott unterwegs. Dann doch lieber den im Keller.

Fazit

Flaschenhals ist definitiv also das PowerLAN auf den langen und alten Leitungen hier im Haus. Das Ganze würde noch besser laufen, wenn ich bessere Kabel im Haus hätte, zum Beispiel einfach ein LAN. Die Verwendung von LAN gegenüber dem WLAN hat den Durchsatz nochmals ein bisschen gesteigert. Das Ausschalten der Kompression mit

-o compression=no

hat übrigens keinerlei Einfluss auf den Durchsatz gehabt.

Generell scheint der Chaha20 Cipher für die Kombination ARM und x64 gut zu funktionieren. AES128 bringt offenbar nichts.

Nutzung

Zum Mounten der fernen Verzeichnisse habe ich mir folgendes kleine Script gebaut, wie gesagt, vorher den privaten Schlüssel in den ssh-agent laden:

#!/bin/bash

opts="-o auto_cache -o idmap=user \
-o cache_timeout=115200 -o attr_timeout=115200 -o entry_timeout=1200  \
-o Ciphers=chacha20-poly1305@openssh.com \
-o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3"

sshfs user@sshserver: ~/Cloud $opts

Die Option auto_cache bewirkt, dass die gecachten Daten im Client invalidiert werden, sobald sich auf der Serverseite die File-Größe oder die Modification-Time ändert.

Mit idmap=user erreichen wir, dass bei uns alle Dateien mit Rechten für unseren lokalen User erscheinen, obwohl auf dem Server die Dateien einem User mit einer anderen User-ID gehören.

Die Cache-Zeilen sorgen dafür, dass Dateien, die einmal in den lokalen Cache im RAM geladen wurden, nicht so schnell wieder rausfallen.

Die letzte Zeile sorgt für einen Reconnect, wenn Ihr einmal für mindestens 3x15 Sekunden keinen Connect bekommen habt.