paramiko模块-2
如何用paramiko模块模拟登入服务器,并记录操作日志,起到审计的作用?
各个client ---(连接跳转机)--->(跳转机)------>各自的目标服务器。
目前我们公司的跳转机,只有跳转的功能(外网--->内网),没有其他功能。
可以用如下的demo进行日志记录等操作:
脚本登入服务器:
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import os import sys import select import socket tran = paramiko.Transport(('10.1.1.10', 22,)) 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('lbsweb', key) ''' tran.auth_password('ganzl', '123456') #通过密码认证 chan = tran.open_session()# 打开一个通道 chan.get_pty()# 获取一个终端 chan.invoke_shell()# 激活器 ''' chan创建的通道,用于接收服务器返回信息 利用sys.stdin,肆意妄为执行操作,用户在终端输入内容,并将内容发送至远程服务器 远程服务器执行命令,并将结果返回,用户终端显示内容. ''' while True: readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) # sys.stdin 处理用户输入 #只要发生变化,chan或者stdin或者都变化 if chan in readable: #远端有变化后捕获到 try: x = chan.recv(1024) #Transport的对象调用的start_client方法,就是sorcket,看这个start_client方法。 if len(x) == 0: print '\r\n*** EOF\r\n', break sys.stdout.write(x)#把内容输入到终端上显示 sys.stdout.flush() except socket.timeout: pass if sys.stdin in readable: #当终端有输入捕获到之后 inp = sys.stdin.readline() #把用户的那一行输入 chan.sendall(inp) #发送命令至远端 chan.close() tran.close()
脚本登入服务器并写日志:
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import os import sys import select import socket tran = paramiko.Transport(('10.1.1.10', 22,)) 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('lbsweb', key) ''' tran.auth_password('ganzl', '123456') #通过密码认证 chan = tran.open_session()# 打开一个通道 chan.get_pty()# 获取一个终端 chan.invoke_shell()# 激活器 file_log = open('log','a') ''' chan创建的通道,用于接收服务器返回信息 利用sys.stdin,肆意妄为执行操作,用户在终端输入内容,并将内容发送至远程服务器 远程服务器执行命令,并将结果返回,用户终端显示内容. ''' while True: readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) # sys.stdin 处理用户输入 #只要发生变化,chan或者stdin或者都变化 if chan in readable: #远端有变化后捕获到 try: x = chan.recv(1024) #Transport的对象调用的start_client方法,就是sorcket,看这个start_client方法。 if len(x) == 0: print '\r\n*** EOF\r\n', break sys.stdout.write(x)#把内容输入到终端上显示 sys.stdout.flush() except socket.timeout: pass if sys.stdin in readable: #当终端有输入捕获到之后 inp = sys.stdin.readline() #把用户的那一行输入 file_log.write(inp) chan.sendall(inp) #发送命令至远端 file_log.close() chan.close() tran.close()
脚本登入服务器,并且能操作[tab]等特殊键:(我的环境下日志写入有问题 python --version:Python 2.6.6)
这个修改终端模式,会不会对写日志有影响,再学习实验!!!待完善。
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import os import sys import select import socket import termios import tty tran = paramiko.Transport(('10.1.1.10', 22,)) 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('lbsweb', key) ''' tran.auth_password('ganzl', '123456') #通过密码认证 chan = tran.open_session()# 打开一个通道 chan.get_pty()# 获取一个终端 chan.invoke_shell()# 激活器 # 获取原tty属性 oldtty = termios.tcgetattr(sys.stdin) try: # 为tty设置新属性 # 默认当前tty设备属性: # 输入一行回车,执行 # CTRL+C 进程退出,遇到特殊字符,特殊处理。 # 这是为原始模式,不认识所有特殊符号 # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器 tty.setraw(sys.stdin.fileno()) #把远端更换为LINUX原始模式 chan.settimeout(0.0) file_log = open('log','a') while True: # 监视 用户输入 和 远程服务器返回数据(socket) # 阻塞,直到句柄可读 r, w, e = select.select([chan, sys.stdin], [], [], 1) if chan in r: try: x = chan.recv(1024) if len(x) == 0: file_log.close() print '\r\n*** EOF\r\n', break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: x = sys.stdin.read(1) if len(x) == 0: break if x == '\t': #判断用户的是否为tab如果为tab将不记录 pass else: file_log.write(x)#如果用户输入的命令保存至日志 chan.send(x) finally: # 重新设置终端属性 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) chan.close() tran.close()
windows下的操作:(我暂时用不到,等学到web操作终端的时候再回头看。)
def windows_shell(chan): import threading sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") def writeall(sock): while True: data = sock.recv(256) if not data: sys.stdout.write('\r\n*** EOF ***\r\n\r\n') sys.stdout.flush() break sys.stdout.write(data) sys.stdout.flush() writer = threading.Thread(target=writeall, args=(chan,)) writer.start() try: while True: d = sys.stdin.read(1) if not d: break chan.send(d) except EOFError: # user hit ^Z or F6 pass
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import sys import threading tran = paramiko.Transport(('10.1.1.10'', 22,)) tran.start_client() tran.auth_password('ganzl', '123456!') #通过密码认证 chan = tran.open_session()# 打开一个通道 chan.get_pty()# 获取一个终端 chan.invoke_shell()# 激活器 sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") def writeall(sock): while True: data = sock.recv(256) ''' SSH发送数据的也是通过socket进行发送数据的,那么我们就可以使用socket来获取远程机器发送回来的数据。 while循环一直接收数据,sock.recv(256)是阻塞的只有数据过来的时候才会继续走。 ''' if not data: sys.stdout.write('\r\n*** EOF ***\r\n\r\n') sys.stdout.flush() break sys.stdout.write(data) sys.stdout.flush() writer = threading.Thread(target=writeall, args=(chan,)) #创建了一个线程,去执行writeall方法,参数为chan(建立的SSH连接) writer.start() try: while True: #主线程循环 d = sys.stdin.read(1) #一直监听用户的输入,输入一个发送一个 if not d: break chan.send(d) except EOFError: # user hit ^Z or F6 pass chan.close() tran.close()
paramiko操作的更多详细,请看:
http://www.cnblogs.com/wupeiqi/articles/5095821.html
http://pythonpeixun.blog.51cto.com/7195558/1213929