Les options
| Option | Effet | Ce que voit l'autre côté |
|---|---|---|
restrict | Aucune redirection d'aucune sorte, pas de terminal, pas de ~/.ssh/rc | PTY allocation request failed on channel 0 |
command="..." | Exécute toujours cette commande | La sortie de cette commande |
from="..." | Uniquement depuis ces adresses ou ces noms | Permission denied |
permitopen="host:port" | Limite ssh -L et -W à cette destination | stdio forwarding failed ou open failed |
permitlisten="[host:]port" | Limite ssh -R à ce port | remote port forwarding failed |
Commencez par restrict, puis ajoutez ce dont la clé a besoin. Cette option couvre aussi toute restriction qu'OpenSSH ajoutera plus tard, ce que ne fait pas une liste de no-pty,no-port-forwarding et autres. Les options tiennent sur une seule ligne, séparées par des virgules, sans espace entre elles.
Une seule commande
restrict,command="/usr/local/bin/backup" ssh-ed25519 AAAA... backup-job
Désormais, ssh user@server et ssh user@server rm -rf / lancent tous deux la sauvegarde et rien d'autre.
Quelques commandes autorisées, avec SSH_ORIGINAL_COMMAND
Ce que le client a demandé se trouve dans la variable SSH_ORIGINAL_COMMAND, et un petit script peut la vérifier :
#!/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
Dans notre essai, ssh user@server uptime a fonctionné, et ssh user@server "uptime; id" a répondu Not allowed: uptime; id. Comparez des chaînes entières, comme ci-dessus. Un motif comme uptime* laisse passer tout ce qui commence par ce mot, et ne transmettez jamais la variable à sh -c ou eval.
Choisissez aussi les commandes autorisées avec soin. Une commande capable d'écrire des fichiers ou de lancer un shell, comme un éditeur, annule la restriction.
Limiter par adresse
from="203.0.113.10,198.51.100.0/24" ssh-ed25519 AAAA... office
Les motifs et les plages CIDR fonctionnent tous deux, et ! exclut une adresse. Utilisez des adresses IP plutôt que des noms d'hôte, car un nom d'hôte dépend du DNS inverse. Quand l'adresse ne correspond pas, le client voit Permission denied et le journal du serveur donne l'explication :
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).
Une clé réservée à un seul tunnel
restrict,port-forwarding,permitopen="10.0.1.10:5432",command="/usr/sbin/nologin" ssh-ed25519 AAAA... db-tunnel
Cette clé peut atteindre la base de données à cette adresse et sur ce port. Une redirection vers un autre port échoue, et une commande ne reçoit que This account is currently not available. Pour l'utiliser, ajoutez -N afin que ssh ne demande aucune commande :
ssh -N -L 5432:10.0.1.10:5432 user@server
Un nom d'hôte dans permitopen doit correspondre exactement à ce qu'envoie le client, sans résolution. localhost et 127.0.0.1 comptent comme deux valeurs différentes.
Attention : cela autorise encore ssh -R
port-forwarding active les deux sens, et permitopen n'en limite qu'un. Dans notre essai, la clé ci-dessus pouvait encore ouvrir une redirection distante avec ssh -R. permitlisten="none" n'est pas une issue, car la ligne devient alors invalide et la clé cesse complètement de fonctionner. Faites plutôt l'une de ces deux choses :
- Réglez
permitlistensur un seul port que rien n'utilise, par exemplepermitlisten="127.0.0.1:9". Nous avons vérifié qu'une redirection sur tout autre port est refusée. - Limitez le compte dans la configuration du serveur, ce qui vaut pour toutes ses clés :
# /etc/ssh/sshd_config.d/10-tunnel.conf
Match User tunnel
AllowTcpForwarding local
Pour le rôle de -L, -R et -D, voyez les tunnels SSH locaux, distants et dynamiques.
Clés pour le transfert de fichiers
restrict seul n'empêche pas le transfert de fichiers. Dans notre essai, sftp fonctionnait encore avec cette option, car SFTP n'a besoin ni de terminal ni de redirection. Pour autoriser SFTP et rien d'autre :
restrict,command="internal-sftp" ssh-ed25519 AAAA... files
Pour autoriser rsync dans un seul dossier, utilisez rrsync, fourni avec rsync. Sur Debian, il se trouve dans /usr/bin/rrsync, et d'autres systèmes peuvent différer. Avec -ro, seule la lecture est permise, et nous avons confirmé que les envois échouent alors :
restrict,command="/usr/bin/rrsync -ro /srv/backup" ssh-ed25519 AAAA... backup-read
Ce que ces options ne font pas
- Elles ne lient que cette clé. Une autre clé, ou un mot de passe, sur le même compte n'a aucune de ces limites. Donnez à chaque tâche son propre compte quand c'est possible, et désactivez les mots de passe.
- L'utilisateur peut modifier le fichier. Si le compte peut écrire dans son propre
authorized_keys, une commande capable d'écrire des fichiers peut supprimer les limites. Pour une frontière solide, laissez le fichier appartenir à root. Voir authorized_keys expliqué. - L'ordre des lignes compte. Si la même clé figure aussi sur une ligne sans restriction plus haut, c'est cette ligne qui l'emporte.
Questions
command= dans authorized_keys bloque-t-il SFTP ?
Oui, si command= désigne autre chose que internal-sftp, car SFTP exécute alors cette commande à la place. restrict seul ne bloque pas SFTP.
Qu'est-ce que SSH_ORIGINAL_COMMAND ?
Une variable d'environnement qui contient la commande demandée par le client quand une commande forcée s'exécute. Un script peut la vérifier et n'autoriser que quelques commandes exactes.
Peut-on mettre un nom d'hôte dans from= ?
Oui, mais cela dépend du DNS inverse, que l'autre partie peut contrôler. Les adresses IP et les plages CIDR sont plus sûres.