Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking if an SSH tunnel is up and running

I have a perl script which, when destilled a bit, looks like this:

my $randport = int(10000 + rand(1000));          # Random port as other scripts like this run at the same time
my $localip = '192.168.100.' . ($port - 4000);   # Don't ask... backwards compatibility
system("ssh -NL $randport:$localip:23 root\@$ip -o ConnectTimeout=60 -i somekey &");    # create the tunnel in the background

sleep 10;       # Give the tunnel some time to come up

# Create the telnet object
my $telnet = new Net::Telnet(
        Timeout =>      10,
        Host    =>      'localhost',
        Port    =>      $randport,
        Telnetmode =>   0,
        Errmode =>      \&fail,
);

# SNIPPED... a bunch of parsing data from $telnet

The thing is that the target $ip is on a link with very unpredictable bandwidth, so the tunnel might come up right away, it might take a while, it might not come up at all. So a sleep is necessary to give the tunnel some time to get up and running.

So the question is: How can i test if the tunnel is up and running? 10 seconds is a really undesirable delay if the tunnel comes up straight away. Ideally, i would like to check if it's up and continue with creating the telnet object once it is, to a maximum of, say, 30 seconds.

Edit: Ping doesn't help me mouch, as the remote end of the tunnel is generally up, but with a very high amount of packetloss

Solved: Extrapolating from the tip suggested by mikebabcock, sleep 10 has been replaced with this block which works like a charm:

my $starttime = time();
while (1)
{
    # Check for success
    if (system("nc -dzw10 localhost $randport > /dev/null") == 0) { last }

    # Check for timeout
    if (time() > $starttime + 30) { &fail() }

    # 250ms delay before recheck
    select (undef, undef, undef, 0.25);
}
like image 1000
Jarmund Avatar asked Sep 26 '12 15:09

Jarmund


2 Answers

Use netcat -- often nc on Linux systems:

nc -dvzw10 ${HOSTNAME} 23

Works for me, with a response like:

Connection to ${HOSTNAME} 23 port [tcp/telnet] succeeded!

It also returns 0 on success, and is happy with a simple connection after which it goes away.

  • -d means not to read anything from the keyboard side
  • -v means to be verbose (turn this off in a script)
  • -z means to disconnect after making the connection
  • -w10 means to wait up to 10 seconds, otherwise give up
like image 65
mikebabcock Avatar answered Oct 09 '22 04:10

mikebabcock


You can integrate a ping to your ssh server and if it works fine the ssh tunnel is up

# only a ping sample :-D
if !  ping -c 1 192.168.101.9; then
    echo "ping does not succeed"
else
    echo "ping succeed"
fi
like image 1
OkieOth Avatar answered Oct 09 '22 03:10

OkieOth