Home » Questions » Computers [ Ask a new question ]

An SSH tunnel via multiple hops

An SSH tunnel via multiple hops

Tunneling data over SSH is pretty straight-forward:

Asked by: Guest | Views: 208
Total answers/comments: 5
Guest [Entry]

"You basically have three possibilities:

Tunnel from localhost to host1:

ssh -L 9999:host2:1234 -N host1

As noted above, the connection from host1 to host2 will not be secured.
Tunnel from localhost to host1 and from host1 to host2:

ssh -L 9999:localhost:9999 host1 ssh -L 9999:localhost:1234 -N host2

This will open a tunnel from localhost to host1 and another tunnel from host1 to host2. However the port 9999 to host2:1234 can be used by anyone on host1. This may or may not be a problem.
Tunnel from localhost to host1 and from localhost to host2:

ssh -L 9998:host2:22 -N host1
ssh -L 9999:localhost:1234 -N -p 9998 localhost

This will open a tunnel from localhost to host1 through which the SSH service on host2 can be used. Then a second tunnel is opened from localhost to host2 through the first tunnel.

Normally, I'd go with option 1. If the connection from host1 to host2 needs to be secured, go with option 2. Option 3 is mainly useful to access a service on host2 that is only reachable from host2 itself."
Guest [Entry]

"OpenSSH v7.3 onward supports a -J switch and a ProxyJump option, which allow one or more comma-separated jump hosts, so, you can simply do this now:

ssh -J jumpuser1@jumphost1,jumpuser2@jumphost2,...,jumpuserN@jumphostN user@host"
Guest [Entry]

"I did what I think you wanted to do with

ssh -D 9999 -J host1 host2

I'm prompted for both passwords, then I can use localhost:9999 for a SOCKS proxy to host2. It's the nearest I can think of to the example you showed in the first place."
Guest [Entry]

"This answer is similar to kynan, as it involves the use of ProxyCommand. But it's more convenient to use IMO.

If you have netcat installed in your hop machines you can add this snippet to your ~/.ssh/config:

Host *+*
ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /') nc $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /')

Then

ssh -D9999 host1+host2 -l username

will do what you asked.

I came here looking for the original place where I read this trick. I'll post a link when I find it."
Guest [Entry]

"My answer is really the same as all the other answers here, but, I wanted to clarify the usefulness of ~/.ssh/config and ProxyJump.

Let say I need to get to a destination in 3 hops, and, for each hop, I needed a specific username, host, port and identity. Because of the identity criteria, this can only be done with the ~/.ssh/config config file:

Host hop1
User user1
HostName host1
Port 22
IdentityFile ~/.ssh/pem/identity1.pem

Host hop2
User user2
HostName host2
Port 22
IdentityFile ~/.ssh/pem/identity2.pem
ProxyJump hop1

Host hop3
User user3
HostName host3
Port 22
IdentityFile ~/.ssh/pem/identity3.pem
ProxyJump hop2

From your computer, you can test each jump individually, i.e.

[yourpc] $ ssh hop1 # will go from your PC to host1 in a single step
[host1] $ exit
[yourpc] $ ssh hop2 # will go from your PC to host2 via host1 (i.e. two steps)
[host2] $ exit
[yourpc] $ ssh hop3 # will go from your PC to host3 via host1 and host2 (i.e. three steps)
[host3] $ exit
[yourpc] $

Another cool thing about the ~/.ssh/config file is that this will also enable sftp file transfers via any series of hops, e.g.

[yourpc] $ sftp hop1 # for file transfers between your PC and host1
Connected to hop1.
sftp> quit
[yourpc] $ sftp hop2 # for file transfers between your PC and host2
Connected to hop2.
sftp> quit
[yourpc] $ sftp hop3 # for file transfers between your PC and host3
Connected to hop3.
sftp> quit"