Python Paramiko模块实战:SSH客户端与服务端实现详解
本文详解Python Paramiko模块的实际应用,涵盖SSH客户端与服务端的实现方案。通过具体代码案例,演示如何利用SSHClient执行远程命令,包括直接调用与基于Transport对象两种方式。同时介绍继承ServerInterface构建SSH服务端的方法,以及使用SFTPClient进行文件上传和下载的完整流程,帮助开发者快速掌握Python远程运维核心技能。
本文主要探讨Python中Paramiko模块的实际应用案例,具体内容如下。
Windows平台下存在众多优秀的SSH客户端工具,例如Putty。在Python生态中,虽然可以通过原始套接字结合加密函数自行开发SSH客户端或服务端,但若已有成熟模块可用,便无需重复造轮子。借助Paramiko库配合PyCrypto,可以便捷地实现SSH2协议通信。
Paramiko的安装教程在网上已十分丰富,此处不再赘述。重点在于讲解其具体用法。Paramiko对SSH2协议的支持主要从两个维度展开:SSH客户端与服务端。
首先梳理以下核心概念:
- SSHClient:封装了Channel、Transport及SFTPClient。
- Channel:一种类似Socket的安全SSH传输通道。
- Transport:代表一个加密会话(此时Session尚未建立),并创建了一个名为Channel的加密隧道。
- Session:用于保持Client与Server连接的对象,通过connect()/start_client()/start_server()方法启动会话。
详细参考请查阅Paramiko官方文档:http://docs.paramiko.org/en/2.0/index.html
以下提供几个常用场景的使用案例:
SSH客户端实现方案一:直接执行远程命令
该方案直接利用SSHClient对象的exec_command()方法在服务端执行命令,具体代码如下:
#实例化SSHClient client = paramiko.SSHClient() #自动添加策略,保存服务器的主机名和密钥信息 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接SSH服务端,以用户名和密码进行认证 client.connect(ip,username=user,password=passwd) #打开一个Channel并执行命令 stdin,stdout,stderr = client.exec_command(command) #打印执行结果 print stdout.readlines() #关闭SSHClient client.close()
SSH客户端实现方案二:基于Transport执行远程命令
此方案先通过SSHClient建立连接获取Transport对象,再利用Transport对象的exec_command()在服务端执行命令,具体代码如下:
#实例化SSHClient client = paramiko.SSHClient() #自动添加策略,保存服务器的主机名和密钥信息 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接SSH服务端,以用户名和密码进行认证 client.connect(ip,username=user,password=passwd) #实例化Transport,并建立会话Session ssh_session = client.get_transport().open_session() if ssh_session.active: ssh_session.exec_command(command) print ssh_session.recv(1024) client.close()
SSH服务端的实现
构建SSH服务端需继承ServerInterface,并实现其中相应方法。具体代码如下:
import socket
import sys
import threading
import paramiko
host_key = paramiko.RSAKey(filename='private_key.key')
class Server(paramiko.ServerInterface):
def __init__(self):
#执行start_server()方法首先会触发Event,如果返回成功,is_active返回True
self.event = threading.Event()
#当is_active返回True,进入到认证阶段
def check_auth_password(self, username, password):
if (username == 'root') and (password == '123456'):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
#当认证成功,client会请求打开一个Channel
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
#命令行接收ip与port
server = sys.argv[1]
ssh_port = int(sys.argv[2])
#建立socket
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP socket
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, ssh_port))
sock.listen(100)
print '[+] Listening for connection ...'
client, addr = sock.accept()
except Exception, e:
print '[-] Listen failed: ' + str(e)
sys.exit(1)
print '[+] Got a connection!'
try:
#用sock.accept()返回的socket实例化Transport
bhSession = paramiko.Transport(client)
#添加一个RSA密钥加密会话
bhSession.add_server_key(host_key)
server = Server()
try:
#启动SSH服务端
bhSession.start_server(server=server)
except paramiko.SSHException, x:
print '[-] SSH negotiation failed'
chan = bhSession.accept(20)
print '[+] Authenticated!'
print chan.recv(1024)
chan.send("Welcome to my ssh")
while True:
try:
command = raw_input("Enter command:").strip("\n")
if command != 'exit':
chan.send(command)
print chan.recv(1024) + '\n'
else:
chan.send('exit')
print 'exiting'
bhSession.close()
raise Exception('exit')
except KeyboardInterrupt:
bhSession.close()
except Exception, e:
print '[-] Caught exception: ' + str(e)
try:
bhSession.close()
except:
pass
sys.exit(1)
使用SFTP上传文件
import paramiko
#获取Transport实例
tran = paramiko.Transport(("host_ip",22))
#连接SSH服务端
tran.connect(username = "username", password = "password")
#获取SFTP实例
sftp = paramiko.SFTPClient.from_transport(tran)
#设置上传的本地/远程文件路径
localpath="/root/Desktop/python/NewNC.py"
remotepath="/tmp/NewNC.py"
#执行上传动作
sftp.put(localpath,remotepath)
tran.close()
使用SFTP下载文件
import paramiko
#获取SSHClient实例
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#连接SSH服务端
client.connect("host_ip",username="username",password="password")
#获取Transport实例
tran = client.get_transport()
#获取SFTP实例
sftp = paramiko.SFTPClient.from_transport(tran)
remotepath='/tmp/NewNC.py'
localpath='/root/Desktop/NewNC.py'
sftp.get(remotepath, localpath)
client.close()
总结
以上内容为Python Paramiko模块使用的实际案例全解,希望能对大家有所帮助。感兴趣的朋友可继续查阅本站其他相关专题,如有不足之处,欢迎留言指正。感谢各位对本站的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









