0

I use the following script to open a ssh tunnel to a bunch servers always varying between mysql, redis and ssh ports. I am doing this while being in the company vpn, but I had the same problem back in the days, when you worked in the office.

Usually I start the script and use the opened connection with other tools like SequelPro or PhpStorm to connect to webserver or databases. Ideally it would just run until I don't need it any more and then I would exit the jumpserver and the connections should close. That is fine as long as I don't loose the connection and get kicked out of the jumpserver.

#!/bin/sh

username="my-user"
jumpServer="my.bastionserver.net"
hosts=("my.awsserver1.com" "my.awsserver2.com" "my.awsserver3.com")

destMysqlPort=3306
destSshPort=22
destRedisPort=6379

x=10001
y=10002
z=10003

for i in "${hosts[@]}"; do
  :
  server=$i
  sshTunnel="$sshTunnel -L $x:$server:$destMysqlPort -L $y:$server:$destSshPort -L $y:$server:$destRedisPort"
  echo "Server: $server -- MYSQL: $x -- SSH: $y-- Redis: $z"
  x=$((x + 3))
  y=$((y + 3))
  z=$((z + 3))
done

if [ -z "$sshTunnel" ]
then
  echo "ssh tunnels are empty"
else
  ssh $sshTunnel $username@$jumpServer -i ~/.ssh/aws
fi

the output is as follows:

$ ./awstunnel.sh
Server: my.awsserver1.com -- MYSQL: 10001 -- SSH: 10002-- Redis: 10003
Server: my.awsserver1.com -- MYSQL: 10004 -- SSH: 10005-- Redis: 10006
Server: my.awsserver1.com -- MYSQL: 10007 -- SSH: 10008-- Redis: 10009
[...]

When I try to connect again via this script I get the messages that the address is already in use:

bind [127.0.0.1]:10002: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 10002
bind [127.0.0.1]:10005: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 10005
[...]

How can I change the script so that I can start it again right away and don't have to wait for quite some time until the connection via this tunnel really closes?

I work from a Mac and the jumpserver is a Linux server, where I should not change settings.

Calamity Jane
  • 2,189
  • 5
  • 36
  • 68
  • Sounds like you are actually looking for a way to reconnect to a connection when you were disconnected. Look for `tmux` or `screen` – tripleee May 09 '22 at 12:34
  • Reconnect or actively close the open connections before opening others, both would be fine. – Calamity Jane May 09 '22 at 13:40
  • I'm afraid that's not really a programming question then, but if you have `tmux` installed on the jump host, it should be like five minutes to replace your current configuration, and maybe 20 to refactor your existing script to use `tmux` to set up the connections from scratch again in the future (though the need for that should be significantly less frequent then). – tripleee May 09 '22 at 13:45
  • In very brief, `ssh -t jumphost tmux attach -t foo` to reattach to an existing session named `foo` if you lose your connection to it. – tripleee May 09 '22 at 13:46
  • Regrettably tmux doesn't exist there and I should not install software on it, since it isn't "my" jumpserver. – Calamity Jane May 09 '22 at 13:48
  • Could I add a loop at the beginning of my script, where all maybe open connections are force closed? – Calamity Jane May 09 '22 at 13:52
  • Possible duplicate of https://stackoverflow.com/questions/26505294/how-to-kill-port-forwarding-once-you-have-have-finished-using-it – tripleee May 09 '22 at 13:54
  • The answer to that one also looks promising: https://stackoverflow.com/questions/9447226/how-to-close-this-ssh-tunnel – Calamity Jane May 09 '22 at 13:57
  • If you aren't familiar with `ControlMaster`/`ControlSocket` functionality in ssh, they may be worth looking into -- openssh is perfectly capable of managing background processes for jump hosts completely on its own with no explicit scripts needing to be written for the purpose in the first place. – Charles Duffy May 09 '22 at 14:27
  • ...play your cards right, and you can avoid needing a tunnel at all, instead having a ControlMaster-managed transport and spawning a new openssh client that opens a channel on that transport whenever you want a new connection through said already-open transport. – Charles Duffy May 09 '22 at 14:29

1 Answers1

1

Just like this, a little hint:

To get the PID of the last executed command you have to type:

echo "$!"

So, what you can do is just store the PID after each ssh login command like this for example:

#Store the pid of the last command in a variable named sshPid: 
sshPid=$!

and when you are done just kill the corresponding PID with:

kill ${sshPid}

Tell me if that worked for you :p

Bguess

Bguess
  • 1,700
  • 1
  • 11
  • 24
  • The problem happens not "when I am done" In that case I exit the jumpserver connection I opened via the script and all my ssh connections are closed too. The problem happens, when I loose the connection and my shell window freezes and I cannot do anything beside closing the shell window and open a new one. Then my ssh connections still block the ports. – Calamity Jane May 11 '22 at 16:30
  • Look at answer 1 here from the link above: https://stackoverflow.com/questions/26505294/how-to-kill-port-forwarding-once-you-have-have-finished-using-it – Calamity Jane May 11 '22 at 16:32