Specifying a RemoteForward of 0:example.com:1234 dynamically allocates the listen port on the server, and then reports it to ... the client! Where it is practically useless. Was this someone's idea of a joke? Presumably not--there are some technical obstacles to reporting it to the remote process. I'd like to help solve that problem. The natural way to me would be to extend the syntax of RemoteForward to allow ENV_VAR:example.com:1234. This would set $ENV_VAR to the dynamically alocated port in the remote process. However, the protocol passes the listen port as a u_int. A hack might be to pack the env var name into the listen address and set the listen port to a special value to indicate this, but I don't know if this is playing too fast and loose. A cleaner solution would be to add a new request type. I imagine that ssh protocol changes are made conservatively, so I don't know how viable these options are. Without changing the protocol, we could at least set an environment variable for each dynamically allocated port, numbered by the order of the RemoteForward requests, eg. SSH_REMOTE_FORWARD_PORT_1, SSH_REMOTE_FORWARD_PORT_2, .... I was able to wedge a proof of concept into session.c:do_setup_env (patch below). It's a hack because there doesn't seem to be an API to iterate channels outside of channels.c. Would it be agreeable to export channels and channels_alloc? Also, struct Channel doesn't let you tell which forwards were dynamically allocated, so an environment variable is set for all RemoteForwards. This could be changed by extending struct Channel, though it isn't a show-stopper for me. Last thought: if a new protocol request type were added, it should make it easy to add support for forwarding unix sockets, which I have missed for a long time. Would any of these approaches be acceptable? Any other ideas? Thanks, Andrew --- session.c.orig 2013-08-03 13:22:10.354171156 -0700 +++ session.c 2013-08-05 09:58:00.017397667 -0700 @@ -1307,6 +1307,17 @@ child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, auth_sock_name); + char name[256]; + u_int n = 0; + for (i = 0; i < 100; i++) { + Channel *c = channel_by_id(i); + if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) + continue; + snprintf(name, sizeof name, "SSH_REMOTE_FORWARD_PORT_%d", n); + snprintf(buf, sizeof buf, "%d", c->listening_port); + child_set_env(&env, &envsize, name, buf); + } + /* read $HOME/.ssh/environment. */ if (options.permit_user_env && !options.use_login) { snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
On 5 Aug 2013, at 20:04, Andrew Pimlott wrote:> Specifying a RemoteForward of 0:example.com:1234 dynamically allocates > the listen port on the server, and then reports it to ... the client! > Where it is practically useless. Was this someone's idea of a joke?Yes this is not great; I've wanted this too. One problem with your approach is that the child may already be running by the time the remote forward is processed; that could be ten minutes after the session start. -- Alex Bligh
see http://www.openssh.com/txt/release-5.6 * ssh(1) connection multiplexing now supports remote forwarding with dynamic port allocation and can report the allocated port back to the user: LPORT=`ssh -S muxsocket -R0:localhost:25 -O forward somehost` -m Am 05.08.2013 um 21:04 schrieb Andrew Pimlott <andrew at pimlott.net>:> Specifying a RemoteForward of 0:example.com:1234 dynamically allocates > the listen port on the server, and then reports it to ... the client! > Where it is practically useless. Was this someone's idea of a joke? > > Presumably not--there are some technical obstacles to reporting it to > the remote process. I'd like to help solve that problem. > > The natural way to me would be to extend the syntax of RemoteForward to > allow ENV_VAR:example.com:1234. This would set $ENV_VAR to the > dynamically alocated port in the remote process. However, the protocol > passes the listen port as a u_int. A hack might be to pack the env var > name into the listen address and set the listen port to a special value > to indicate this, but I don't know if this is playing too fast and > loose. A cleaner solution would be to add a new request type. I > imagine that ssh protocol changes are made conservatively, so I don't > know how viable these options are. > > Without changing the protocol, we could at least set an environment > variable for each dynamically allocated port, numbered by the order of > the RemoteForward requests, eg. SSH_REMOTE_FORWARD_PORT_1, > SSH_REMOTE_FORWARD_PORT_2, .... I was able to wedge a proof of concept > into session.c:do_setup_env (patch below). It's a hack because there > doesn't seem to be an API to iterate channels outside of channels.c. > Would it be agreeable to export channels and channels_alloc? Also, > struct Channel doesn't let you tell which forwards were dynamically > allocated, so an environment variable is set for all RemoteForwards. > This could be changed by extending struct Channel, though it isn't a > show-stopper for me. > > Last thought: if a new protocol request type were added, it should make > it easy to add support for forwarding unix sockets, which I have missed > for a long time. > > Would any of these approaches be acceptable? Any other ideas? > > Thanks, > Andrew > > --- session.c.orig 2013-08-03 13:22:10.354171156 -0700 > +++ session.c 2013-08-05 09:58:00.017397667 -0700 > @@ -1307,6 +1307,17 @@ > child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, > auth_sock_name); > > + char name[256]; > + u_int n = 0; > + for (i = 0; i < 100; i++) { > + Channel *c = channel_by_id(i); > + if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) > + continue; > + snprintf(name, sizeof name, "SSH_REMOTE_FORWARD_PORT_%d", n); > + snprintf(buf, sizeof buf, "%d", c->listening_port); > + child_set_env(&env, &envsize, name, buf); > + } > + > /* read $HOME/.ssh/environment. */ > if (options.permit_user_env && !options.use_login) { > snprintf(buf, sizeof buf, "%.200s/.ssh/environment", > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev