Le opzioni
| Opzione | Cosa fa | Cosa vede l'altra parte |
|---|---|---|
restrict | Nessun inoltro di alcun tipo, nessun terminale, niente ~/.ssh/rc | PTY allocation request failed on channel 0 |
command="..." | Esegue sempre questo comando | L'output di quel comando |
from="..." | Solo da questi indirizzi o nomi | Permission denied |
permitopen="host:port" | Limita ssh -L e -W a questa destinazione | stdio forwarding failed oppure open failed |
permitlisten="[host:]port" | Limita ssh -R a questa porta | remote port forwarding failed |
Parti da restrict e riaggiungi solo ciò che serve alla chiave. Copre anche le restrizioni che OpenSSH aggiungerà in futuro, cosa che un elenco come no-pty,no-port-forwarding non fa. Le opzioni stanno su una sola riga, separate da virgole, senza spazi in mezzo.
Un solo comando
restrict,command="/usr/local/bin/backup" ssh-ed25519 AAAA... backup-job
Ora sia ssh user@server sia ssh user@server rm -rf / eseguono il backup e nient'altro.
Pochi comandi permessi, con SSH_ORIGINAL_COMMAND
Quello che il client ha chiesto sta nella variabile SSH_ORIGINAL_COMMAND, e un piccolo script può controllarla:
#!/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
Nella nostra prova, ssh user@server uptime ha funzionato, mentre ssh user@server "uptime; id" ha risposto Not allowed: uptime; id. Confronta stringhe intere, come sopra. Un pattern come uptime* lascia passare qualsiasi cosa inizi con quella parola, e non passare mai la variabile a sh -c o a eval.
Scegli con cura anche i comandi permessi. Un comando che può scrivere file o aprire una shell, come un editor, annulla la restrizione.
Limitare per indirizzo
from="203.0.113.10,198.51.100.0/24" ssh-ed25519 AAAA... office
Funzionano sia i pattern sia gli intervalli CIDR, e ! esclude un indirizzo. Usa indirizzi IP e non nomi host, perché un nome host dipende dal DNS inverso. Quando l'indirizzo non corrisponde, il client vede Permission denied e il log del server ne spiega il motivo:
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).
Una chiave solo per un tunnel
restrict,port-forwarding,permitopen="10.0.1.10:5432",command="/usr/sbin/nologin" ssh-ed25519 AAAA... db-tunnel
Questa chiave può raggiungere il database a quell'indirizzo e a quella porta. Un inoltro verso un'altra porta fallisce, e un comando ottiene solo This account is currently not available. Per usarla, aggiungi -N così che ssh non chieda alcun comando:
ssh -N -L 5432:10.0.1.10:5432 user@server
Un nome host in permitopen deve corrispondere esattamente a quello che invia il client, senza alcuna risoluzione. localhost e 127.0.0.1 contano come due cose diverse.
Attenzione: questa riga permette ancora ssh -R
port-forwarding attiva entrambe le direzioni, e permitopen ne limita una sola. Nella nostra prova, la chiave qui sopra poteva ancora aprire un inoltro remoto con ssh -R. permitlisten="none" non è una soluzione, perché la riga diventa non valida e la chiave smette di funzionare del tutto. Fai invece una di queste due cose:
- Imposta
permitlistensu una sola porta che nessuno usa, per esempiopermitlisten="127.0.0.1:9". Abbiamo verificato che un inoltro su qualsiasi altra porta viene rifiutato. - Limita l'account nella configurazione del server, così vale per tutte le sue chiavi:
# /etc/ssh/sshd_config.d/10-tunnel.conf
Match User tunnel
AllowTcpForwarding local
Per cosa fanno -L, -R e -D, vedi tunnel SSH locali, remoti e dinamici.
Chiavi per il trasferimento di file
restrict da solo non blocca il trasferimento di file. Nella nostra prova, sftp funzionava ancora, perché SFTP non richiede né terminale né inoltro. Per permettere SFTP e nient'altro:
restrict,command="internal-sftp" ssh-ed25519 AAAA... files
Per permettere rsync in una sola cartella, usa rrsync, che arriva insieme a rsync. Su Debian si trova in /usr/bin/rrsync, altri sistemi possono differire. Con -ro permette solo la lettura, e abbiamo confermato che i caricamenti poi falliscono:
restrict,command="/usr/bin/rrsync -ro /srv/backup" ssh-ed25519 AAAA... backup-read
Cosa non fanno queste opzioni
- Vincolano solo quella chiave. Un'altra chiave, o una password, sullo stesso account non ha nessuno di questi limiti. Dove puoi, dai a ogni lavoro il suo account e disattiva le password.
- L'utente può modificare il file. Se l'account può scrivere nel proprio
authorized_keys, un comando che scrive file può togliere i limiti. Per un confine solido, lascia il file di proprietà di root. Vedi authorized_keys spiegato. - L'ordine delle righe conta. Se la stessa chiave compare anche in una riga senza restrizioni più in alto, vince quella riga.
Domande
command= in authorized_keys blocca SFTP?
Sì, se command= indica qualcosa di diverso da internal-sftp, perché SFTP esegue quel comando al suo posto. restrict da solo non blocca SFTP.
Cos'è SSH_ORIGINAL_COMMAND?
Una variabile d'ambiente con il comando chiesto dal client quando gira un comando forzato. Uno script può controllarla e permettere solo pochi comandi esatti.
Posso usare un nome host in from=?
Sì, ma dipende dal DNS inverso, che l'altra parte può controllare. Indirizzi IP e intervalli CIDR sono più sicuri.