How to check if an SSH connection is open or not?

6,982

A simplified version of some functions from my ~/.bashrc and ~/.zshrc (fully POSIX compatible, ready for your shell scripts):

# true if we have the given command(s)
we_have() { type "$@" >/dev/null 2>&1; }

# Usage: probe SERVER PORT|SERVICE
# returns true when SERVER has PORT opened (and responds within one second)
if we_have nc
  then probe() { nc -zw1 "$@" >/dev/null 2>&1; }
  else probe() { echo X |telnet -e X "$@" >/dev/null 2>&1; }
fi

# Usage: poke SERVER [PORT|SERVICE]
# As probe.  Also: PORT defaults to 80 (http) and reports the result
poke() {
  local RETVAL STATUS
  probe "$1" "${2:-80}"
  RETVAL=$?
  if [ $RETVAL != 0 ]; then
    STATUS=" not"
  fi
  echo "could$STATUS connect to port ${2:-80} on host '$1'"
  return $RETVAL
}

This supports port numbers and any service name indexed by /etc/services. (Be careful to test this; if your test fails due to a bad service name, you won't know.)

Some example tests:

$ poke localhost ssh
could connect to port ssh on host 'localhost'
$ poke localhost 12345
could not connect to port 12345 on host 'localhost'

Use probe if you want to script something with just the return value, e.g.

if probe localhost ssh; then
  echo something contingent on hosting ssh goes here
fi

If you have nmap version 5+ installed, you can use ncat --send-only --recv-only -w 334ms $1 $2 instead of the nc command. This fails faster (I've settled on 334ms. nc only allows to-the-second resolution, so you're stuck waiting a full second).


Note that this does not verify what is being hosted, only that the port is open. 99% of the time, this is good enough. If you need more than that, try something like this:

nmap -sV -p ssh localhost |grep -qi 'open.*ssh.*ssh[^?]'

This will tell nmap to scan port ssh (22) on server localhost and determine the service/version info. On my system, without the grep, it reports:

Starting Nmap 6.40 ( http://nmap.org ) at 2014-02-14 17:01 PST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000048s latency).
Other addresses for localhost (not scanned): 127.0.0.1
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.4p1 Debian 2 (protocol 2.0)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds

So the grep command is looking past the first instance of SSH (which merely indicates the mapping in /etc/services) into the hosting server and version info, which must match "ssh" (case-insensitive). The -q flag merely suppresses the output (so this can replace probe). If nmap can't figure out what the service is, it will say ssh?, so the grep regex avoids matching that.

Let's combine them to make it fast yet still verify SSH is truly being served:

# Usage: vet_ssh SERVER [PORT|SERVICE]
# True when SERVER has PORT (default=22) both opened and serving SSH
vet_ssh() {
  probe $1 ${2:-22} && nmap -sV -p ${2:-22} $1 |grep -qiE 'open.....*ssh[^?]'
}

Now you can use vet_ssh in place of probe in your poke function. This will be almost as fast as my original poke function: it's the same speed when the port is not open, it's slightly slower when the port is open and serving SSH, and it's decently slower when open and serving something nmap can't recognize quickly (or at all). The grep regex here is slightly different in order to accommodate alternate ports.


In the event that I've completely misinterpreted your question ... if you want to know whether you're already connected to this server (rather than whether or not you could), use netstat in a manner like this:

# Usage: am_i_sshed_to SERVER [PORT|SERVICE]
# True when you have an established connection to SERVER on PORT (default=22)
am_i_sshed_to() {
  local IP_QUERY=`host "$1" |awk -v port="${2:-22}" '
    $2 != "mail" { printf "-e %s:%s ", $NF, port }
  '`
  netstat -tn |grep -w $IP_QUERY |grep -wq ESTABLISHED
}

Then you can use am_i_sshed_to in the same manner as probe or vet_ssh.

(Explanation: netstat takes a really long time to look up each address. We only need one lookup for the one server we want to check for, so we cache that on the first line. The awk command says any line not discussing mail delivery must end ($NF) in the IP. Make that a grep query for our upcoming netstat call, so 1.2.3.4 becomes e.g. -e 1.2.3.4:22 and we can have multiple IPs (up to a few hundred before we hit command line size limits). Then, we run netstat, looking only at TCP connections and not mapping anything to a name. We grep for words (don't match "11.2.3.4:22" or "1.2.3.4:2234") against our cached query (note intentional lack of quotes, we don't need them and they'd change the argument structure!) and then make sure the connection is still established. Again, grep -q has no output, so this is a drop-in replacement for probe but not for poke)

Share:
6,982

Related videos on Youtube

Vivek Menon
Author by

Vivek Menon

Updated on September 18, 2022

Comments

  • Vivek Menon
    Vivek Menon almost 2 years

    I am trying to connect to the public.sigmadesigns.com site. Actually I was authorized to that server by sending my RSA Public key to it. But now when I try to do repo, I get:

    Getting manifest ...
       from [email protected]:mipsandroid/platform/manifest.git
    ssh: connect to host public.mipsandroid.com port 22: Connection refused
    ssh: connect to host public.mipsandroid.com port 22: Connection refused
    fatal: The remote end hung up unexpectedly
    fatal: cannot obtain manifest [email protected]:mipsandroid/platform/manifest.git
    

    Since I am inside a corporate proxy network, I would like to know if my access to this IP is open or not. How can I check this?

  • user1686
    user1686 about 13 years
    Creating an account is not necessary. Just run ssh in verbose mode, and if it establishes the connection and asks for authentication, then the firewall is open.
  • hicklypups
    hicklypups about 13 years
    @grawity I did not think to check that sdf.org might be the name of their actual server they allow ssh to.