How to create a restricted SSH user for port forwarding?

22 Jun 2011  Posted under: linux, , security

This is a repost of a very helpful article on askubuntu.com, written by Lekensteyn on June 22nd, 2011.

I am reposting it so that it doesn’t disappear on me!


Adding a restricted user consists of two parts: 1. Creating the user 2. Configuring the SSH daemon (sshd)

Configuring sshd

The best place to get known to the possibilities of SSH is by reading the related manual pages:

Where can SSH client perform actions?

Before you can restrict something, you need to know the features of SSH. Spitting through the manual pages yields:

From the Authentication section of the manual page of sshd(8):

If the client successfully authenticates itself, a dialog for preparing the session is entered. At this time the client may request things like allocating a pseudo-tty, forwarding X11 connections, forwarding TCP connections, or forwarding the authentication agent connection over the secure channel.

After this, the client either requests a shell or execution of a command. The sides then enter session mode. In this mode, either side may send data at any time, and such data is forwarded to/from the shell or command on the server side, and the user terminal in the client side.

Options for restricting SSH features

Files and their options that alter behavior are:

Applying the restrictions

Modifying the system-wide configuration file /etc/ssh/sshd_config allows the configuration be applied even if password-based authentication is applied or if the restrictions in ~/.ssh/authorized_keys are accidentally removed. If you’ve modified the global defaults, you should uncomment the options accordingly.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

Now add a user:

sudo useradd -m limited-user

The option ForceCommand can be omitted if the shell is set to a non-shell like /bin/false (or /bin/true) as /bin/false -c [command] won’t do anything.

Now the client can only connect to port 62222 on the loopback address of the server over SSH (it will not listen on the public IP address)

Disabling AllowTcpForwarding would also disallow the use of -R, thus defeating the use of such a restricted account for forwarding a single port. PermitOpen localhost:62222 assumes that port 62222 on the server is never in use because the client can happily connect to it and listen on it too.

If TCP forwarding is allowed in the system-wide configuration and disabled password-based authentication, you can use per-key settings as well. Edit ~/.ssh/authorized_keys and add the next options before the ssh- (with a space between the options and ssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

Verify

To be sure that it works as expected, some test cases need to be run. In the below commands, host should be replaced by the actual login if it’s not set in ~/.ssh/config. Behind the command, a command is shown that should be executed on either the client or server (as specified).

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

Conclusion

Checklist: The SSH user should not able to: