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. |