paramiko模块-2

时间:2022-02-24 07:39:09

如何用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', '') #通过密码认证 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', '') #通过密码认证 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', '') #通过密码认证 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