How to restrict an SSH user to only allow SSH-tunneling?

On the server side, you can restrict this by setting their user shell to /bin/true. This will allow them to authenticate, but not actually run anything since they don't get a shell to run it in. This means they will be limited to whatever subset of things SSH is able to offer them. If it offers port forwarding, they will still be able to do that.

On the client side, you will probably want to connect with the -N. This stops the client from ASKING for a remote command such as a shell, it just stops after the authentication part is done. Thanks to commentors for pointhing this out.


The following has the advantage that X11 and SSH agent socket forwardings are also disallowed, which might still be allowed in Calebs way. Another advantage is, that if the user is able to change his default shell through any other way, this will still restrict his SSH access to only TCP forwardings.

Put the following into your /etc/ssh/sshd_config:

Match User that-restricted-guy
  AllowTcpForwarding yes
  X11Forwarding no
  AllowAgentForwarding no
  ForceCommand /bin/false

to allow the user that-restricted-guy to forward any TCP connections through your SSH enabled machine (connection to this machine, also to localhost and even connection from this machine to other machines).

If you want it even more restrictive (which is a good idea) you can also do the following:

Match User even-more-restricted-guy
  PermitOpen 127.0.0.1:12345
  X11Forwarding no
  AllowAgentForwarding no
  ForceCommand /bin/false

This will allow the user even-more-restricted-guy to only ever forward connections to 127.0.0.1 TCP port 12345 (as it is visible through your SSH enabled machine).

When the user normally connects he will now be instantly disconnected because the /bin/false command will be triggered which does nothing but instantly exit with a code of 1. If you want to avoid this and keep your forwarding connection open, add the -N flag to the ssh command. This will not try to execute any command but still allows to setup TCP forwardings.

An example of a forward command that should work in the latter setup:

ssh -L 12345:127.0.0.1:12345 -N even-more-restricted-guy@insert-your-machine

You can control what people can do in ssh by matching groups assuming your version of ssh is new enough to support it (openssh 5.x+).

Basically, we treat them as if they were sftp users, but allow tcp forwarding and optionally specify the destinations they may forward to. If you give them a home directory but don't create any directories under it, they can't transfer any files because they will not have permission to do so.

Match Group                     nicepeople
    PubkeyAuthentication        yes
    PasswordAuthentication      yes
    PermitEmptyPasswords        no
    GatewayPorts                no
    ChrootDirectory             /opt/dummy_location/%u
    ForceCommand                internal-sftp
    AllowTcpForwarding          yes
        PermitOpen              192.168.0.8:22
        PermitOpen              192.168.0.5:8080
    # Or leave out the PermitOpen to allow forwarding to anywhere.
    HostbasedAuthentication     no
    RhostsRSAAuthentication     no
    AllowAgentForwarding        no
    Banner                      none

You can repeat these Match Group blocks for each group that you wish to provide different behavior or restrictions.

You can further control where this person can go on the network using iptables

/sbin/iptables -I OUTPUT -m owner --gid-owner 500 -j REJECT
/sbin/iptables -I OUTPUT -m owner --gid-owner 500 -m tcp -p tcp -d 192.168.0.0/24 -j ACCEPT

This assumes the group "nicepeople" GID is 500.

Some of the above ssh options are available in the older versions of openssh, but not within the Match Group section. Match Group is very limited in OpenSSH 4.x and earlier.