2

I am trying to write a script that will server more as a health check or security test. I don't need to actually run anything via SSH.

We have a few servers running and for safety reasons we don't always allow SSH to them, and I would like to have a script that I could run that would confirm which are accessible and which are not.

I realize that StackExchange is filled with questions like these, so I quickly found this suggestion:

$ ssh -q user@downhost exit
$ echo $?
255

$ ssh -q user@uphost exit
$ echo $?
0

Basically it would return 255 whenever connection is not possible, but here is where I have an issue. Our servers require a key file AND user/password authentication.

Having BatchMode=yes I could test it fine if I didn't have the password constraint as well.

I can give the script the location of the file, no problem there. But I get 255 every time because the server requires a password, as can be seen in this answer.

So basically my question is:

Is it possible to write a script that would let me know if it is possible to connect to these servers via SSH (given my constraints), and if it is what would that look like?

I don't need the final script as an answer (although that would be preferable). Just some pointers in the right direction would help me a great deal.

Thanks!

Community
  • 1
  • 1
Rodrigo Sasaki
  • 7,048
  • 4
  • 34
  • 49
  • 2
    Do you care if SSH is actually working or not, or just whether it is running? If the latter, you can simplify this by checking if the port is open and not actually trying to log in. – John Kugelman Dec 18 '15 at 17:34

3 Answers3

6

You can use netcat.

If you are just interested if the port is open you can use this:

if nc -w 5 -z "$server" 22 ; then
    echo "Port 22 on $server is open"
fi

If you are also interested if there is actually an ssh daemon running on that port you may analyze the server's hello message:

if [[ $(nc -w 5 "$server" 22 <<< "\0" ) =~ "OpenSSH" ]] ; then
    echo "open ssh is running"
fi

Btw, using the option -w you can specify a connection timeout (in seconds). I've chosen 5 seconds for this example

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
2

Can you use "expect"(TCL)? If so, you could use a script like:

#!/usr/bin/expect

set timeout 6

set IP [lindex $argv 0]

spawn ssh -o StrictHostKeyChecking=no teste@$IP

expect "password:" {
    send_user "\n1\n"
    exit
    }   
send_user "\n0\n"

To run the script use:

./script.sh "SSH server IP"

This script will run expect and launch the ssh program connecting to the IP you passed on the 1st argument. If the "password:" prompt is returned to this script, it simply finishes. Of course this is just an idea, you must develop and parse content the script returns.

AsK
  • 51
  • 6
  • Baiscally a good idea. However, you should improve the program to silently return `0` or `1`. At the moment it is always returning `0`. – hek2mgl Dec 18 '15 at 17:51
  • Sure it is just a fragment of a script I made for another purpose. As the Rodrigo said in the original quaestion he does not want a complete script (I supposed he wants to learn by himself) I just ansewer the most relvant part. :D (I am really new here, so forgive me if I am not doing it right). – AsK Dec 18 '15 at 17:55
  • You can still improve the script and update your answer. – hek2mgl Dec 18 '15 at 17:56
  • I hope you like it better now. – AsK Dec 18 '15 at 18:06
  • That is very interesting, I will have to tweak some things for our needs, but that is pretty great. But just out of curiosity, Is there an option without using expect? – Rodrigo Sasaki Dec 18 '15 at 18:23
  • I also think it is basically great, however I would write it in a way that it silently returns `0` or `1`. – hek2mgl Dec 18 '15 at 18:30
  • Unfortunately for this solution, "expect" is necessary. Important to note expect is a library ported to several languages like python, php and perl, so I sure you will find something more suitable for your needs. To return 0 or 1 silently, just remove the 2 commands "send_user" and put 1 right after the exit command; in this way the script will fill the bash's exit status with 0 when succesfully find a server who returns "password:" prompt and return 1 when for any reason no "password:" prompt is received. – AsK Dec 18 '15 at 18:56
  • Oh just one more comment: You can change the spawn line from SSH to telnet or any other command you want to run and interact with... :) – AsK Dec 18 '15 at 18:58
1

If you have valid key installed in your .ssh, you can use following (one time, not part of your script):

ssh-copy-id user@downhost

this will ask for your password and copies the key to server so that you can login without password from next time.

after that you should be able to run your command without password:

ssh -q user@downhost exit

hope it will help.

VK Kashyap
  • 168
  • 1
  • 10
  • It's an interesting suggestion. I would just prefer to not have this script tied to a single machine (or any machine that would need to fit these prerequisites) – Rodrigo Sasaki Dec 18 '15 at 20:20