How to use bash/expect to check if an SSH login wo

2019-03-26 04:20发布

My team manages many servers, and company policy dictates that the passwords on these servers must be changed every couple of weeks. Sometimes, our official database of passwords gets out of date for whatever reason (people forget to update it, usually), but we cannot identify this sometimes until months later, since we don't consistently use every server.

I want to write a script that will scrape the passwords from the database, and use those passwords to attempt an (ssh) login to each server every night, and send an email with the results to the team. I am able to scrape the database for login information, but I'm not sure how to check whether ssh login was successful or not in expect.

I cannot use public key authentication for this task. I want password authentication so I can verify the passwords.

I disable public-key authentication by specifying the following file:

PasswordAuthentication=yes
PubkeyAuthentication=no

My attempts at the expect script:

# $1 = host, $2 = user, $3 = password, $4 = config file
expect -c "spawn ssh $2@$1 -F $4
expect -re \".*?assword.*?\"
send \"$3\n\"
...
send \'^D\'"

I thought maybe exit status could indicate the success? Couldn't find anything in the man pages though.

4条回答
看我几分像从前
2楼-- · 2019-03-26 04:56

crowbent has provided you an expect script to test ssh login however I would recommend using Non-interactive ssh password auth for testing out ssh/sftp. sshpass is much more secured and less error prone than expect.

查看更多
萌系小妹纸
3楼-- · 2019-03-26 05:03

I've been using something like the script below for a similar task.

#!/bin/sh
# Run using expect from path \
exec expect -f "$0" "$@"
# Above line is only executed by sh
set i 0; foreach n $argv {set [incr i] $n}
set pid [ spawn -noecho ssh $1@$3 $4 ]
set timeout 30
expect {
    "(yes/no)" {
        sleep 1
        send "yes\n"
        exp_continue
    }
    "(y/n)" {
        sleep 1
        send "y\n"
        exp_continue
    }
    password {
        sleep 1
        send "$2\n"
        exp_continue
    }
    Password {
        sleep 1
        send "$2\n"
        exp_continue
    }
    "Last login" {
        interact
    }
    "Permission denied" {
        puts "Access not granted, aborting..."
        exit 1
    }
    timeout {
        puts "Timeout expired, aborting..."
        exit 1
    }
    eof {
        #puts "EOF reached."
    }
}
set status [split [wait $pid]]
set osStatus [lindex $status 2]
set procStatus [lindex $status 3]
if { $osStatus == 0 } {
    exit $procStatus
} else {
    exit $procStatus
}
查看更多
闹够了就滚
4楼-- · 2019-03-26 05:04

Do you specifically need to check if you can obtain a shell or is trying to execute a command also OK ?

If you just want to check authentication, you may want to do ssh asimplecommand (using echo, hostname, or something as such) and check if you get the expected result.

You may also want to launch ssh with -v option, and look for Authentication succeeded (at the debug1 log level).

查看更多
该账号已被封号
5楼-- · 2019-03-26 05:15

The solution to the underlying problem (password database getting out of sync) is to use public key authentication. For everyone. Do NOT bother with passwords when it comes to SSH.

Successful login could be checked like this:

ssh -o PasswordAuthentication=no USER@HOST 'exit' || echo "SSH login failed."
查看更多
登录 后发表回答