Einen entfernten SMB-Share lokal bereitstellen, ohne die Zugangsdaten zu verteilen
smb-proxy holt einen entfernten SMB-Share, etwa von einer Hetzner Storage Box, in einen Docker-Container und stellt ihn lokal mit eigenem Login bereit. Wie du ihn startest, was er im Container tut und an welchen vier Stellen du aufpassen solltest.

Eine Hetzner Storage Box spricht neben SFTP auch SMB, und SMB-Freigaben kann fast jedes Betriebssystem einbinden. Für jedes Gerät, das die Box nutzen soll, brauchst du dann allerdings die Zugangsdaten der Box. Von außerhalb des Hetzner-Netzes muss bei der Box außerdem „Äußere Erreichbarkeit“ eingeschaltet sein.
smb-proxy ist ein kleiner Docker-Container von mir, der an dieser Stelle dazwischensitzt. Er meldet sich mit den Zugangsdaten der Box an und stellt den Share im eigenen Netz unter einem eigenen Benutzer und Passwort bereit. Die Zugangsdaten der Box bleiben im Container. Der Text bezieht sich auf Version 0.0.2, und die Storage Box dient als Beispiel. Bei einem anderen SMB-Server ändern sich nur Host, Share und Zugangsdaten.
Starten
Das Image liegt auf GHCR und ist für amd64 und arm64 gebaut. Für eine Storage Box sieht der Start so aus:
docker run -d \
--name smb-proxy \
--privileged \
-p 127.0.0.1:1445:445 \
-e SMB_HOST=u123456.your-storagebox.de \
-e SMB_SHARE=backup \
-e SMB_USER=u123456 \
-e SMB_PASSWORD='Passwort-der-Box' \
-e LOCAL_SHARE=proxy \
-e LOCAL_USER=proxy \
-e LOCAL_PASSWORD='lokales-Passwort' \
ghcr.io/danielgtmn/smb-proxy:latest
Die ersten vier Variablen beschreiben die Box. Bei Hetzner heißt der Share beim Hauptbenutzer backup. Bei einem Unterkonto ist der Share-Name der Benutzername des Unterkontos, also zum Beispiel u123456-sub1. Host und Benutzer ändern sich dann mit: SMB_HOST=u123456-sub1.your-storagebox.de und SMB_USER=u123456-sub1. In der Hetzner-Konsole muss SMB für die Box aktiviert sein, und nach dem Einschalten kann es ein paar Minuten dauern, bis es funktioniert. Die drei LOCAL_-Variablen legen fest, wie der Share im eigenen Netz heißt und womit sich deine Geräte anmelden.
Danach bindest du den Share ein. Unter Linux geht das mit smbclient:
smbclient //127.0.0.1/proxy -p 1445 -U proxy
Im Finder öffnest du mit Cmd+K die Adresse smb://127.0.0.1:1445/proxy. Der Port 1445 steht im Beispiel, weil Port 445 auf einem Mac oft schon belegt ist.
Was im Container passiert
Der Container arbeitet vier Schritte ab:
- Er liest die Konfiguration aus den Umgebungsvariablen. Fehlt
SMB_HOST,SMB_SHARE,SMB_USERoderSMB_PASSWORD, bricht er sofort ab. - Er meldet sich mit der Go-Bibliothek
go-smb2an der Box an und öffnet den Share. Schlägt das fehl, beendet sich der Container mit der Meldung „remote SMB verification failed“. Bei Problemen lohnt sich deshalb zuerst ein Blick indocker logs smb-proxy. - Er bindet den Share mit
mount -t cifsnach/mnt/remoteein. Die Zugangsdaten stehen dabei in einer Datei mit Rechten0600und nicht auf der Kommandozeile. - Er schreibt eine
smb.conf, legt den lokalen Samba-Benutzer an und startetsmbdim Vordergrund. Beendet sichsmbd, beendet sich auch der Container.
Mount-Optionen
Als Mount-Optionen setzt smb-proxy standardmäßig iocharset=utf8,rw,seal,vers=3.0,uid=0,gid=0,file_mode=0664,dir_mode=0775,noserverino. Wichtig ist seal. Laut Hetzner-Dokumentation sind SMB-Verbindungen nicht in jedem Fall verschlüsselt, und für die Verschlüsselung braucht es genau diese Option.
Laut Hetzner kann cache=none helfen, wenn es beim Kopieren von Dateien ab 4 GB Fehler gibt. In der README steht dazu, SMB_MOUNT_OPTIONS nehme „extra“ Optionen auf. Im Code ersetzt der Wert aber die ganze Standardliste. Wer nur cache=none setzt, verliert damit seal und vers=3.0. Schreib deshalb die komplette Liste und häng die neue Option an:
-e SMB_MOUNT_OPTIONS='iocharset=utf8,rw,seal,vers=3.0,uid=0,gid=0,file_mode=0664,dir_mode=0775,noserverino,cache=none'
Ein weiterer Standard betrifft IPv6. SMB_FORCE_IPV4 steht auf true: Der Container löst den Hostnamen zu einer IPv4-Adresse auf und übergibt sie dem Mount. Das hilft, wenn Docker auf einem Host IPv6 bevorzugt, das dort nicht funktioniert. Mit SMB_HOST_IP legst du die Adresse selbst fest.
TCP-Modus
Neben dem Gateway gibt es einen zweiten Modus mit SMB_PROXY_MODE=tcp. Dann reicht der Container nur TCP-Verbindungen vom lokalen Port an den SMB-Server weiter:
docker run -d \
--name smb-proxy \
-p 127.0.0.1:1445:445 \
-e SMB_PROXY_MODE=tcp \
-e SMB_HOST=u123456.your-storagebox.de \
ghcr.io/danielgtmn/smb-proxy:latest
Hier meldet sich jeder Client selbst am Server an, mit den Zugangsdaten der Box. Die Variablen für Benutzer und Passwort nutzt der TCP-Modus nicht. Dafür braucht dieser Modus kein --privileged, weil nichts gemountet wird. Du nutzt ihn, wenn die Clients ihre eigenen Zugangsdaten haben und du nur einen anderen Weg zum Server brauchst.
Worauf du achten solltest
Der Container läuft privilegiert
Für den CIFS-Mount braucht der Container erweiterte Rechte. Die README nennt --privileged oder CAP_SYS_ADMIN. Die mitgelieferte docker-compose.yml setzt privileged: true, SYS_ADMIN und apparmor:unconfined zusammen. Ein privilegierter Container hat auf dem Host weitreichende Rechte. Starte ihn deshalb nur auf einem Rechner, dem du ohnehin vertraust, und nur mit dem Image aus diesem Repository.
Ohne Adresse hört der Port auf allen Netzwerkkarten
Ein -p 1445:445 veröffentlicht den Port auf jeder Schnittstelle des Hosts, und die mitgelieferte docker-compose.yml schreibt es genau so. Dann kann jedes Gerät im selben Netz den Share erreichen und sich mit LOCAL_USER und LOCAL_PASSWORD anmelden. Wenn nur dein Rechner den Share braucht, schreib wie oben -p 127.0.0.1:1445:445, in Compose entsprechend "127.0.0.1:1445:445".
Noch weiter geht LOCAL_ALLOW_GUEST=true. Dann braucht niemand ein Passwort, und der Share ist beschreibbar konfiguriert. Wer den Port erreicht, kommt an die Dateien der Box. Lass die Variable auf false, solange du den Port nicht abgeschottet hast.
Passwörter stehen in Umgebungsvariablen
Alle Zugangsdaten gehen über Umgebungsvariablen in den Container. Wer auf dem Host docker inspect smb-proxy ausführen darf, sieht sie im Klartext. Die README rät, Docker Secrets oder einen Vault zu nutzen. Die Konfiguration liest allerdings nur Umgebungsvariablen und kennt keine Variante, die ein Passwort aus einer Datei lädt. Bei Docker Compose legst du die Werte deshalb in eine .env, die nicht ins Git gehört. Im Repository ist .env in der .gitignore eingetragen.
Der lokale Benutzer muss im Container existieren
LOCAL_USER legt der Container nicht selbst als Systembenutzer an. Er ruft smbpasswd -a auf, und das verlangt einen Benutzer, den es im System schon gibt. Der Standardwert proxy funktioniert, weil Debian einen Systembenutzer mit diesem Namen mitbringt. Bei einem anderen Namen wie daniel schlägt der Start nach der Samba-Dokumentation fehl, und im Log steht „create local samba user“.
Dieser Benutzer ist auch der, mit dem Samba auf die Dateien zugreift. Mit den Standardoptionen gehört der Mount aber root (uid=0,gid=0), Dateien haben 0664, Ordner 0775. Für proxy bleibt damit voraussichtlich nur Lesen, obwohl der Share in der smb.conf mit read only = no eingetragen ist. Prüf nach dem Start einmal, ob du eine Datei anlegen kannst.
Wofür es reicht
smb-proxy hält pro Container genau einen Share. Für zwei Boxen oder zwei Shares startest du zwei Container mit unterschiedlichen Host-Ports. Es ist ein kleiner Helfer für zu Hause oder ein kleines Netz, in dem die Zugangsdaten der Box an einer Stelle liegen sollen.
Wer die Box lieber ohne Docker auf dem Mac im Finder haben möchte, findet in diesem Beitrag den Weg über SFTP. Fragen und Fehler zu smb-proxy gehören in die Issues auf GitHub.