NB: The OpenSSH clients I am using are all at version 7.2, so no RemoteCommand
available.
Assume the following setting:
- machine
foo
is a jump host and provides access to hostbar
via itslocalhost:10022
bar
sits inside a network inside of which we can access hostrdp
and access its RDP port (3389). I actually give the IP ofrdp
inside my command lines and configuration, but I presume that it is legit to use its name as long as name lookup works. For brevity I am usingrdp
here.
The goal is now to gain access to rdp:3389
by connecting to bar
via jump host foo
and forward that to localhost:33389
on the local machine from which I am invoking ssh bar
.
[local:33389] --> {foo} --> {bar} --> [rdp:3389]
Interlude
I have solved this previously with PuTTY as follows:
- create a connection to
foo
and configure a local forwarding-L 33389:localhost:33389
, thus tyinglocalhost:33389
on the local machine tolocalhost:33389
onfoo
. - use the following remote command to carry the port forwarding into the network inside of which
bar
sits by passingssh -L 33389:rdp:3389 -A bar
. Host bar
is configured onfoo
inside of.ssh/config
to connect tolocalhost:10022
and thereby end up onbar
via the jump host.
The PuTTY configuration works like a charm, but it relies on a remote command to be executed. While a shell alias would be one way of going about this, I was wondering if there's a way to keep everything inside the ssh_config(5)
used by my client, using ProxyCommand
?
A rough equivalent of the above PuTTY configuration is this:
ssh -L 33389:localhost:33389 foo ssh -t -L 33389:rdp:3389 -p 10022 localhost
or, provided that Host bar
is configured on foo
to go through localhost:10022
of foo
:
ssh -L 33389:localhost:33389 foo ssh -t -L 33389:rdp:3389 bar
And this seems to get the job done.
But of course this is plenty to type and it would be neater to be able to put this all into the configuration file and simply type ssh bar
on the local machine.
With RemoteCommand
as introduced in OpenSSH 7.6 this seems to be rather trivial:
Host bar
HostName foo
RemoteCommand ssh -L 33389:rdp:3389 -A -p 10022 localhost
LocalForward 33389 localhost:33389
… which should roughly translate to the ssh
invocation shown above. But as mentioned before, I am using an older (packaged) version of OpenSSH without support for the RemoteCommand
stanza.
Here's the attempt that seems to come closest to what I want to achieve.
Host bar
HostName localhost
Port 10022
ProxyCommand ssh -L 33389:localhost:33389 -W %h:%p foo
LocalForward 33389 rdp:3389
The idea being that on the local machine I will simply invoke ssh bar
. In fact it works in that I end up on the shell prompt of bar
, but the port forwarding doesn't work at all. While sudo lsof -i|grep 3389
on the local machine gives me:
ssh 15271 accden 6u IPv6 7933201 0t0 TCP localhost:33389 (LISTEN)
ssh 15271 accden 7u IPv4 7933202 0t0 TCP localhost:33389 (LISTEN)
On the jump host I see nothing listening on any port containing 3389
.
Since ProxyCommand
establishes the connection to foo
and I am giving a LocalForward
for the connection to bar
, I'd expect this to work.
What am I doing wrong?
Goal is to use ssh bar
to connect to bar
and at the same time make rdp:3389
available on the local machine as localhost:33389
. Tweaking the ssh_config(5)
files on the local machine and foo
are allowed. Passing remote commands is not a valid answer, though.
Best Answer
First, with your kind of setting, what would work, requiring anyway two ssh:
What you'd really need wouldn't be RemoteCommand but ProxyJump, really simplifying your configuration, with goal reached only with:
Or the equivalent (only) configuration:
With zero intermediate port needed.
Unfortunately ProxyJump is available only starting from openssh 7.3
But it's easily replaced with the
ProxyCommand
/-W
combo you were using before.or as configuration file:
There are still two ssh running: the hidden one is the one as
ProxyCommand
parameter still running on the local host doing the link using a pair of pipes with the main ssh, instead of an extra tcp port. Trying to involve the intermediate host in participating with the port forwarding is insecure or can clash (other users of foo can access the tunnel or use the same port), and prone to errors. Tunnel ends should always be kept on the client host if possible, where there's full control. Intermediate tunnels should either not exist or point to the next ssh entry point (that's the-W
's usage here).