When creating reverse tunnels on recent versions of OpenSSH a remote port of 0 can be given to bind any available port:

-R [bind_address:]port:host:hostport


If the port argument is `0', the listen port will be dynamically allocated on the server and reported to the client at run time.

openssh ssh client manpage

My question is how I can (in an automated way) determine this port allocation on the server. It seems rather unhelpful that it is reported to the host running the ssh client - but not to the target, which will want to make connections to this port to access services on the client.

Two similar options I can think of are either running

# netstat -ntlp

on the server and look for suspect ports bound on by sshd or by looking at the output of

# lsof -p $PPID | grep TCP | grep LISTEN

But neither of these is pleasant from an automation point of view, and there isn't any way of tying the dynamic ports back to the origin service port if more than one such tunnel is created.

Is there anything I'm missing to effectively get a list of active tunnels (both local and remote port numbers) on the sshd server side, like an equivalent to the SSH_CONNECTION environment variable, but for active tunnels?

For some context, I'm trying to create potentially very many simultaneous reverse tunnels to a host, tunnelling back to the same port number on many different hosts. Having the TCP stack automatically manage the port pool seems like the most effective way of doing this.

  • When using the "-R 0:x.x.x.x:y" syntax, ssh will output "Allocated port 49488 for remote forward to x.x.x.x:y on stderr.
    – BlakBat
    Jun 12 '12 at 15:31
  • Yes, the issue is how to get that information to the server side - where it would be a lot more helpful... Aug 15 '12 at 13:09

If you set the 'LogLevel' in the sshd_config configuration file to DEBUG1 (or any DEBUG level), then sshd will log the port numbers in /var/log/auth.log.

Do remember, that using a LogLevel of DEBUG or higher could be a privacy risk, since much is logged.

(from /var/log/auth.log, removed a few lines to show relevant information)

Jun 24 06:18:24 radon sshd[9334]: Connection from port 39193
Jun 24 06:18:24 radon sshd[9334]: Accepted publickey for lornix from port 39193 ssh2
Jun 24 06:18:24 radon sshd[9334]: pam_unix(sshd:session): session opened for user lornix by (uid=0)
Jun 24 06:18:24 radon sshd[9334]: User child is on pid 9339
Jun 24 06:18:24 radon sshd[9339]: debug1: Local forwarding listening on port 0.
Jun 24 06:18:24 radon sshd[9339]: debug1: Allocated listen port 39813
Jun 24 06:18:24 radon sshd[9339]: debug1: channel 0: new [port listener]
Jun 24 06:18:24 radon sshd[9339]: debug1: Local forwarding listening on :: port 39813.
Jun 24 06:18:24 radon sshd[9339]: debug1: channel 1: new [port listener]
Jun 24 06:18:27 radon sshd[9339]: Received disconnect from 11: disconnected by user

If you follow it through, you can see where you could parse the connection information, and then the forwarded port (39813 in this case)

I used this command line between two of my machines, I do have ssh-key login set up, so no password prompts or delays

-xenon- lornix:~> ssh -R "*:0:radon:22" -N -T radon
Allocated port 39813 for remote forward to radon:22

-N specifies no command is given, and -T stops allocation of a tty for this connection.

Another way to disseminate the port connection information would be to parse it from the client side and send an email, jabber, text msg, smoke signals or pigeon to carry the port # to whomever needs it.


You could pipe the stderr of ssh into a program which opens up a connection to a server on the target machine and reports its machine name / IP address / serial number / whatever along with the port number. Kind of like this:

% ssh -R "*:0:radon:22" -N -T radon 2>&1 | sed "s/^/`uname -n` /" | netcat radon 3743

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.