How to disable ssh non-interactive commands from the server side?
Solution 1:
There is ForceCommand
keyword in sshd_config
:
ForceCommand
Forces the execution of the command specified by ForceCommand, ignoring any command supplied by the client and~/.ssh/rc
if present. The command is invoked by using the user's login shell with the-c
option. This applies to shell, command, or subsystem execution. It is most useful inside a Match block. The command originally supplied by the client is available in theSSH_ORIGINAL_COMMAND
environment variable. […]
(source)
If you use it like this:
ForceCommand exec /bin/sh -i
then you will force interactive sh
. There are at least two problems with this simple approach:
- I haven't found any simple way to force tty allocation by configuring the server. A client can choose, the server may allow or refuse (with
PermitTTY
). When forcing interactivesh
, supposedly it would be good to force tty allocation. I may have missed something; it doesn't matter because on the other hand… - A client trying to run a non-interactive command does not expect interactive shell instead. A better way to disable such command is to make it fail. Probably this is what you want.
Therefore:
ForceCommand if [ "$SSH_ORIGINAL_COMMAND" ]; then echo "this server rejects non-interactive ssh usage" >&2; exit 1; else exec "$SHELL" -i; fi
Notes:
-
ForceCommand
uses the user's login shell with the-c
option. Our command uses portable syntax, it should work in many shells. If the user can choose something non-standard as his or her login shell then the command may misbehave. Consider putting the command in a script (with proper shebang) and executing the script instead (ForceCommand /path/to/the_script
). -
$SHELL
will most likely work as expected, still I think the variable is not strictly required by POSIX. You may prefer${SHELL:-/bin/sh}
or something similar instead.