SSH – Force Command execution on login even without Shell

Iacchus picture Iacchus · Nov 14, 2015 · Viewed 41.5k times · Source

I am creating a restricted user without shell for port forwarding only and I need to execute a script on login via pubkey, even if the user is connected via ssh -N user@host which doesn't asks SSH server for a shell.

The script should warn admin on connections authenticated with pubkey, so the user connecting shouldn't be able to skip the execution of the script (e.g., by connecting with ssh -N).

I have tried to no avail:

  • Setting the command at /etc/ssh/sshrc.
  • Using command="COMMAND" in .ssh/authorized_keys (man authorized_keys)
  • Setting up a script with the command as user's shell. (chsh -s /sbin/myscript.sh USERNAME)
  • Matching user in /etc/ssh/sshd_config like: Match User MYUSERNAME ForceCommand "/sbin/myscript.sh"

All work when user asks for shell, but if logged only for port forwarding and no shell (ssh -N) it doesn't work.

Answer

Todd A. Jacobs picture Todd A. Jacobs · Nov 14, 2015

The ForceCommand option runs without a PTY unless the client requests one. As a result, you don't actually have a shell to execute scripts the way you might expect. In addition, the OpenSSH SSHD_CONFIG(5) man page clearly says:

The command is invoked by using the user's login shell with the -c option.

That means that if you've disabled the user's login shell, or set it to something like /bin/false, then ForceCommand can't work. Assuming that:

  1. the user has a sensible shell defined,
  2. that your target script is executable, and
  3. that your script has an appropriate shebang line

then the following should work in your global sshd_config file once properly modified with the proper username and fully-qualified pathname to your custom script:

Match User foo
    ForceCommand /path/to/script.sh