remctl-shell - Restricted shell that mimics a remctl server
remctl-shell [ -dhqSv
] [-f config
] -c command
remctl-shell [ -dqS
] [-f config
is a restricted shell that mimics the behavior of the
server without using the remctl protocol, GSS-API, or Kerberos.
It's intended to be run via ssh as either the shell or the forced command for
a special user (by convention, "remctl", although
doesn't care), with an authorized_keys
specifies the user identity corresponding to each key that is allowed to run
remctl commands. All access control then works as normal.
The output of the command ran is returned on standard output and standard error,
like a normal command run via ssh, and the exit status of remctl-shell
will be the exit status of the command. Only one command can be run per ssh
connection, so this will be noticeably slower for each command execution than
a well-designed remctl client and server design that holds connections open
for multiple commands.
is designed to mimic the behavior of remctld
the same configuration syntax and environment variables. See
"CONFIGURATION FILE" in remctld
(8) for configuration
information and ENVIRONMENT below for more specific details about environment
variable handling. The location of the configuration file may be specified
with the -f
option. The default location is
is designed to be run by a potentially untrusted user
as a shell, normally all error messages and logging is done via syslog and not
sent to standard error. See the -S
, and -q
when running it manually to debug problems. (When running manually, you will
also normally need to set the SSH_CONNECTION environment variable and either
REMCTL_USER or SSH_ORIGINAL_COMMAND depending on how you invoke it.)
The ssh protocol is much less sophisticated than remctl at passing command
arguments from the client to the server, so remctl-shell
careful attention to command arguments and quoting. ssh does no quoting of
arguments, just adds a single space between each argument and passes them
verbatim to the shell on the server side. This means the client has to add
quoting to any arguments containing whitespace. remctl-shell
single and double quotes, and supports using backslash to escape any character
inside or outside either quotes. However, be aware, when running ssh from the
command line, that your shell will remove another level of quoting. You will
therefore usually have to double-quote arguments.
For example, to run the command "log message" with argument "this
is a message" via ssh from the command line, use:
ssh firstname.lastname@example.org log message "'this is a message'"
The first level of "" quoting will be removed by your local shell, and
will interpret the second level of '' quotes. Note that,
because of how ssh does command argument passing, this is exactly equivalent
ssh email@example.com "log message 'this is a message'"
since ssh doesn't preserve the distinction between separate arguments when
creating the command to send to the remote server. It may be less confusing to
get in the habit of quoting the entire command.
Also be aware that the full command is passed via command line arguments, which
means, when invoking remctl-shell
as a shell, there is a tight limit on
the length of the whole command plus arguments. Expect to have problems if the
total command length exceeds 1000 characters. For the same reason, binary data
including nul characters cannot be passed via remctl-shell
. Invoking it
as a forced command may work around these limitations by putting the command
into the environment instead, but there may still be restrictions on that.
(The regular remctl protocol supports arbitrary-length arguments, limited only
by server-side configuration and available server memory, and supports
arbitrary binary data in arguments.)
is intended for use via ssh using
"authorized_keys" to manage authentication. (If you have Kerberos
available, it's generally better to use the normal remctld
native remctl protocol.)
There are two ways to set up remctl-shell
: either by specifying forced
commands, or by configuring remctl-shell
as the shell of the account.
The forced command approach is recommended, since it doesn't require setting a
Using forced commands
For the role account that you want to use to run remctl commands
("remctl" by convention), create an authorized_keys
listing everyone who should be able to run commands. Before each key, set the
"command" option like the below:
where the argument to remctl-shell
is the identity matching the ssh key
on that line. A more complete example of a line in authorized_keys
no-X11-forwarding ssh-rsa AAAAB3NzaC1yc2EA... \
Backslashes and line breaks were added for clarity. The actual entry should be a
single long line. For more information on the other settings here, see
Using a shell
When running remctl-shell
as the shell of the account, instead of using
forced commands, the authorized_keys
configuration must be set up to
associate each key with an identity by setting the REMCTL_USER environment
variable. Using user identities that look like Kerberos principal names is
strongly recommended, since it may make it easier to use some of the ACL
methods intended for the normal remctl server.
Since this relies on setting environment variables via
"authorized_keys", you unfortunately have to enable
"PermitUserEnvironment" in sshd_config
(this is not the
default) by adding:
will not make use of forwarded connections or agents, and
will not pass them along to the processes they run, so all such ssh options
should normally be disabled for defense in depth security.
Here is a recommended line in "authorized_keys" for the account
managed by remctl-shell
, with appropriate restrictions and an example
of how to set the REMCTL_USER variable. Backslashes and line breaks were added
for clarity. The actual entry should be a single long line.
no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa \
Setting "no-user-rc" is particularly important for
. If you have OpenSSH 7.2 or later, which added the
"restrict" keyword, you can instead use the much simpler:
environment="REMCTL_USER=example@EXAMPLE.ORG",restrict ssh-rsa \
REMCTL_USER should be set to the identity string for the owner of that key pair,
as used in the ACLs in your remctl configuration.
is normally only run with either the -c
with a user, since it's intended for use as a shell or forced command.
However, it does support some other options for testing, which may be useful
. If using it as a shell, one can use a small wrapper
program as the configured shell that passes additional options into
The start of each option description is annotated with the version of
in which that option was added with its current meaning.
- -c command
- [3.12] The command to run. This is how ssh passes the
command string into remctl-shell. remctl-shell will then
parse it into separate arguments using an algorithm similar to that used
by a shell. See the above discussion of quoting for more information.
This is mandatory when using remctl-shell as a shell. If using it as
a forced command, pass the user on the command line instead and do not use
- [3.12] Enable verbose debug logging to syslog (or to
standard output if -S is also given).
- -f config
- [3.12] The configuration file for remctld,
overriding the default path.
- [3.12] Show a brief usage message and then exit. This usage
method will include a list of supported ACL types and can be used to
determine if optional ACL methods were compiled into a given
- [3.12] Suppress the normal informational logging of what
commands are being executed and by whom. This is intended primarily to
avoid spamming syslog during testing.
- [3.12] Rather than logging to syslog, log debug and routine
connection messages to standard output and error messages to standard
error. In normal usage, this would send all the logging back to the
client, intermixed with program output, so it's normally useful only for
testing and debugging.
- [3.12] Print the version of remctl-shell and
itself requires the following environment variables be set
when it is invoked, or it exits with an error and doesn't do anything.
- The user used for logging and to make authorization
decisions, unless that was passed on the command line. The security of all
remctl-shell authorization checks is based on the accuracy of this
environment variable, so be sure that it is set correctly. The best way to
do this is via "environment" stanzas in authorized_keys
as described above. If the user is passed on the command line, this is
- sshd uses this environment variable to communication
information about the local and remote IP addresses and ports of the ssh
connection. remctl-shell expects the first space-separated token in
this environment variable to be the IP address of the client. It then uses
that to set REMOTE_ADDR in the environment of any commands it runs.
- When run as a forced command, the command run by the user
is taken from this environment variable, which is set by sshd.
The following environment variables will be set for any commands run via
(annotated with the version at which they were added).
These are mostly the same as those set by remctld
. Differences are
noted in each description.
- [3.12] The command string that caused this command to be
run. This variable will contain only the command, not the subcommand or
any additional arguments (which are passed as command arguments).
- [3.12] The IP address of the remote host. This may be IPv4
or IPv6. This is taken from the SSH_CONNECTION environment variable.
- [3.12] Normally, this communicates the time (in seconds
since UNIX epoch) when the authenticated remote session will expire.
However, this is not a meaningful concept for ssh authentication via
public key, and regardless is not communicated by sshd to the
shell. It is therefore always set to 0 by remctl-shell.
- [3.12] The hostname of the remote host, if it was
available. If reverse name resolution failed, this environment variable
will not be set.
This is determined via a simple reverse DNS lookup and should be considered
under the control of the client. remctl commands should treat it with
skepticism and not use it for anything other than logging purposes.
- [3.12] Set to the value of REMCTL_CLIENT as set in the
environment of remctl-shell. This should be set security via
authorized_keys as discussed above.
Note that REMOTE_HOST is not set by remctl-shell
, at least currently.
will either be run as a forced command or set as
the shell for a dedicated user, normally "remctl", via the normal
mechanism for local account creation. That account should be configured with
an ssh authorized_keys
file as discussed above. remctl-shell
will then be invoked with:
remctl-shell -c 'command subcommand argument'
(if used as a shell) or with:
(if used as a forced command) by sshd
for each incoming connection from a
user that has a key in the authorized_keys
If you need to run a command manually for debugging, you can run the same
command as above, but it's often more useful to send errors to standard error
instead of to syslog. You can do that with:
remctl-shell -S -c 'command subcommand argument'
If you don't want to see the normal command logging, add the -q
well. You can test an alternate configuration file by specifying it with the
option. You will need to set SSH_CONNECTION and either REMCTL_USER
(if using -c
) or SSH_ORIGINAL_COMMAND (if passing the user on the
was added in the remctl 3.12 release.
The forced command mode where the user can be passed on the command line and the
command retrieved from SSH_ORIGINAL_COMMAND was added in the remctl 3.13
Most of the caveats and differences between remctl-shell
and the normal
server are from quoting and the limitations of passing
arguments via the command line. Review the section on quoting above for more
runs as a dedicated non-root user (as opposed to
often running as root like remctld
), which means that all commands will
normally run as that user and the "user" configuration option will
not work. The easiest way to run commands as other users is to have the
underlying command use sudo
or some other user switching mechanism,
which will normally require additional local configuration.
User environment setting has to be enabled in sshd
by setting the
non-default "PermitUserEnvironment" configuration option. A future
version of remctl-shell
may use forced commands with an argument
instead of a shell to avoid this.
was written by Russ Allbery <firstname.lastname@example.org>. Many
thanks to Dropbox, Inc. for providing the time to write the initial
implementation during Dropbox's annual Hack Week.
Copyright 2016 Russ Allbery <email@example.com>
Copyright 2016 Dropbox, Inc.
Copying and distribution of this file, with or without modification, are
permitted in any medium without royalty provided the copyright notice and this
notice are preserved. This file is offered as-is, without any warranty.
The current version of this program is available from its web page at