「PYTHON」- Paramiko:连接 SSH 服务

Paramiko 是 Python 实现 SSHv2 协议的模块,它支持口令认证和公钥认证两种方式。我们能够基于Paramiko模块编写Python代码,实现SSH相关功能。

它可以实现安全的远程命令执行、文件传输等功能。

组件架构(架构概述)

Paramiko 组件如下图所示,最常用的两个类为 SSHClient 类和 SFTPClient 类,分别提供 SSH 和 SFTP 功能。

我们将主要学习四个类的相关方法:Transport类,Key handling类,SSHClient类,SFTPClient类;

常用协议类

Channel:该类用于创建在 SSH Transport 上的安全通道。Channel类包含执行命令,请求X11会话,发送数据,打开交互式会话等方法。通常这些来自Channel类的常用方法已包装在 SSHClient 中。

Message:SSH Message是字节流,该类包含向流中写入字节,提取字节等方法。该类对字符串、整数、bools、无限精度整数(Python中称为long)的某些组合进行编码。

Packetizer:数据包处理类。Packetizer类包含检查握手,获取channel ID等方法。

Transport:该类用于在现有套接字或类套接字对象上创建一个Transport会话对象。Transport类包含公钥认证,打开channel通道等方法。

SFTPClient:该类通过一个打开的SSH Transport会话创建SFTP会话通道并执行远程文件操作。SSHClient类包含建立连接,打开交互式会话等方法。

SSHClient:SSHClient类是与SSH服务器会话的高级表示。该类集成了Transport,Channel和SFTPClient类。SFTPClient类包含文件上传,文件下载等方法。

密钥相关类

SSH Agent类:该类用于SSH代理。

Host keys类:该类与OpenSSH known_hosts文件相关,用于创建一个host keys对象。

Key handling类:该类用于创建对应密钥类型的实例,如RSA密钥,DSS(DSA)密钥。

Transport 及其方法介绍

一个SSH Transport连接到一个流(通常为套接字),协商加密会话,进行认证。后续可在加密会话上创建通道。多个通道可以在单个会话连接中多路复用(事实上经常如此,如端口转发)。

如下为方法示例:

tran = paramiko.Transport(('192.168.56.100',22)) 
tran.connect(username=‘client’,password=‘test’)

# Transport(sock):建立Transport对象,实例化SSH会话通道。
# connect(username="",password=None,pkey=None):建立SSH会话连接,并使用密码或私钥进行身份认证。
# close():关闭会话。

# 为了便于使用,可以传入地址(作为元组)或主机字符串作为sock参数。
# 主机字符串是具有可选端口(以“:”分隔)的主机名,该端口将转换为(主机名,端口)的元组。

Key handling 及其方法介绍

Key handling:用于创建对应密钥类型的实例,如RSA密钥,DSS(DSA)密钥。这个类包含了密钥的读取,写入等相关方法。

如下为方法示例:

key=paramiko.RSAKey.from_private_key_file(r'C:\Users\exampleuser\.ssh\id_rsa')

# RSAKey.from_private_key_file(filename):从文件读取RSA私钥来创建密钥对象。
# DSSKey.from_private_key_file(filename):从文件读取DSS私钥来创建密钥对象。

SFTPClient 及其方法介绍

SFTPClient类通过一个打开的SSH Transport会话通道创建SFTP会话连接并执行远程文件操作。

如下为典型用例:

key=paramiko.RSAKey.from_private_key_file(r'C:\Users\exampleuser\.ssh\id_rsa')
tran = paramiko.Transport(('192.168.56.100',22)) 
tran.connect(username=‘client’, pkey=key)
sftp = paramiko.SFTPClient.from_transport(tran) 

local_path=r'C:\Users\exampleuser\.ssh\vrptest.cfg'
remote_path= '/vrpcfg.cfg'
sftp.get(remote_path, local_path) 

# from_transport()	从打开的Transport创建一个SFTP会话连接。
# get()	下载指定文件。
# put()	上传指定文件。

from_transport()

from_transport():从开启的Transport通道创建一个SFTP客户端通道。

如下为方法示例:

T = paramiko.Transport((‘192.168.56.100’,22)) 
sftp = paramiko.SFTPClient.from_transport(T,window_size=None, max_packet_size=None)

# T	一个认证过的开启的Transport会话。
# window_size	可选参数,SFTP会话窗口大小。
# max_packet_size	可选参数,SFTP会话最大数据包大小。

get()

将远程文件(remotepath)从SFTP服务器复制到本地主机的指定路径中(localpath),操作引发的任何异常都将被传递。
如下为方法示例:

local_path=r'C:\Users\exampleuser\.ssh\vrptest.cfg'
remote_path= '/vrpcfg.cfg'
sftp.get(remote_path, local_path) 

# remotepath	远程文件。
# localpath	本地主机的目的路径,该路径应包含文件名,仅指定目录可能会导致错误。

put()

将本地文件(localpath)从本地主机复制到SFTP服务器的指定路径中(remotepath),操作引发的任何异常都将被传递。
如下为方法示例:

local_path=r'C:\Users\exampleuser\.ssh\vrptest.cfg'
remote_path= '/vrpcfg.cfg'
sftp.put(localpath, remotepath)

# localpath	本地文件。
# remotepath	SFTP服务器上的目的路径,该路径应包含文件名,仅指定目录可能会导致错误。

SSHClient 及其方法介绍

SSHClient类是与SSH服务器会话的高级表示。这个类已经包装 Transport类、Channel类、SFTPClient类来进行会话通道的建立和鉴权认证。

如下为一个典型用例:

client=paramiko.client.SSHClient()
client.connect(hostname=‘192.168.56.100’,port=22,username=‘client’,password=‘123456’)
stdin,stdout,stderr=client.exec_command(‘ls –l’)

connect()

实现远程服务器的连接与认证。

client.connect(hostname='192.168.56.100',port=22,username=‘client',key_filename='id_rsa')
client.connect(hostname='192.168.56.100',port=22,username=‘client',password=‘123456')

hostname	连接的目标主机,只有该参数为必选参数。
port	指定端口,默认为22。
username	进行认证的用户名,默认为空。
password	进行认证的用户密码,默认为空。
key_filename	一个文件名或文件列表,指定私钥文件,默认为空。
pkey	用于身份验证的私钥。

set_missing_host_key_policy()

设置连接到没有已知主机密钥的服务器时使用的策略。

client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())

AutoAddPolicy	自动添加主机名及主机密钥到本地HostKeys对象,不依赖load_system_host_key的配置。即新建立ssh连接时不需要再输入yes或no进行确认。
WarningPolicy	用于记录一个未知的主机密钥的python警告并接受,功能上和AutoAddPolicy类似,但是会提示是新连接。
RejectPolicy	自动拒绝未知的主机名和密钥,依赖load_system_host_key的配置,此为默认选项。

load_system_host_keys()

从系统文件加载主机密钥,如果没有参数,那么就尝试从用户本地的“known hosts”文件中读取密钥信息。

如下为方法示例:

client.load_system_host_keys()

# filename	文件名,默认为空。

exec_command()

在远程服务器执行Linux命令。

exec_command():在远程服务器执行Linux命令的方法。

如下为方法示例:

stdin,stdout,stderr=client.exec_command(‘ls –l’)

invoke_shell()

在远程服务器上启动交互式shell会话。

cli = client.invoke_shell()

open_sftp()

在一个会话连接中创建SFTP通道。

sftp=client.open_sftp()

close()

关闭连接。

使用流程图

以 Paramiko SFTP 为例:

补充说明:
1)事实上,由于SSHClient类集成 Transport、Channel、SFTPClient 类,上述方法都可由 SSHClient 这个类实现,SSH 会话更是如此。

参考文献

Welcome to Paramiko! — Paramiko documentation
docs.paramiko.org/en/latest/index.html