I have 2 servers as ubuntu@example1.com and ubuntu@example2.com, I want to connect to ubuntu@example2.com but I cannot connect to it directly due to restrictions, I have to first connect to ubuntu@example1.com and then I have to connect to example2.com from example1.com.

Now in my local I want to connect my application to remote psql server which is on ubuntu@example2.com:5432. For this I have to do following steps.

  1. SSH into example1.com

    ssh ubuntu@example1.com
  2. Now from example1, After ssh, go inside example1.com and then forward port 5432 from example2 to 5434 of example1 by entering following in example1.com:

    ssh -L 5434:localhost:5432 ubuntu@example2.com
  3. Now from my local, in another terminal tab, I have to type following command to forward port 5434 of example1.com (which is coming from 5432 of example2) to my local 5432.

    ssh -L 5432:localhost:5434 ubuntu@example1.com

Now finally in my local, my application can connect to localhost with port 5432, as if psql is running locally.

I want to make this whole into a single command so that I can do it in just one step and also stop it in one step, rather than doing the above 3 steps because again and again I have to type so much, I am willing to create a executable file (like a shell script) as well.

So far I tried doing this:

ssh -L 5432:localhost:5434 ubuntu@example1.com ssh -L 5434:localhost:5542 -N ubuntu@example2.com

This is exactly the solution I want, it works like a charm, IT WORKS, but , there is a BUT now. And that but is, when I do CTRL + C, it kills my local ssh connection for 5434 of example1 to my local 5432, but it does not kill the connection between example2.com and example1.com , due to this when I run the above command again it gives me this error:

bind: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 5434

And then I have to change port again, and then again it hangs there, and when I do CTRL+C again it would block that port,

So what I need?

So I need another way of port forwarding or I need a way to kill the connection between example1.com and example2.com, I just need one step (single line) to start and 1 step to stop (single line).

So far I have been killing these connections by doing ps -aux | grep 5434 from inside of example1.com and the killing it using kill command.

My local SSH config (~/.ssh/config)

Host *.*.*.*
   StrictHostKeyChecking no

Host *
        ServerAliveInterval 50
        ServerAliveCountMax 10
        ForwardAgent yes

Edit #1:

ssh -J ubuntu@example1.com ssh -L 5432:localhost:5432 -N ubuntu@example2.com

Tried the above command but I am getting this error:

open failed: administratively prohibited: open failed
stdio forwarding failed
ssh_exchange_identification: Connection closed by remote host

Probably this has something to do with example2 being a private IP, only example1 is a public IP (not sure if this is the problem).

  • "Probably this has something to do with example2 being a private IP, only example1 is a public IP" – Irrelevant. The mechanism of -J resolves the target host on the last (in your case the only) jump host. The target host may not be reachable from your local computer, it doesn't matter. – Kamil Maciorowski Aug 28 at 16:22

The problem is ssh running on example1.com survives.

Simplify the whole setup. An elegant way is to use ssh -J:

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

ssh -J ubuntu@example1.com ssh -L 5432:localhost:5432 -N ubuntu@example2.com

This is not equivalent to connecting from your local computer to example1.com and then from example1.com to example2.com. It's equivalent to connecting from your local computer to example1.com and then from your local to example2.com (using packets forwarded through example1.com). No SSH client is invoked on example1.com. This means:

  • The credentials for example2.com must come from your local computer, not from example1.com. If the restrictions you mentioned mean the credentials come from example1.com and you cannot change this, then this approach cannot be used.

  • Neither /etc/ssh/ssh_config nor ~/.ssh/config from example1.com matters. Configure the access to example2.com in your local config. Note you can specify ProxyJump in the config:

    Host example2.com
         ProxyJump example1.com

    If you do this, you will no longer need -J when connecting to example2.com:

    ssh -L 5432:localhost:5432 -N ubuntu@example2.com

In case of administratively prohibited: open failed (or if you cannot or don't want to use -J/ProxyJump for whatever reason), revert to your original command (we will fix it in a moment).

administratively prohibited: open failed in your case means -J cannot establish a TCP forwarding from your local computer to example2.com via example1.com, because the administrator of example1.com disallows this. Still your original command succeeds in forwarding ports. Possibly PermitOpen localhost:* is in use. Let's fix your original command then.

Your original command is in a form:

ssh     … ubuntu@example1.com ssh …

Fix it like this:

ssh -tt … ubuntu@example1.com ssh …

The difference is -tt will force tty allocation for ssh running on ubuntu@example1.com (regardless if your local ssh has tty). Now if you terminate the local ssh then the remote ssh will receive SIGHUP:

On POSIX-compliant platforms, SIGHUP ("signal hang up") is a signal sent to a process when its controlling terminal is closed.

The ssh running on example1.com will gracefully exit upon SIGHUP. You will no longer need to kill it manually.

Your original command allocates no tty, so this useful mechanism does not apply. Adding -tt changes this.

| improve this answer | |
  • this is the best, I don't want even want to go to example2 from example1, going from my local is even better!!!! thanks for this, this is exactly what I need, I will test this and get back to you later and accept it if it works and confirm. – user1735921 Aug 28 at 13:37
  • Getting this error: channel 0: open failed: administratively prohibited: open failed stdio forwarding failed ssh_exchange_identification: Connection closed by remote host Not sure if this has something to do with, example2.com being a private IP, only example1.com is the public IP, thats why I cannot directly connect to example2.com maybe, not sure. – user1735921 Aug 28 at 13:53
  • I have added my local ssh config in the question edit as well, for your reference – user1735921 Aug 28 at 13:58
  • @user1735921 The answer now addresses the issue. – Kamil Maciorowski Aug 28 at 16:13

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.