💾 Archived View for perso.pw › blog › articles › ssh-auth-command.gmi captured on 2024-05-10 at 11:29:20. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2024-03-21)

-=-=-=-=-=-=-

Safely restrict commands through SSH

NIL[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

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.