SSH Tunnel from Windows through Linux to Windows

Solution 1:

Preliminary notes

  • I don't use Windows but hopefully it won't matter much.
  • Often when I say "A", "B", "C", I really mean "the user on A", "user1 on B", "user2 on C" respectively. E.g. "the B's key" means "user1's key available on B". This is for brevity.

Analysis

This is how -J works:

-J destination
Connect to the target host by first making a ssh connection to the jump host described by destination and then establishing a TCP forwarding to the ultimate destination from there.

This means ssh -J user1@B user2@C is not equivalent to connecting from A to B and then from B to C. It's equivalent to connecting from A to B and then from A to C (using packets forwarded through B). No SSH client is invoked on B, so the key that allows you to connect from B to C is never used.


Solution

The most elegant way to solve the general problem is to make C accept the (or an) A's key. You said:

It works if I use the same key pair on all three hosts, but I would like to use different users with different key pairs because of security reasons.

You can use different pairs. I understand there's currently a key pair that allows you to connect from A to B and a separate pair that allows B to C. The latter is irrelevant. On C authorize any key A uses to authenticate. It may be the old key (the one already authorized on B); but it may be a new key created exclusively for this connection.

Then, when you do ssh -J user1@B user2@C on A, you need to use the key that allows A to connect to B and the key that allows A to connect to C. If they are different keys, you need to use them both. Use -i once or even twice if needed.


Alternative solution

You can use the already registered keys if you actually connect from B to C after connecting from A to B. If you wanted to log in from A to C, then it would be like:

# from A
ssh -t user1@B 'ssh user2@C'

(at least in Linux; I'm not sure how quoting works in Windows).

This command runs ssh on B to connect to C, so it will use the B's key.


About port forwarding

Your original command used -N and -L, so I understand the only goal is to forward a port. You forwarded the port using the A-to-C connection and the destination was also C; so the last leg for forwarded packets was from the SSH server on C to C. Maybe the [remote_port] is reachable from B. If so, then you don't need any of the above solutions; all you need is:

ssh -NL [port]:C:[remote_port] user1@B

This will make the last leg for forwarded packets be from the SSH server on B to C.

If the last leg must be from C to C, then the course of action depends on which solution you choose.

  • The solution with an A's key authorized on C will allow you to use your original command without passwords.

  • The solution with running ssh on B will require you to forward the port from A to B and separately from B to C. Something like:

    ssh -L [port]:localhost:[relay_port] user1@B 'ssh -NL [relay_port]:C:[remote_port] user2@C'