How to check if an SSH connection is open or not?
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
)
Related videos on Youtube
![Vivek Menon](https://i.stack.imgur.com/rw8s0.jpg?s=256&g=1)
Vivek Menon
Updated on September 18, 2022Comments
-
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 about 13 yearsCreating 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 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.