天天看點

腳本自動配置ssh互信

此腳本雖然是python腳本,但是裡面調用了太多os.system指令(囧,哥的python太水了),隻要懂shell腳本,就可用shell來完成自動配置ssh互信腳本。為何當初沒有使用except,因為本公司的centos中沒有攜帶except安裝包,centos還是精簡版,很多依賴包都沒有。我不想太折騰。

我會一點python,使用python是理所當然的。原計劃用python paramiko子產品來實作密碼放檔案裡登陸,但是paramiko安裝編譯需要gcc環境。精簡的centos也沒有,弄了半天,幾十個依賴包弄得我頭暈眼花,大小達到50M,不通用,懶得做了。

現在的這個腳本需要手動輸入遠端主機密碼,不适用于成百上千台伺服器部署ssh互信。在網上找了很久,确認ssh 不支援腳本輸入密碼。

由于我的業務上經常也就同時做10台以内的ssh互信,這個腳本就滿足需求了。

1、不互動自動生成密鑰檔案

用ssh-keygen 的-f和-P參數,生成密鑰不需要互動。如下:

       rm -rf ~/.ssh/

      /usr/bin/ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''

      cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys

2、自動添加/etc/hosts中主機名與IP對應關系,并推送到遠端主機

這個簡單,手動配置或腳本配置都行。互信成功後,用腳本批量推送就行了。

3、推送密鑰檔案至遠端主機

最簡單的方法:scp  -r /root/.ssh root@hostb:/root

但是咱公司精簡的centos沒有關閉selinux。拷貝過去還是不能無密碼登陸(不信可自己測試)。如果采用輸入兩次密碼,第一次登陸上去關閉selinux,第二次拷貝/root/.ssh過去也可以(不想梅開二度)。我采用的是另一種方法,隻需輸入一次密碼即可。怎麼實作的?見代碼。

第一次登陸互動需要輸入yes擷取對端公鑰

     .ssh檔案拷貝過去後,第一次登陸會讓你輸入yes接收公鑰,而且,不止自己登陸對方要輸入yes,每一台登陸遠端主機都要輸入yes,如果一共10台伺服器,每台輸入9次,共需要輸入81次。這個怎麼破?見代碼。

[root@VueOS scripts]#python ssh_trust.py

Input node's info. Usage:hosta/192.168.0.101. Press Enter is complete.

Please input Node info: nodea/192.168.2.151

#擷取節點資訊,主機名與IP,生産中盡量使用主機名,友善以後環境遷移

check ip address success!

Please input Node info:  nodeb/192.168.2.158

Please input Node info:  

Are you sure you want  to set ssh mutual trust? (yes/no) yes

#是否要設定互信?因為本次互信是我部署其它程式的前提。互信一次就能配置成功,程式可能多次失敗,不需要每次運作都做互信。

Generating public/private rsa key pair.

Created directory '/root/.ssh'.

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:

79:97:67:36:e5:db:0d:4c:8e:20:63:a2:59:f6:bf:17root@VueOS

The key's randomart image is:

+--[ RSA 2048]----+

|                 |

|     + + .   . .|

|    = + + . * o |

|   o   S . + O .|

|        o .E+ o+|

|         .  . .o|

|          ..    |

|         ..     |

+-----------------+

#自動生成完密鑰後,把密鑰拷貝到其它節點

Scp ssh key file too another node...

The authenticity of host 'nodeb(192.168.2.158)' can't be established.

RSA key fingerprint isc6:2d:8e:e0:a1:e1:2e:c3:77:c7:1d:ef:92:7c:41:ba.

Are you sure you want to continueconnecting (yes/no)? yes

Warning: Permanently added'nodeb,192.168.2.158' (RSA) to the list of known hosts.

root@nodeb's password:

#輸入遠端節點密碼

copy ssh file successful

Done

Warning: Permanently added'nodea,192.168.2.151' (RSA) to the list of known hosts.

local nodea RsaKey remote nodea issuccessful

local nodea RsaKey remote nodeb issuccessful

known_hosts                                                                                      100%  802     0.8KB/s  00:00    

hosts                                                                                             100%   84    0.1KB/s   00:00    

[root@VueOS scripts]#ssh nodeb

Last login: Fri Apr  4 15:34:06 2014 from 192.168.2.72

[root@VueOS ~]#exit

logout

Connection to nodeb closed.

[root@VueOS scripts]# ssh nodea

Last login: Fri Apr  4 11:55:58 2014 from hosta

[root@VueOS ~]# exit

Connection to nodea closed.

#如上所示,互信自動配置成功。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

<code>[root@VueOS scripts]</code><code># cat ssh_trust.py</code>

<code>#!/usr/bin/python</code>

<code>import</code> <code>datetime</code>

<code>import</code> <code>os,sys,time</code>

<code>import</code> <code>commands</code>

<code>#這個函數是校驗IP合法性的。</code>

<code>def</code> <code>check_ip(ipaddr):</code>

<code>        </code><code>import</code> <code>sys</code>

<code>        </code><code>addr</code><code>=</code><code>ipaddr.strip().split(</code><code>'.'</code><code>)</code>

<code>        </code><code>#print addr</code>

<code>        </code><code>if</code> <code>len</code><code>(addr) !</code><code>=</code> <code>4</code><code>:</code>

<code>                </code><code>print</code> <code>"check ip address failed!"</code>

<code>                </code><code>sys.exit()</code>

<code>        </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>4</code><code>):</code>

<code>                </code><code>try</code><code>:</code>

<code>                        </code><code>addr[i]</code><code>=</code><code>int</code><code>(addr[i])</code>

<code>                </code><code>except</code><code>:</code>

<code>                        </code><code>sys.exit()</code>

<code>                </code><code>if</code> <code>addr[i]&lt;</code><code>=</code><code>255</code> <code>and</code> <code>addr[i]&gt;</code><code>=</code><code>0</code><code>:</code>

<code>                        </code><code>pass</code>

<code>                </code><code>else</code><code>:</code>

<code>                        </code><code>print</code> <code>"check ip address failed!"</code>

<code>                </code><code>i</code><code>+</code><code>=</code><code>1</code>

<code>        </code><code>else</code><code>:</code>

<code>                </code><code>print</code> <code>"check ip address success!"</code>

<code>node_dict</code><code>=</code><code>{}</code>

<code>host_all</code><code>=</code><code>[]</code>

<code>host_ip_all</code><code>=</code><code>{}</code>

<code>#這個函數擷取輸入的節點資訊,并校驗輸入的IP是否合法。</code>

<code>def</code> <code>get_nodes():</code>

<code>        </code><code>while</code> <code>True</code><code>:</code>

<code>                </code><code>node</code><code>=</code><code>raw_input</code><code>(</code><code>"""Input node's info. Usage: hosta/192.168.0.101. Press Enter is complete.</code>

<code>Please input Node info:  """</code><code>)</code>

<code>                </code><code>if</code> <code>len</code><code>(node)</code><code>=</code><code>=</code><code>0</code><code>:</code>

<code>                                </code><code>return</code> <code>2</code>

<code>                </code><code>node_result</code><code>=</code><code>node.strip().split(</code><code>'/'</code><code>)</code>

<code>                </code><code>host_ip_all[node_result[</code><code>0</code><code>]]</code><code>=</code><code>[node_result[</code><code>1</code><code>],'']</code>

<code>                </code><code>#print node_result</code>

<code>                </code><code>if</code> <code>len</code><code>(node_result[</code><code>0</code><code>])</code><code>=</code><code>=</code><code>0</code><code>:</code>

<code>                        </code><code>print</code> <code>"Hostname is failed!"</code>

<code>                </code><code>check_ip(node_result[</code><code>1</code><code>])</code>

<code>                </code><code>#node_dict[node_result[0]]=[node_result[1]]</code>

<code>                </code><code>host_all.append(node_result[</code><code>0</code><code>])</code>

<code>                </code><code>#print node_dict</code>

<code>                </code><code>local_ip_status,local_ip_result</code><code>=</code><code>commands.getstatusoutput(</code><code>"""ifconfig |grep 'inet addr'|awk -F '[: ]+' '{print $4}' """</code><code>)</code>

<code>                </code><code>local_ip</code><code>=</code><code>local_ip_result.split(</code><code>'\n'</code><code>)</code>

<code>                </code><code>#print host_all</code>

<code>                </code><code>if</code> <code>len</code><code>(host_all)</code><code>=</code><code>=</code><code>1</code><code>:</code>

<code>                        </code><code>if</code> <code>node_result[</code><code>1</code><code>] </code><code>in</code> <code>local_ip:</code>

<code>                                </code><code>pass</code>

<code>                        </code><code>else</code><code>:</code>

<code>                                </code><code>print</code> <code>"The first IP must be native IP."</code>

<code>                                </code><code>sys.exit()</code>

<code>#這個函數生成ssh密鑰檔案,簡單的3條shell指令</code>

<code>def</code> <code>create_sshkey_file():</code>

<code>        </code><code>os.system(</code><code>"rm -rf ~/.ssh/"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"/usr/bin/ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''    "</code><code>)</code>

<code>        </code><code>os.system(</code><code>"cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys"</code><code>)</code>

<code>#這個函數配置/etc/hosts檔案</code>

<code>def</code> <code>add_etc_hosts():</code>

<code>    </code><code>for</code> <code>i </code><code>in</code> <code>host_ip_all.keys():</code>

<code>        </code><code>#print host_ip_all.keys()</code>

<code>        </code><code>#判斷/etc/hosts是否存在</code>

<code>        </code><code>if</code> <code>os.path.exists(</code><code>'/etc/hosts'</code><code>):</code>

<code>                </code><code>pass</code>

<code>                </code><code>os.system(</code><code>"touch /etc/hosts"</code><code>)</code>

<code>        </code><code>#删除掉原有主機名項,并添加新的對應關系</code>

<code>        </code><code>os.system(</code><code>"sed -i '/%s/d' /etc/hosts"</code><code>%</code><code>i)</code>

<code>        </code><code>#print i,host_ip_all[i][0]</code>

<code>        </code><code>os.system(</code><code>''' echo '%s %s\r' &gt;&gt;/etc/hosts '''</code><code>%</code><code>(host_ip_all[i][</code><code>0</code><code>],i))</code>

<code>        </code><code>#with open('/etc/hosts','ab') as f :</code>

<code>        </code><code>#       f.write('%s  %s\r'%(host_ip_all[i][0],i))</code>

<code>#拷貝ssh密鑰檔案</code>

<code>def</code> <code>scp_sshkey():</code>

<code>        </code><code>#把/root/.ssh檔案放在/tmp下,并開使其生效。</code>

<code>        </code><code>os.system(</code><code>"sed -i /tmp/d /etc/exports"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"echo '/tmp *(rw)' &gt;&gt;/etc/exports"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"exportfs -r"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"cp -a /root/.ssh /tmp"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"chmod 777 /tmp"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"/etc/init.d/iptables stop"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"chmod 777 /tmp/.ssh/id_rsa"</code><code>)</code>

<code>        </code><code>os.system(</code><code>"chmod 777 /tmp/.ssh"</code><code>)</code>

<code>        </code><code>print</code> <code>'Scp ssh key file too another node...'</code>

<code>        </code><code>print</code> <code>host_all[</code><code>1</code><code>:]</code>

<code>        </code><code>localhost</code><code>=</code><code>host_all[</code><code>0</code><code>]</code>

<code>        </code><code>local_ip</code><code>=</code><code>host_ip_all[localhost][</code><code>0</code><code>]</code>

<code>        </code><code>#輸入一次密碼,登陸上去後執行了N條指令,挂載nfs,拷貝.ssh,修改權限,解除安裝等等。</code>

<code>        </code><code>for</code> <code>i </code><code>in</code> <code>host_all[</code><code>1</code><code>:]:</code>

<code>                </code><code>os.system(</code><code>'''/usr/bin/ssh %s "/bin/umount -lf /mnt &gt;/dev/null 2 &amp;&gt;1;/bin/mount %s:/tmp /mnt ;rm -rf /root/.ssh;mkdir /root/.ssh;sleep 3; /bin/cp -a /mnt/.ssh/* /root/.ssh/ ;echo 'copy ssh file successful';/bin/chmod 600 /root/.ssh/id_rsa;/bin/chmod 700 /root/.ssh;/bin/umount -lf /mnt "'''</code><code>%</code><code>(i,local_ip))</code>

<code>        </code><code>print</code> <code>"Done"</code>

<code>#測試ssh互信是否成功</code>

<code>def</code> <code>test_sshkey(host):</code>

<code>    </code><code>for</code> <code>host_n </code><code>in</code> <code>host_all:</code>

<code>        </code><code>try</code><code>:</code>

<code>                </code><code>#to gain public key</code>

<code>                </code><code>#使用StrictHostKeyChecking跳過公鑰接收提示。并遠端執行指令,連上了自然會輸出成功資訊。</code>

<code>                </code><code>os.system(</code><code>''' ssh  -o  "StrictHostKeyChecking no" %s "echo -e local %s RsaKey remote %s  is successful" '''</code><code>%</code><code>(host_n,host_all[</code><code>0</code><code>],host_n))</code>

<code>        </code><code>except</code><code>:</code>

<code>                </code><code>print</code> <code>"\033[31mlocal %s RsaKey remote %s is fail.\033[0m"</code><code>%</code><code>(host_all[</code><code>0</code><code>],host_n)</code>

<code>else</code><code>:</code>

<code>        </code><code>#全部測試完成後,把known_hosts檔案拷貝到所有主機。一台伺服器擷取了所有公鑰,那拷貝到遠端自然是所有節點都有對方公鑰了。</code>

<code>        </code><code>for</code> <code>host_m </code><code>in</code> <code>host_all[</code><code>1</code><code>:]:</code>

<code>                </code><code>#copy ~/.ssh/known_hosts file to another host...</code>

<code>                </code><code>os.system(</code><code>"""/usr/bin/scp ~/.ssh/known_hosts %s:~/.ssh/known_hosts"""</code><code>%</code><code>host_m)</code>

<code>                </code><code># copy hosts file to another host...</code>

<code>                </code><code>os.system(</code><code>"""/usr/bin/scp /etc/hosts %s:/etc/hosts """</code><code>%</code><code>host_m)</code>

<code>#函數執行部分</code>

<code>get_nodes()</code>

<code>a</code><code>=</code><code>raw_input</code><code>(</code><code>"Are you sure you want  to set ssh mutual trust? (yes/no) "</code><code>).strip()</code>

<code>#提示一下,做不做互信要讓使用者選擇。</code>

<code>if</code> <code>a</code><code>=</code><code>=</code><code>"yes"</code><code>:</code>

<code>        </code><code>create_sshkey_file()</code>

<code>        </code><code>add_etc_hosts()</code>

<code>        </code><code>scp_sshkey()</code>

<code>        </code><code>test_sshkey(</code><code>'192.168.2.73'</code><code>)</code>

<code>elif</code> <code>a</code><code>=</code><code>=</code><code>"no"</code><code>:</code>

<code>#輸入no就代表互信已做好了。接下來執行别的代碼。</code>

<code>        </code><code>pass</code>

<code>        </code><code>print</code> <code>'Byebye,Please input yes or no.'</code>

<code>        </code><code>sys.exit()</code>

<code></code>