简体   繁体   English

期待 TCL - 如何处理 ssh 远程主机标识在某些设备上发生了变化?

[英]Expect TCL - How to handle ssh remote host identification has changed on some devices?

I have tcl expect script to daily check some version on the network devices.我有 tcl 期望脚本每天检查网络设备上的某些版本。

#!/usr/bin/expect --

set env(TERM) vt100
set timeout 5
set username [lindex $argv 0]
set password [lindex $argv 1]
set hostname [lindex $argv 2]
set success 1

#login script
log_user 1
spawn ssh $username@$hostname
expect {
    "Connection refused" {
        spawn telnet $hostname
        expect {
            "?sername:" {
                if { $success == 0 } {
                    log_user 1
                    puts "error user or password incorrect"
                    exit 1;
                } else {
                    incr success -1
                    send "$username\r"
                }
                exp_continue
            }
            "?assword:" {
                send "$password\r"
                exp_continue
            }
            timeout {
                log_user 1
                puts "error could not ssh or telnet devices"
                exit 1;
                exp_continue
            }
            "#" {
                send "terminal length 0\r"
            }
        }
        exp_continue
    }
    timeout {
        spawn telnet $hostname
        expect {
            timeout {
                log_user 1
                puts "error could not ssh or telnet devices"
                exit 1;
                exp_continue
            }
            "?..." {
                log_user 1
                puts "error could not ssh or telnet devices"
                exit 1;
                exp_continue
            }
            "?sername:" {
                if { $success == 0 } {
                    log_user 1
                    puts "error user or password incorrect"
                    exit 1;
                } else {
                    incr success -1
                    send "$username\r"
                }
                exp_continue
            }
            "?assword:" {
                send "$password\r"
                exp_continue
            }
            "#" {
                send "terminal length 0\r"
            }
        }

        exp_continue
    }
    "continue connecting (yes/no)?" {
        send "yes\r"
        exp_continue
    }
    "?assword:" {
            if { $success == 0 } {
                log_user 1
                puts "error user or password incorrect"
                exit 1;
            } else {
                incr success -1
                send "$password\r"
        }
        exp_continue
    }
    "$ " {
        send "ssh keygen -R $hostname\r"
        exp_continue
    }
    "#" {
        send "terminal length 0\r"
    }
}

#execute script
expect "#"
send "\r"
expect "#"
log_user 1
send "show version\r"
expect "#"
send "exit\r"

My expect script working like this,我的期望脚本像这样工作,

  1. ssh to the devices. ssh 到设备。
  2. If ssh not working ("Connection refused" or "timeout") it will go to telnet condition如果 ssh 不工作(“连接被拒绝”或“超时”),它将 go 到远程登录状态
  3. If ssh known_hosts key is not present on linux devices, it will send "yes"如果 ssh known_hosts 密钥在 linux 设备上不存在,它将发送“是”
  4. If ssh key on the remote devices is changed, it will send "ssh-keygen -R $hostname"如果远程设备上的 ssh 密钥被更改,它将发送“ssh-keygen -R $hostname”

and the problem is, my expect program from could not work if ssh key on remote devices is changed.问题是,如果远程设备上的 ssh 密钥被更改,我的期望程序将无法运行。

[linux]$ ./sshtelnet.tcl mine password 1.1.1.1
spawn ssh mine@1.1.1.1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
83:24:a5:c4:2c:98:0d:0b:d6:ad:cb:74:12:7e:84:83.
Please contact your system administrator.
Add correct host key in /home/linux/.ssh/known_hosts to get rid of this message.
Offending key in /home/linux/.ssh/known_hosts:152
RSA host key for 1.1.1.1 has changed and you have requested strict checking.
Host key verification failed.
expect: spawn id exp4 not open
    while executing
"expect "#""
    (file "./sshtelnet.tcl" line 106)

When the remote host identification has changed, the ssh process terminates.当远程主机标识发生变化时,ssh 进程终止。 Assuming you know that this is not because "someone is doing something nasty", you want to execute the "ssh-keygen -R $hostname" locally, not send it to the spawned ssh process.假设您知道这不是因为“有人在做坏事”,您想在本地执行“ssh-keygen -R $hostname”,而不是将其发送到生成的 ssh 进程。 After cleaning up the offending key, you have to spawn the ssh command again.清理有问题的密钥后,您必须再次生成 ssh 命令。

The easiest way to be able to repeat the ssh command is to put things in procs:能够重复 ssh 命令的最简单方法是将内容放入 procs 中:

proc connectssh {username password hostname} {
    global spawn_id
    set success 1
    spawn ssh $username@$hostname
    expect {
        "Connection refused" {
            connecttelnet $username $password $hostname
        }
        timeout {
            connecttelnet $username $password $hostname
        }
        "continue connecting (yes/no)?" {
            send "yes\r"
            exp_continue
        }
        "?assword:" {
            if {$success == 0} {
                log_user 1
                puts "error user or password incorrect"
                exit 1;
            } else {
                incr success -1
                send "$password\r"
            }
            exp_continue
        }
        "Host key verification failed" {
            wait
            exec ssh-keygen -R $hostname
            connectssh $username $password $hostname
        }
        "#" {
            send "terminal length 0\r"
        }
    }
}

proc conecttelnet {username password hostname} {
    global spawn_id
    spawn telnet $hostname
    expect {
        # ...
    }
}

set env(TERM) vt100
set timeout 5
lassign $argv username password hostname
log_user 1
connectssh $username $password $hostname

# The rest of your script

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM