Die Optionen
| Option | Was sie tut | Was die Gegenseite sieht |
|---|---|---|
restrict | Keine Weiterleitung jeder Art, kein Terminal, kein ~/.ssh/rc | PTY allocation request failed on channel 0 |
command="..." | Führt immer diesen Befehl aus | Die Ausgabe dieses Befehls |
from="..." | Nur von diesen Adressen oder Namen | Permission denied |
permitopen="host:port" | Beschränkt ssh -L und -W auf dieses Ziel | stdio forwarding failed oder open failed |
permitlisten="[host:]port" | Beschränkt ssh -R auf diesen Port | remote port forwarding failed |
Beginnen Sie mit restrict und fügen Sie nur hinzu, was der Schlüssel braucht. Das deckt auch Beschränkungen ab, die OpenSSH künftig neu einführt, anders als eine Liste wie no-pty,no-port-forwarding. Die Optionen stehen in einer Zeile, durch Kommas getrennt und ohne Leerzeichen dazwischen.
Nur ein Befehl
restrict,command="/usr/local/bin/backup" ssh-ed25519 AAAA... backup-job
Jetzt führen sowohl ssh user@server als auch ssh user@server rm -rf / das Backup aus und sonst nichts.
Einige erlaubte Befehle mit SSH_ORIGINAL_COMMAND
Was der Client verlangt hat, steht in der Variable SSH_ORIGINAL_COMMAND, und ein kleines Skript kann sie prüfen:
#!/bin/sh
# /usr/local/bin/ssh-allow
case "$SSH_ORIGINAL_COMMAND" in
"uptime"|"df -h")
exec $SSH_ORIGINAL_COMMAND
;;
*)
echo "Not allowed: $SSH_ORIGINAL_COMMAND" >&2
exit 1
;;
esac
restrict,command="/usr/local/bin/ssh-allow" ssh-ed25519 AAAA... monitoring
In unserem Test funktionierte ssh user@server uptime, und ssh user@server "uptime; id" antwortete mit Not allowed: uptime; id. Vergleichen Sie ganze Zeichenketten wie oben. Ein Muster wie uptime* lässt alles durch, was mit diesem Wort beginnt, und übergeben Sie die Variable niemals an sh -c oder eval.
Wählen Sie auch die erlaubten Befehle mit Sorgfalt. Ein Befehl, der Dateien schreiben oder eine Shell starten kann, etwa ein Editor, hebt die Beschränkung wieder auf.
Nach Adresse beschränken
from="203.0.113.10,198.51.100.0/24" ssh-ed25519 AAAA... office
Muster und CIDR-Bereiche funktionieren beide, und mit ! schließen Sie eine Adresse aus. Verwenden Sie IP-Adressen statt Hostnamen, denn ein Hostname hängt vom Reverse-DNS ab. Passt die Adresse nicht, sieht der Client Permission denied, und das Server-Log nennt den Grund:
Authentication tried for user with correct key but not from a permitted host (host=198.51.100.7, ip=198.51.100.7, required=203.0.113.10).
Ein Schlüssel nur für einen Tunnel
restrict,port-forwarding,permitopen="10.0.1.10:5432",command="/usr/sbin/nologin" ssh-ed25519 AAAA... db-tunnel
Dieser Schlüssel erreicht die Datenbank an dieser Adresse und diesem Port. Eine Weiterleitung auf einen anderen Port schlägt fehl, und ein Befehl liefert nur This account is currently not available. Zur Nutzung fügen Sie -N hinzu, damit ssh keinen Befehl anfordert:
ssh -N -L 5432:10.0.1.10:5432 user@server
Ein Hostname in permitopen muss genau dem entsprechen, was der Client sendet, ohne Namensauflösung. localhost und 127.0.0.1 gelten als verschieden.
Achtung: Das erlaubt trotzdem ssh -R
port-forwarding schaltet beide Richtungen frei, und permitopen beschränkt nur eine. In unserem Test konnte der Schlüssel oben trotzdem mit ssh -R eine Remote-Weiterleitung öffnen. permitlisten="none" ist kein Ausweg, denn dann ist die Zeile ungültig und der Schlüssel funktioniert gar nicht mehr. Tun Sie stattdessen eines von beidem:
- Setzen Sie
permitlistenauf einen einzelnen Port, den nichts benutzt, zum Beispielpermitlisten="127.0.0.1:9". Wir haben getestet, dass eine Weiterleitung auf jeden anderen Port abgelehnt wird. - Beschränken Sie das Konto in der Server-Konfiguration, was für alle seine Schlüssel gilt:
# /etc/ssh/sshd_config.d/10-tunnel.conf
Match User tunnel
AllowTcpForwarding local
Was -L, -R und -D bewirken, erklärt lokale, entfernte und dynamische SSH-Tunnel.
Schlüssel für Dateiübertragung
restrict allein verhindert keine Dateiübertragung. In unserem Test funktionierte sftp damit weiterhin, weil SFTP weder Terminal noch Weiterleitung braucht. So erlauben Sie SFTP und sonst nichts:
restrict,command="internal-sftp" ssh-ed25519 AAAA... files
Um rsync in einem Ordner zu erlauben, nutzen Sie rrsync, das mit rsync mitkommt. Unter Debian liegt es in /usr/bin/rrsync, auf anderen Systemen kann das abweichen. Mit -ro ist nur Lesen erlaubt, und wir haben bestätigt, dass Uploads dann scheitern:
restrict,command="/usr/bin/rrsync -ro /srv/backup" ssh-ed25519 AAAA... backup-read
Was diese Optionen nicht leisten
- Sie binden nur diesen einen Schlüssel. Ein anderer Schlüssel oder ein Passwort desselben Kontos hat keine dieser Beschränkungen. Geben Sie wenn möglich jeder Aufgabe ein eigenes Konto und schalten Sie Passwörter ab.
- Der Benutzer kann die Datei bearbeiten. Darf das Konto seine eigene
authorized_keysschreiben, kann ein Befehl, der Dateien schreibt, die Beschränkungen entfernen. Für eine feste Grenze sollte die Datei root gehören. Siehe authorized_keys erklärt. - Die Reihenfolge der Zeilen zählt. Steht derselbe Schlüssel weiter oben noch einmal ohne Beschränkung, gilt diese Zeile.
Fragen
Blockiert command= in authorized_keys SFTP?
Ja, wenn command= auf etwas anderes als internal-sftp zeigt, denn SFTP führt dann stattdessen diesen Befehl aus. restrict allein blockiert SFTP nicht.
Was ist SSH_ORIGINAL_COMMAND?
Eine Umgebungsvariable mit dem Befehl, den der Client angefordert hat, wenn ein erzwungener Befehl läuft. Ein Skript kann sie prüfen und nur wenige exakte Befehle zulassen.
Kann ich in from= einen Hostnamen verwenden?
Ja, aber das hängt vom Reverse-DNS ab, das die Gegenseite steuern kann. IP-Adressen und CIDR-Bereiche sind sicherer.