批量實現多臺伺服器之間ssh無密碼登入的相互信任關係

散盡浮華發表於2018-05-20

 

最近IDC上架了一批hadoop大資料業務伺服器,由於叢集環境需要在這些伺服器之間實現ssh無密碼登入的相互信任關係具體的實現思路:在其中的任一臺伺服器上通過"ssh-keygen -t rsa"產生公私鑰檔案,然後將公鑰檔案拷貝成authorized_keys檔案,最後將它的.ssh目錄下的檔案全部批量拷貝到其他伺服器的/root/.ssh目錄(即當前使用者家目錄的.ssh)下即可。這批hadoop伺服器的ssh埠預設都是22,密碼預設都是kevin123456,ip列表如下:

192.168.10.202
192.168.10.203
192.168.10.205
192.168.10.206
192.168.10.207
192.168.10.208

注意:批量部署信任關係後,目標機器的公私鑰檔案id_rsa和id_rsa.pub會被覆蓋,但是authorized_keys檔案不會被覆蓋,只會進行新內容追加,所以如果目標機器之前做了別的信任關係,在新的信任關係做好後,老的信任關係不會丟失。

1)方法一(適用於機器數量不算多的情況下)

首先在其中任一臺伺服器,如192.168.10.202上生產公私鑰檔案:
[root@server-202 ~]# ssh-keygen -t rsa
[root@server-202 ~]# ls /root/.ssh/
id_rsa  id_rsa.pub

[root@server-202 ~]# chmod 600 /root/.ssh/id_rsa                                            #一定要保證私鑰id_rsa檔案許可權是600!
[root@server-202 ~]# cp /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys
[root@server-202 ~]# ls /root/.ssh/
authorized_keys  id_rsa  id_rsa.pub

[root@server-202 ~]# vim /root/hosts
192.168.10.202
192.168.10.203
192.168.10.205
192.168.10.206
192.168.10.207
192.168.10.208
[root@server-202 ~]# for i in `cat /root/hosts`;do rsync -e "ssh -p22" -avpgolr /root/.ssh root@$i:/root/;done
執行該命令後,需要多次手動輸入密碼
 
執行後,這些機器之間就可以通過ssh密碼登入了,即實現了相互信任關係。檢查下這些機器的/root/.ssh目錄,發現他們的公私鑰檔案都是192.168.10.202這臺機器的。
該種方法僅適用於少數伺服器的情況,因為涉及到中途人工互動(輸入密碼等),如果伺服器數量眾多的情況下,適用這種方式就比較傻X了,這就需要用到下面這種方法。 

2)方法二(使用expect工具,適用於機器數量眾多的情況下)
expect是互動性很強的指令碼語言,可以幫助運維人員實現批量管理成千上百臺伺服器操作,是一款很實用的批量部署工具!expect依賴於tcl,而linux系統裡一般不自帶安裝tcl,所以需要手動安裝。選擇其中的任意一臺伺服器上操作,比如這裡還是選擇192.168.10.202這臺機器。expect-5.43.0.tar和tcl8.4.11-src.tar的下載地址:https://pan.baidu.com/s/1kVyeLt9       提取密碼:af9p

將expect和tcl的軟體包下載放到/usr/local/src目錄下,解壓tcl,進入tcl解壓目錄,然後進入unix目錄進行編譯安裝
[root@server-202 ~]# cd /usr/local/src/
[root@server-202 src]# tar -zvxf tcl8.4.11-src.tar.gz
[root@server-202 src]# cd tcl8.4.11/unix
[root@server-202 unix]# ./configure
[root@server-202 unix]# make && make install
 
安裝expect
[root@server-202 src]# tar -zvxf expect-5.43.0.tar.gz
[root@server-202 src]# cd expect-5.43.0
[root@server-202 expect-5.43.0]# ./configure --with-tclinclude=/usr/local/src/tcl8.4.11/generic --with-tclconfig=/usr/local/lib/
[root@server-202 expect-5.43.0]# make && make install
 
安裝完成後進行測試
[root@server-202 ~]# expect
expect1.1>
 
[root@server-202 ~]# which expect
/usr/local/bin/expect
 
做個expect執行檔案的軟體
[root@server-202 ~]# ln -s /usr/local/bin/expect /usr/bin/expect
[root@server-202 ~]# ll /usr/bin/expect
 
批量實現信任關係的指令碼如下:
[root@server-202 ~]# vim /opt/ssh_auth.sh
#!/bin/sh 
DEST_USER=$1 
PASSWORD=$2 
HOSTS_FILE=$3 
if [ $# -ne 3 ]; then 
    echo "Usage:" 
    echo "$0 remoteUser remotePassword hostsFile" 
    exit 1 
fi 
   
SSH_DIR=~/.ssh 
SCRIPT_PREFIX=./tmp 
echo =========================== 
 
# 1. prepare  directory .ssh 
mkdir $SSH_DIR 
chmod 700 $SSH_DIR 
   
# 2. generat ssh key 
TMP_SCRIPT=$SCRIPT_PREFIX.sh 
echo  "#!/usr/bin/expect">$TMP_SCRIPT 
echo  "spawn ssh-keygen -b 1024 -t rsa">>$TMP_SCRIPT 
echo  "expect *key*">>$TMP_SCRIPT 
echo  "send \r">>$TMP_SCRIPT 
if [ -f $SSH_DIR/id_rsa ]; then 
    echo  "expect *verwrite*">>$TMP_SCRIPT 
    echo  "send y\r">>$TMP_SCRIPT 
fi 
echo  "expect *passphrase*">>$TMP_SCRIPT 
echo  "send \r">>$TMP_SCRIPT 
echo  "expect *again:">>$TMP_SCRIPT 
echo  "send \r">>$TMP_SCRIPT 
echo  "interact">>$TMP_SCRIPT 
   
chmod +x $TMP_SCRIPT 
   
/usr/bin/expect $TMP_SCRIPT 
rm $TMP_SCRIPT 
   
# 3. generat file authorized_keys 
cat $SSH_DIR/id_rsa.pub>>$SSH_DIR/authorized_keys 
   
# 4. chmod 600 for file authorized_keys 
chmod 600 $SSH_DIR/authorized_keys 
echo =========================== 
 
# 5. copy all files to other hosts 
for ip in $(cat $HOSTS_FILE)   
do 
    if [ "x$ip" != "x" ]; then 
        echo ------------------------- 
        TMP_SCRIPT=${SCRIPT_PREFIX}.$ip.sh 
        # check known_hosts 
        val=`ssh-keygen -F $ip` 
        if [ "x$val" == "x" ]; then 
            echo "$ip not in $SSH_DIR/known_hosts, need to add" 
            val=`ssh-keyscan $ip 2>/dev/null` 
            if [ "x$val" == "x" ]; then 
                echo "ssh-keyscan $ip failed!" 
            else 
                echo $val>>$SSH_DIR/known_hosts 
            fi 
        fi 
        echo "copy $SSH_DIR to $ip" 
                   
        echo  "#!/usr/bin/expect">$TMP_SCRIPT 
        echo  "spawn scp -r  $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT 
        echo  "expect *assword*">>$TMP_SCRIPT 
        echo  "send $PASSWORD\r">>$TMP_SCRIPT 
        echo  "interact">>$TMP_SCRIPT 
           
        chmod +x $TMP_SCRIPT 
        #echo "/usr/bin/expect $TMP_SCRIPT" >$TMP_SCRIPT.do 
        #sh $TMP_SCRIPT.do& 
       
        /usr/bin/expect $TMP_SCRIPT 
        rm $TMP_SCRIPT 
        echo "copy done."                 
    fi 
done 
   
echo done.
 
 
在上面指令碼檔案的同目錄下新建名為host的檔案,將要建立ssh互信的機器名或ip地址新增到該檔案中,每個機器名或ip佔一行,如:
[root@server-202 ~]# vim /opt/host
192.168.10.202
192.168.10.203
192.168.10.205
192.168.10.206
192.168.10.207
192.168.10.208
 
最後就可以執行這個指令碼ssh_auth.sh檔案,ssh_auth.sh接受三個引數,遠端機器使用者名稱、密碼和host檔名(相對路徑或絕對路徑均可)。
[root@server-202 ~]# sh /opt/ssh_auth.sh root kevin123456 /opt/host
 
然後檢視下其他伺服器,發現.ssh目錄下的檔案和192.168.10.202機器的.ssh目錄下的檔案一致。
最後就可以在這些機器之間進行相互信任的ssh無密碼跳轉登入了!
 
==========================================================================
注意:上面指令碼針對的是伺服器ssh埠是22的情況,如果ssh是非22埠,比如是22222埠。
則只需要在ssh_auth.sh指令碼中修改下面兩行內容:
[root@server-202 ~]# cp /opt/ssh_auth.sh /opt/ssh_auth.sh.bak
[root@server-202 ~]# vim /opt/ssh_auth.sh              #注意下面一個小寫p,一個大寫P
.......
val=`ssh-keyscan $ip 2>/dev/null`
修改為
val=`ssh-keyscan -p 22222 $ip 2>/dev/null`
.......
echo  "spawn scp -r  $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
修改為
echo  "spawn scp -P 22222 -r  $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
 
[root@server-202 ~]# diff /opt/ssh_auth.sh /opt/ssh_auth.sh.bak
57c57
<             val=`ssh-keyscan -p 22222 $ip 2>/dev/null` 
---
>             val=`ssh-keyscan $ip 2>/dev/null` 
67c67
<         echo  "spawn scp -P 22222 -r  $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT 
---
>         echo  "spawn scp -r  $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
 
最後執行指令碼,進行相互信任關係批量部署即可
[root@server-202 ~]# sh /opt/ssh_auth.sh root kevin123456 /opt/host

相關文章