Why with ssh -R is possible to allocate a free port by specifying '0' while with ssh -L you need to specify a valid free port?

I want ssh to use a local free port to FWD remote traffic without depending on free ports hacks

From manual pages

-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.

But -L doesn't provide that possibility :(

-L [bind_address:]port:host:hostport

Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side.....


SSH will bind to the L-specified port and listen on it for arbitrary clients initiating connections (and for packets on the conections already established, forwarding them to the remote servers, but that's not relevant in the context of this question).

In order to initiate a connection the client must specify the port number on which the server is listening for such requests. If such port is arbitrarily selected then the client doesn't know it and thus cannot initiate the connection.

For -R that is not an issue as the remote server will not accept any connection on that port other than the one from the local server (which knows the port number from the -R argument).

After the initial connection is established additional dynamically assigned ports can be negotiated (thus known) by both the client and the server for the actual traffic.

  • Both the -L and -R ports are listening so your reply doesn't really make sense does it? – pedz Apr 23 '17 at 17:37
  • @pedz A local process will never listen to a remote machine port... – Dan Cornilescu Apr 24 '17 at 2:27
  • With the -R, the remote side does the listen. That is the difference between -R and -L. -L the local side listens. -R the remote side listens. In both cases, the port (if the options allowed it) could be specified or allowed to pick a ephermeral port. – pedz May 6 '17 at 13:10
  • Ah, I see what you mean - yes, technically they all listen for packets. I'll update the answer. – Dan Cornilescu May 6 '17 at 13:41

Because OpenSSH has not decided to implement this. Maybe it's time for a feature request. Not sure quite how it would make the port number accessible to other programs though... maybe write to some file?

However, this should be easy enough to do yourself with some coding.

Pseudo code:

  1. Pick random number [1000-65535]: export LOCAL=$(( $RANDOM + 1000 )) (good enough)
  2. Try to connect with ssh some.host -L $LOCAL:dest.host:1234
  3. On failure, repeat.
  4. Use $LOCAL to get the random port that was used.

Unfortunately, this is difficult to implement nicely in bash or I'd give a more complete example here.

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.