Title : Safely restrict commands through SSH Author: Solène Date : 08 November 2018 Tags : ssh security openbsd68 highlight [sshd(8)](https://man.openbsd.org/sshd) has a very nice feature that is often overlooked. That feature is the ability to allow a ssh user to run a specified command and nothing else, not even a login shell. This is really easy to use and the magic happens in the file **authorized_keys** which can be used to restrict commands per public key. For example, if you want to allow someone to run the "uptime" command on your server, you can create a user account for that person, with no password so the password login will be disabled, and add his/her ssh public key in ~/.ssh/authorized_keys of that new user, with the following content. restrict,command="/usr/bin/uptime" ssh-rsa the_key_content_here The user will not be able to log-in, and doing the command `ssh remoteserver` will return the output of `uptime`. There is no way to escape this. While running uptime is not really helpful, this can be used for a much more interesting use case, like allowing remote users to use **vmctl** without giving a shell account. The vmctl command requires parameters, the configuration will be slightly different. restrict,pty,command="/usr/sbin/vmctl $SSH_ORIGINAL_COMMAND" ssh-rsa the_key_content_here" The variable *SSH_ORIGINAL_COMMAND* contains the value of what is passed as parameter to ssh. The **pty** keyword also make an appearance, that will be explained later. If the user connects to ssh, vmctl with no parameter will be output. $ ssh remotehost usage: vmctl [-v] command [arg ...] vmctl console id vmctl create "path" [-b base] [-i disk] [-s size] vmctl load "path" vmctl log [verbose|brief] vmctl reload vmctl reset [all|vms|switches] vmctl show [id] vmctl start "name" [-Lc] [-b image] [-r image] [-m size] [-n switch] [-i count] [-d disk]* [-t name] vmctl status [id] vmctl stop [id|-a] [-fw] vmctl pause id vmctl unpause id vmctl send id vmctl receive id If you pass parameters to ssh, it will be passed to vmctl. $ ssh remotehost show ID PID VCPUS MAXMEM CURMEM TTY OWNER NAME 1 - 1 1.0G - - solene test $ ssh remotehost start test vmctl: started vm 1 successfully, tty /dev/ttyp9 $ ssh -t remotehost console test (I)nstall, (U)pgrade, (A)utoinstall or (S)hell? The ssh connections become a call to vmctl and ssh parameters become vmctl parameters. Note that in the last example, I use "ssh -t", this is so to force allocation of a pseudo tty device. This is required for vmctl console to get a fully working console. The keyword **restrict** does not allow pty allocation, that is why we have to add **pty** after restrict, to allow it.