Linux系統(tǒng)自動化管理: 遠(yuǎn)程登錄
Telnet 和 SSH 協(xié)議是 Internet 遠(yuǎn)程登錄服務(wù)的標(biāo)準(zhǔn)協(xié)議和主要方式,它們?yōu)橛脩籼峁┝嗽诒镜貦C器上完成遠(yuǎn)程機器上工作的能力。用戶使用 Telnet 或者 SSH 軟件連接遠(yuǎn)程服務(wù)器,在 Telnet 或者 SSH 軟件中輸入的命令就會在服務(wù)器上運行。Telnet 協(xié)議本質(zhì)上是不安全的,因為它使用明文傳送數(shù)據(jù)、用戶賬號和口令,很容易受到中間人攻擊方式的攻擊;而 SSH 協(xié)議則是比較可靠、專為遠(yuǎn)程登錄會話和其他網(wǎng)絡(luò)服務(wù)提供安全性的協(xié)議。通過 SSH 可以對所有傳輸?shù)臄?shù)據(jù)進行加密,也能夠防止 DNS 欺騙和 IP 欺騙。本文主要針對 SSH 協(xié)議進行闡述,使用的 SSH 軟件是 OpenSSH,它是開放源代碼的免費的 SSH 替代軟件包。
用戶使用 Telnet 或者 SSH 登錄不同的操作系統(tǒng),會得到不同的返回信息。用戶可以編寫程序根據(jù)運程登錄的返回信息進行判斷和處理,從而實現(xiàn)遠(yuǎn)程服務(wù)器系統(tǒng)的自動化登錄。本文將先介紹實現(xiàn)遠(yuǎn)程自動化登錄用到的技術(shù),再詳細(xì)介紹如何實現(xiàn) Unix/Linux 系統(tǒng)間遠(yuǎn)程登錄自動化。
遠(yuǎn)程系統(tǒng)自動化登錄機制簡介
所謂自動化遠(yuǎn)程登錄,是指在用戶不干預(yù)的情況下,不需要手動輸入密碼,就能登錄到遠(yuǎn)程系統(tǒng)。目前遠(yuǎn)程登錄工具有兩種安全認(rèn)證方式。
基于用戶口令的安全認(rèn)證
當(dāng)使用登錄賬戶登錄時,根據(jù)提示輸入口令,SSH 就會用安全密碼認(rèn)證協(xié)議,將加密傳送給 SSHD 服務(wù)器。認(rèn)證成功后,就可以登錄到 SSHD 服務(wù)器。
針對這種安全認(rèn)證方式,可以讓程序自動輸入用戶名和密碼,實現(xiàn)自動化登錄。目前可以用 expect, C 或 Perl 來實現(xiàn)。如果采用 C, 需要很熟悉 TCP/IP 協(xié)議,實現(xiàn)起來比較復(fù)雜;如果用 expect, 由于 expect 是基于 Tcl 的,需要熟悉 Tcl 語法;如果用 perl 實現(xiàn),需要采用 perl 的 expect.pm 這個包。但需要用戶輸入口令,因此這種認(rèn)證方式存在著安全隱患。
基于 SSH key 交換的安全認(rèn)證方式
用戶需要先在 SSH 客戶端為登錄賬戶創(chuàng)建一對密匙:私鑰(private key)和公鑰 (public key),然后把公鑰傳送到要登錄的 SSHD 服務(wù)器上。當(dāng)用戶使用 SSH 客戶端登錄 SSHD 服務(wù)器時,SSH 客戶端就會向 SSHD 服務(wù)器發(fā)出用登錄帳戶的密鑰進行安全驗證的請求;SSHD 服務(wù)器收到請求,先在登錄帳號的主目錄下尋找對應(yīng)的公鑰,并與客戶端發(fā)送過來的公鑰進行對比;如果兩個密鑰一致,SSHD 服務(wù)器會用公鑰加密“質(zhì)詢”(challenge),發(fā)送給 SSH 客戶端;SSH 客戶端收到“質(zhì)詢”之后用客戶端的私鑰解密,再把它發(fā)送給 SSHD 服務(wù)器。這樣就完成了安全認(rèn)證的整個過程。
使用基于 SSH key 交換的認(rèn)證方式,用戶只要將在 SSH 客戶端生成的公鑰復(fù)制到遠(yuǎn)程的 SSHD 服務(wù)器。當(dāng)通過 SSH 客戶端登錄 SSHD 服務(wù)器時,用戶不需要輸入密碼,就可以自動登錄到遠(yuǎn)程 SSHD 服務(wù)器。這種方式不僅簡便,而且避免了用戶名和密碼的泄露,比第一種方式要安全。
#p#使用 Expect 的自動化登錄
Expect 的基礎(chǔ)知識
Expect 是由 Don Libes 基于 Tcl 語言開發(fā)的,并被廣泛應(yīng)用于交互式操作和自動化測試的場景之中,它尤其適用于需要對多臺服務(wù)器執(zhí)行相同操作的環(huán)境中,可以大幅度得提高系統(tǒng)管理人員的工作效率。目前,大部分 Unix/Linux 系統(tǒng)安裝有 expect. 萬一系統(tǒng)中沒有,可以從 http://expect.nist.gov/ 下載相應(yīng)的包安裝。
Expect 作為基于 Tcl 的高級語言,增加了一些特殊的語法。傳統(tǒng)意義上的 Expect 是以 Tcl 擴展包的形式出現(xiàn)的,任何 Tcl 語言編寫的應(yīng)用程序都可以加載 Expect 功能;此外,Expect 已經(jīng)以模塊的方式移植到了 Perl 和 Python 語言中,因此用戶同樣可以在 Perl 和 Python 腳本中利用 Expect 強大的交互功能。
Send,expect 和 spwan 是 Expect 語言最基本的命令。其中,send 命令會發(fā)送字符串給指定進程(process); expect 命令會等待接受該進程返回的結(jié)果并且會根據(jù)返回的字符串來決定下一步的操作;而 spwan 命令可以發(fā)起一個進程的運行。
send 命令接收一個字符串做為參數(shù)并發(fā)送給指定的進程;從
send “Hello world”
這行代碼中,send 會送出字符串“Hello world”( 不帶引號 )。如果 Expect 早已經(jīng)開始與某一個程序進行交互,那么這個字符串將被發(fā)送給該程序;而在通常情況下,這個字符串會被送到標(biāo)準(zhǔn)輸出設(shè)備。
expect 命令則等待一個響應(yīng),通常是來自于 Expect 正在與之交互的進程,或者來自于標(biāo)準(zhǔn)輸入設(shè)備;它會等待一個指定的字符串或者滿足給定的正則表達(dá)式的任何字符串。我們可以創(chuàng)建一個名為 response.exp 的文件,來看 Expect 是如何處理的,其內(nèi)容如下:
#!expect – f
expect “hi\n”
send “hello there\n”
然后在 shell 下面運行 ”expect response.exp”,它會等待來自標(biāo)準(zhǔn)輸入設(shè)備的響應(yīng),直到用戶輸入 hi 并回車,它才會發(fā)送”hello there”到標(biāo)準(zhǔn)輸出設(shè)備,并回車。然后結(jié)束 expect 腳本的運行。但是,如果用戶沒有輸入 hi 并回車,那么 expect 會繼續(xù)等待”hi\n”;輸入其他的字符并不會影響到 expect 的工作。通常情況下,expect 會一直等會輸入,直到最終超時退出。此外, expect 還支持使用正則表達(dá)式來預(yù)防 expect 匹配到未預(yù)想到的輸入數(shù)據(jù)。
spawn 命令會調(diào)用另一個程序。它的第一個參數(shù)是要啟動程序的名字;剩余的參數(shù)則會被傳遞給該程序做為參數(shù)。比如
spawn ftp linux.ibm.com">ftp.linux.ibm.com
命令會衍生出一個 ftp 進程,并且將 ftp.linux.ibm.com 做為參數(shù)傳遞給這個 ftp 進程。
用戶通過 spawn,send 和 expect 這三個基本命令,就可以編寫一段 Expect 程序來實現(xiàn)自動化工作。
Expect 腳本實現(xiàn)
本節(jié)將利用基于用戶口令的安全認(rèn)證方式,并使用 Expect 來實現(xiàn) SSHD 服務(wù)器的自動化登錄過程,并在登錄的會話中實現(xiàn)命令在 SSHD 服務(wù)器端的執(zhí)行。本文使用的具體實驗環(huán)境如下:用戶使用的 SSH 客戶端機器:操作系統(tǒng)均為 RHELS5.3, IP 地址為 192.168.0.3, Expect 版本為 version 5.43.0;遠(yuǎn)程的 SSHD 服務(wù)器:操作系統(tǒng)均為 RHELS5.3,IP 地址為 192.168.0.4,用戶名 / 密碼為 root/123456。
清單1.登錄 SSHD 服務(wù)器的自動化腳本
#!/usr/bin/expect
# 設(shè)置超時時間為 60 秒
set timeout 60
# 設(shè)置要登錄的主機 IP 地址
set host 192.168.0.4
# 設(shè)置以什么名字的用戶登錄
set name root
# 設(shè)置用戶名的登錄密碼
set password 123456
#spawn 一個 ssh 登錄進程
spawn ssh $host -l $name
# 等待響應(yīng),第一次登錄往往會提示是否永久保存 RSA 到本機的 know hosts 列表中;等到回答后,在提示輸出密碼;之后就直接提示輸入密碼
expect {
"(yes/no)?" {
send "yes\n"
expect "assword:"
send "$pasword\n"
}
"assword:" {
send "$password\n"
}
}
expect "#"
# 下面測試是否登錄到 $host
send "uname\n"
expect "Linux"
send_user "Now you can do some operation on this terminal\n"
# 這里使用了 interact 命令,使執(zhí)行完程序后,用戶可以在 $host 終端進行交互操作。
Interact
如果要運行該腳本,可以參考如下的操作,假設(shè) expect 腳本的文件名為 t1.expect。另外,在運行該腳本之前,需要將 t1.expect 文件設(shè)置成可執(zhí)行的模式 ;
清單2.運行自動化登錄腳本的操作步驟
[root@redhat ~]chmod a+x t1.expect
[root@redhat ~]./t1.expect
spawn ssh 192.168.0.4 -l root
root@192.168.0.4's password:
Last login: Fri Jun 12 15:36:01 2009 from 192.168.0.3
Red Hat Enterprise Linux Server release 5.1 (Tikanga)
[root@c96m3h4ms01 ~]# uname
Linux
Now you can do some operation on this terminal
[root@c96m3h4ms01 ~]#
基于 SSH 交換 Key 自動化登錄
SSH 證書簡介
SSH 證書使用一對密鑰 : 私鑰(private key)和公鑰 (public key)。公鑰(public key)對數(shù)據(jù)進行加密而且只能用于加密,私鑰(private key)只能對所匹配的公鑰(public key)加密過的數(shù)據(jù)進行解密。私鑰(private key)只保存你獨有的一些秘密信息。SSH 客戶端用其向 SSHD 服務(wù)器證明自已的身份。公鑰是公開的,可以隨便將其放入 SSHD 服務(wù)器上自已的帳號中 , 在認(rèn)證時,進行私鑰和公鑰協(xié)商,如果匹配,那么身份就得以證明,認(rèn)證就成功。
目前所有的 OpenSSH 版本都應(yīng)該既能使用 RSA 密鑰又能使用 DSA 密鑰。RSA 密鑰和 DSA 密鑰的生成命令和使用方法相同,本文僅介紹 RSA。
如果采用 SSH 密鑰認(rèn)證的方式實現(xiàn)自動化登錄,用戶可以參考下面的章節(jié)。
生成密鑰對
ssh-keygen 程序生成的 RSA 密鑰的文件名默認(rèn)為 id_rsa 和 id_rsa.pub,用戶也可以將其更改為別的名稱。下面”清單 3. 生成密鑰對”的操作過程將采用系統(tǒng)的默認(rèn)值。
清單3. 生成密鑰對
[root@redhat ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): <--- 可以不輸入密碼
Enter same passphrase again: <--- 可以不輸入密碼
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
4b:70:20:de:89:92:a9:fe:21:a4:9b:7c:6b:65:ae:e0 root@redhat
[root@redhat ~]# ls -al .ssh
total 20
drwx------ 2 root root 4096 May 10 02:51 .
drwxr-x--- 11 root root 4096 May 10 02:51 ..
-rw------- 1 root root 1675 May 10 02:51 id_rsa
-rw-r--r-- 1 root root 397 May 10 02:51 id_rsa.pub
如果 ssh 目錄不存在,程序為自動創(chuàng)建本地 SSH 目錄 ~/.ssh,并將所生成的密鑰分成兩個文件存儲,私鑰為 id_rsa,公鑰為 id_rsa.pub。
#p#配置自動化登錄
在配置自動化登錄的過程中,賬戶對應(yīng)的公鑰需要被添加到 SSHD 服務(wù)器端的配置文件。在 3.0 版本的 OPENSSH 中,用戶需要修改的文件為 authorized_keys,早于 3.0 的版本則使用 authorized_keys2 文件。將在客戶端生成的 id_rsa.pub 文件內(nèi)容加入到 authorized_keys 或者 authorized_keys2 文件中即可完成配置工作。
為安全起見,要確保 $HOME/.ssh 目錄的安全,只有所有者才有 權(quán)寫入。如果遠(yuǎn)程用戶的 SSH 配置文件的權(quán)限設(shè)置不當(dāng),服務(wù)器可能會拒絕進行認(rèn)證。
下面是配置自動化登錄的具體過程,其場景如下:
Openssh 為 OpenSSH_4.3p2SSH,將以 root 用戶登錄到 SSHD 服務(wù)器(192.168.0.4)上,因此公鑰的內(nèi)容將存放在 root/.ssh/authorized_keys。
清單4. 終端操作記錄
[root@redhat ~]# scp /root/.ssh/id_rsa.pub root@192.168.0.4:/tmp
[root@redhat .ssh]# ssh 192.168.0.4
root@192.168.0.4's password: ******
[root@server ~]# cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys
如果用戶在生成 rsa 和 id_rsa.pub 的時候沒有輸入密碼,可以直接使用“ssh root@192.168.0.4”登錄,而不用輸入密碼。
而如果用戶在生成 rsa 和 id_rsa.pub 的時候輸入了密碼,需要進行以下兩步操作:
啟用 ssh-agent 認(rèn)證代理 ,
清單5. 終端操作記錄
[root@redhat ~]# ssh-agent $SHELL
(2) 使用 ssh-add, 裝入私鑰,并輸入生成 rsa 和 id_rsa.pub 時輸入的密碼
清單6. 終端操作記錄
[root@redhat ~]# ssh-add
Enter passphrase for /root/.ssh/id_rsa:
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
Identity added: /root/.ssh/id_dsa (/root/.ssh/id_dsa)
[root@redhat ~]# ssh 192.168.0.4
Last login: Sat May 16 11:37:39 2009 from redhat
把私鑰保存在內(nèi)存中,為認(rèn)證提供服務(wù),之后以 root 用戶 ssh 登錄時,就不用重復(fù)輸入密碼。其生命周期為 ssh-agent 啟動的那個 shell,當(dāng)用戶退出該 shell 時,需要重新執(zhí)行 ssh-agent 和 ssh-add。
只要密鑰配置好,以后登錄就是自動化了。因此本部分登錄過程不需要用腳本來實現(xiàn),實現(xiàn)了前期拷貝 SSH key 到遠(yuǎn)程服務(wù)器,并添加到相應(yīng)的位置,并測試自動登錄是否成功。
腳本實現(xiàn)配置自動化登錄
本節(jié)的腳本實現(xiàn)基于 SSH key 交換的安全認(rèn)證方式,并利用 Expect 來實現(xiàn)自動化登錄。本節(jié)所實現(xiàn)的腳本可以運行在以下的實驗環(huán)境中:用戶使用的 SSH 客戶端機器:操作系統(tǒng)均為 RHELS5.3, IP 地址為 192.168.0.3, Expect 版本為 version 5.43.0;遠(yuǎn)程的 SSHD 服務(wù)器:操作系統(tǒng)均為 RHELS5.3,IP 地址為 192.168.0.4,用戶名 / 密碼為 root/123456。
Expect 腳本的內(nèi)容如下:
清單7.基于 SSH key 交換的自動化登錄腳本
#!/usr/bin/expect
# 判斷輸入的參數(shù)是否為 3 個,如果不為 3 個,就打印錯誤信息,退出該程序。
if { $argc != 3 } {
puts stderr "Usage: test1 host-address username host-password\n"
exit 1
}
# 設(shè)置超時時間為 60 秒
set timeout 60
# 將命令行輸入的第一個參數(shù)作為將要登錄的 SSHD 服務(wù)器
set host [lindex $argv 0]
# 第二個參數(shù)是用戶名,賦值給 name, 之后用 $name 格式來使用
set name [lindex $argv 1]
# 第三個參數(shù)是以 $name 登錄 $host 的口令
set password [lindex $argv 2]
##set timeout 60
##set password "cluster"
##set name “root”
##set host "192.168.0.4"
#root 用戶的 rsa key 放在 /root/.ssh 中,其他用戶則放在 /home/$name/.ssh
if { $name == "root"} {
spawn scp /$name/.ssh/id_rsa.pub $name@$host:/tmp
} else {
spawn scp /home/$name/.ssh/id_rsa.pub $name@$host:/tmp
}
# 等待上個命令的響應(yīng)
expect {
"(yes/no)?" {
send "yes\n"
expect "assword:"
send "$pasword\n"
}
"assword:" {
send "$password\n"
}
}
# 輸入密碼后,拷貝成功,出現(xiàn) 100% 字符串,作為預(yù)期響應(yīng)
expect "100%"
# 調(diào)用 ssh 以 $name 用戶名登錄到 $host 上
spawn ssh $host – l$name
# 期待提示出入密碼的響應(yīng)
expect "assword:"
# 接收密碼
send "$password\n"
expect ":~#"
# 將剛剛拷貝的 rsa key 添加到用戶的 home 目錄下的 ./ssh/authorized_keys
if { $name == "root"} {
send "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys\n"
} else {
send "cat /tmp/id_rsa.pub >> /home/$name/.ssh/authorized_keys\n"
}
expect ":~#"
# 操作成功后,退回 SSH 客戶端機器
send "exit\n"
expect "#"
# 下面將測試能否自動登錄,不用輸入密碼
spawn ssh $host – l$name
expect {
"Welcome" {
send_user "Auto login the server successfully!"
}
"assword:" {
send_user "failed to login the server!"
}
}
send "ls\n"
expect ":~#"
# 退出 $host
send "exit\n"
# 程序結(jié)束
expect eof
清單 7 基于 SSH key 交換的自動化登錄腳本注釋掉了主機名,用戶名和密碼,因此用戶在運行腳本時需要手工輸入主機名,用戶名和密碼。一旦 SSH Key 的交換完成,用戶就可以直接運行 “ssh host-address – l username”實現(xiàn)自動化登錄,而不再需要輸入用戶名密碼。
【編輯推薦】