python学习之路网络编程篇(第五篇)-续篇
Python堡垒机实现之基础知识
一般的堡垒机必须要具备以下5个基本功能:
1、权限控制 2、执行命令 3、上传下载文件 4、远程登录 5、记录操作
权限控制
说明:根据不同的登录用户分配不同的可管理的主机组。(再细分的权限就是根据不同的用户控制可在主机上执行的命令,一般不会限制的这么严格)
思路:使用数据库创建用户表,表字段有ID、用户名、密码、所属组,再创建主机表,表字段有ID,主机IP,所属组。其中用户表中的所属组和主机表中的所属组相对应,这样就能把两张表关联起来。当用户登录的时候就可以根据用户名去获取可管理的主机列表。
例子:这里只写出关于python连接mysql数据库的例子
执行命令:
说明:这里的执行命令一般是指批量执行命令,比如需要同时获取N台主机的主机名。
思路:使用paramiko模块来实现远程登录服务器并执行命令。使用multiprocessing来实现批量并发执行。
例子:(这里只写出paramiko模块远程密码登录服务器并执行命令的例子)
import paramiko class Paramiko_Manage(): def __init__(self,host,port,user,passwd): #初始化连接服务器所需要的参数 self.host = host self.port = port self.user = user self.passwd = passwd #使用密码认证 def connect(self): #连接方法,用来建立与服务器的连接 self.transport = paramiko.Transport((self.host,self.port)) self.transport.connect(username=self.user,password=self.passwd) print('connect') def close(self): #关闭方法,用来关闭与服务器的连接 self.transport.close() print('close') def cmd(self,command): #执行命令的方法,接收需要执行的命令作为参数 ssh = paramiko.SSHClient() ssh._transport = self.transport stdin, stdout, stderr = ssh.exec_command(command,timeout=3) print('command resluat: ',stdout.read()) def run(self,command): self.connect() #建立连接 self.cmd(command) #执行命令 self.close() #关闭连接 p = Paramiko_Manage('192.168.100.20',22,'test','123456') p.run('hostname') # 执行结果: # connect # command resluat: Test1 # # close
上传、下载文件:
说明:批量上传文件相对比较简单,如果是批量下载文件还需要考虑到多台服务器文件重名的问题。
还需要考虑到文件上传后比较大小以确认是否上传下载成功。
思路:使用paramiko模块来实现远程上传下载文件。使用multiprocessing来实现批量并发执行。
例子:(这里只写出paramiko模块远程秘钥认证登录服务器并执行命令的例子)
import paramiko import os class Paramiko_Manage(): def __init__(self,host,port,user,key): self.host = host self.port = port self.user = user keyfile = os.path.expanduser(key) #使用秘钥认证 self.key = paramiko.RSAKey.from_private_key_file(keyfile) def connect(self): self.transport = paramiko.Transport((self.host,self.port)) self.transport.connect(username=self.user,pkey=self.key) print('connect') def close(self): self.transport.close() print('close') def trans(self,file1,file2): #传输文件的方法 sftp = paramiko.SFTPClient.from_transport(self.transport) file1 = '%s_%s' % (file1, self.host) #修改下载文件的保存文件名 sftp.get(file2,file1) file1_size = os.path.getsize(file1) #获取下载文件的大小 file2_size = int(str(sftp.stat(file2)).split()[4]) #获取远程文件的大小 if file1_size == file2_size: #比较两个文件大小 print('File trans done') def run(self,file1,file2): self.connect() #建立连接 self.trans(file1,file2) #传输文件 self.close() #关闭连接 p = Paramiko_Manage('192.168.100.20',22,'test2','~/.ssh/id_rsa') p.run('/root/hosts','/etc/hosts') # 执行结果: # connect # File trans done # close
远程登录和记录操作:
说明:通过堡垒机ssh远程连接到服务器,并执行操作,和在终端执行操作的效果一样。
思路:使用paramiko实现远程连接服务器的功能,使用sys.stdin和select处理用户输入和接受返回结果。
例子:
import paramiko import select import sys import socket import os tran = paramiko.Transport((host,port)) #连接服务器,host和port自定义 tran.start_client() default_path = os.path.join(os.environ['HOME'],'.ssh','id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('root',key) chan = tran.open_session() #打开一个通道 chan.get_pty() #获取一个终端 chan.invoke_shell() #激活器 f = open('log.log','a') #打开一个文件用于写入执行的操作 while True: # 监视用户输入和服务器返回数据 # sys.stdin 处理用户输入 # chan 是之前创建的通道,用于接收服务器返回信息 readable,writeable,error = select.select([chan,sys.stdin,],[],[],1) if chan in readable: #接受命令的返回结果 try: x = chan.recv(1024) if len(x) == 0: print('\r\n*** EOF\r\n',) f.close() #退出时关闭记录文件 break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in readable: #处理用户输入发送到服务器执行 inp = sys.stdin.readline() f.write(inp) #记录用户输入 chan.sendall(inp) chan.close() tran.close()