唐伯虎 发表于 2021-6-23 22:36:12

脚本自动配置ssh互信

前言
此脚本虽然是python脚本,但是里面调用了太多os.system命令(囧,哥的python太水了),只要懂shell脚本,就可用shell来完成自动配置ssh互信脚本。为何当初没有使用except,因为本公司的centos中没有携带except安装包,centos还是精简版,很多依赖包都没有。我不想太折腾。
我会一点python,使用python是理所当然的。原计划用python paramiko模块来实现密码放文件里登陆,但是paramiko安装编译需要gcc环境。精简的centos也没有,弄了半天,几十个依赖包弄得我头晕眼花,大小达到50M,不通用,懒得做了。
现在的这个脚本需要手动输入远程主机密码,不适用于成百上千台服务器部署ssh互信。在网上找了很久,确认ssh 不支持脚本输入密码。
由于我的业务上经常也就同时做10台以内的ssh互信,这个脚本就满足需求了。
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次。这个怎么破?见代码。

执行效果

#python ssh_trust.pyInput 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!Input node's info. Usage:hosta/192.168.0.101. Press Enter is complete.Please input Node info:nodeb/192.168.2.158check ip address success!Input node's info. Usage:hosta/192.168.0.101. Press Enter is complete.Please input Node info:Are you sure you wantto 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@VueOSThe key's randomart p_w_picpath 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)? yesWarning: Permanently added'nodeb,192.168.2.158' (RSA) to the list of known hosts.root@nodeb's password:#输入远端节点密码copy ssh file successfulDoneWarning: Permanently added'nodea,192.168.2.151' (RSA) to the list of known hosts.local nodea RsaKey remote nodea issuccessfullocal nodea RsaKey remote nodeb issuccessfulknown_hosts                                                                                    100%802   0.8KB/s00:00    hosts                                                                                             100%   84    0.1KB/s   00:00   
#ssh nodebLast login: Fri Apr4 15:34:06 2014 from 192.168.2.72#exitlogoutConnection to nodeb closed.# ssh nodeaLast login: Fri Apr4 11:55:58 2014 from hosta# exitlogoutConnection to nodea closed.#如上所示,互信自动配置成功。
脚本代码

# cat ssh_trust.py!/usr/bin/python
import datetime
import os,sys,time
import commands这个函数是校验IP合法性的。
def check_ip(ipaddr):

      import sys
      addr=ipaddr.strip().split('.')
      #print addr
      if len(addr) != 4:
                print "check ip address failed!"
                sys.exit()
      for i in range(4):
                try:
                        addr=int(addr)
                except:
                        sys.exit()
                if addr<=255 and addr>=0:
                        pass
                else:
                        print "check ip address failed!"
                        sys.exit()
                i+=1
      else:
                print "check ip address success!"  node_dict={}
  host_all=[]
host_ip_all={}
这个函数获取输入的节点信息,并校验输入的IP是否合法。

  def get_nodes():

      while True:
                node=raw_input("""Input node's info. Usage: hosta/192.168.0.101. Press Enter is complete.  Please input Node info:""")

                if len(node)==0:
                              return 2
                node_result=node.strip().split('/')
                host_ip_all]=,'']
                #print node_result
                if len(node_result)==0:
                        print "Hostname is failed!"
                        sys.exit()
                check_ip(node_result)
                #node_dict]=]
                host_all.append(node_result)
                #print node_dict
                local_ip_status,local_ip_result=commands.getstatusoutput("""ifconfig |grep 'inet addr'|awk -F '[: ]+' '{print $4}' """)
                local_ip=local_ip_result.split('\n')
                #print host_all
                if len(host_all)==1:
                        if node_result in local_ip:
                              pass
                        else:
                              print "The first IP must be native IP."
                              sys.exit()
这个函数生成ssh密钥文件,简单的3条shell命令

  def create_sshkey_file():

      os.system("rm -rf ~/.ssh/")
      os.system("/usr/bin/ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''    ")
      os.system("cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys")
这个函数配置/etc/hosts文件

  def add_etc_hosts():
  for i in host_ip_all.keys():

      #print host_ip_all.keys()
      #判断/etc/hosts是否存在
      if os.path.exists('/etc/hosts'):
                pass
      else:
                os.system("touch /etc/hosts")
      #删除掉原有主机名项,并添加新的对应关系
      os.system("sed -i '/%s/d' /etc/hosts"%i)
      #print i,host_ip_all
      os.system(''' echo '%s %s\r' >>/etc/hosts '''%(host_ip_all,i))
      #with open('/etc/hosts','ab') as f :
      #       f.write('%s%s\r'%(host_ip_all,i))
拷贝ssh密钥文件

  def scp_sshkey():

      #把/root/.ssh文件放在/tmp下,并开使其生效。
      os.system("sed -i /tmp/d /etc/exports")
      os.system("echo '/tmp *(rw)' >>/etc/exports")
      os.system("exportfs -r")
      os.system("cp -a /root/.ssh /tmp")
      os.system("chmod 777 /tmp")
      os.system("/etc/init.d/iptables stop")
      os.system("chmod 777 /tmp/.ssh/id_rsa")
      os.system("chmod 777 /tmp/.ssh")
      print 'Scp ssh key file too another node...'
      print host_all
      localhost=host_all
      local_ip=host_ip_all
      #输入一次密码,登陆上去后执行了N条命令,挂载nfs,拷贝.ssh,修改权限,卸载等等。
      for i in host_all:
                os.system('''/usr/bin/ssh %s "/bin/umount -lf /mnt >/dev/null 2 &>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 "'''%(i,local_ip))
      print "Done"
测试ssh互信是否成功

  def test_sshkey(host):
  for host_n in host_all:

      try:
                #to gain public key
                #使用StrictHostKeyChecking跳过公钥接收提示。并远程执行命令,连上了自然会输出成功信息。
                os.system(''' ssh-o"StrictHostKeyChecking no" %s "echo -e local %s RsaKey remote %sis successful" '''%(host_n,host_all,host_n))
      except:
                print "\033,host_n)  else:

      #全部测试完成后,把known_hosts文件拷贝到所有主机。一台服务器获取了所有公钥,那拷贝到远端自然是所有节点都有对方公钥了。
      for host_m in host_all:
                #copy ~/.ssh/known_hosts file to another host...
                os.system("""/usr/bin/scp ~/.ssh/known_hosts %s:~/.ssh/known_hosts"""%host_m)
                # copy hosts file to another host...
                os.system("""/usr/bin/scp /etc/hosts %s:/etc/hosts """%host_m)
函数执行部分

  get_nodes()
a=raw_input("Are you sure you wantto set ssh mutual trust? (yes/no) ").strip()
提示一下,做不做互信要让用户选择。

  if a=="yes":

      create_sshkey_file()
      add_etc_hosts()
      scp_sshkey()
      test_sshkey('192.168.2.73')elif a=="no":
输入no就代表互信已做好了。接下来执行别的代码。


      pass  else:

      print 'Byebye,Please input yes or no.'      sys.exit()


页: [1]
查看完整版本: 脚本自动配置ssh互信