| Title: Safely restrict commands through SSH | |
| Author: Solène | |
| Date: 08 November 2018 | |
| Tags: ssh security openbsd highlight | |
| Description: | |
| [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. |