We have a public server which accepts SSH connections from multiple clients behind firewalls.

Each of these clients create a Reverse SSH tunnel by using the ssh -R command from their web servers at port 80 to our public server.

The destination port(at the client side) of the Reverse SSH Tunnel is 80 and the source port(at public server side) depends on the user. We are planning on maintaining a map of port addresses for each user.

For example, client A would tunnel their web server at port 80 to our port 8000; client B from 80 to 8001; client C from 80 to 8002.

Client A: ssh -R 8000:internal.webserver:80 clienta@publicserver

Client B: ssh -R 8001:internal.webserver:80 clientb@publicserver

Client C: ssh -R 8002:internal.webserver:80 clientc@publicserver

Basically, what we are trying to do is bind each user with a port and not allow them to tunnel to any other ports.

If we were using the forward tunneling feature of SSH with ssh -L, we could permit which port to be tunneled by using the permitopen=host:port configuration. However, there is no equivalent for reverse SSH tunnel.

Is there a way of restricting reverse tunneling ports per user?

  • 1
    Only by system-wide policy like SELinux or IPTABLES. – Andrew Smith Jun 29 '12 at 21:58

Since you've placed not allow in bold, I assume you want some kind of run-time rejection at the SSH client side that prevents the port bind. So, I've had a dig of the source code for you:


/* check permissions */
if (!options.allow_tcp_forwarding ||
    no_port_forwarding_flag ||
    (!want_reply && listen_port == 0)
    || (listen_port != 0 && listen_port < IPPORT_RESERVED &&
    pw->pw_uid != 0)
    ) {
        success = 0;
        packet_send_debug("Server has disabled port forwarding.");
} else {
        /* Start listening on the port */
        success = channel_setup_remote_fwd_listener(
            listen_address, listen_port,
            &allocated_listen_port, options.gateway_ports);

Unfortunately, as you can see, there aren't many conditions that appear to prevent port forwarding aside from the standard ones.

I was about to recommend the same suggestion for using mod_owner within iptables, but Jeff has beaten me to it.

Your cleanest solution would just to modify this file (for example, you can use pw->pw_uid to get the uid of the user connecting, and map that to the correct port) and recompile your SSH server, but that would depend on how comfortable you are with this.

  • This is really good. I can actually copy the same syntax from -L option (tunneling) and make it work. Thank you. – Utku Zihnioglu Jul 2 '12 at 0:15

My suggestion is using SELinux for this. You'll have to configure user profiles that allow which ports to be open. The sshd process forks and drops to the user's privileges before opening a port to forward, so anything applied to the user's processes will be enforced on sshd. Be mindful that you'll need to restrict to all user processes since once could use netcat to forward another port. I'll try to sort out proper syntax for you later (or any other user is welcome to edit it in for me).

Alternatively, you could try using iptables.

iptables -m owner --add-owner $user -p tcp --sport 8000 -j ACCEPT
iptables -m owner --add-owner $user -p tcp --tcp-flags SYN,ACK SYN,ACK -j REJECT

That won't prevent them from opening the port and denying another user, however.

  • Thanks for the great answer. I will try the SELinux/User profiles configuration. It sounds like the solution to my question. – Utku Zihnioglu Jul 2 '12 at 0:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.