目录
基本概念
Paramiko组件架构
Key handing类
Transport类
SFTPClient类
SSHClient类—主要使用的类
Python编写完整例子
Paramiko是Python实现SSHv2协议的模块,支持口令认证和公钥认证两种方式
通过Paramiko可以实现通过Python进行安全的远程命令执行、文件传输等功能
Paramiko主要是通过不同的类来实现不同的功能
最常用的两个类是SSHClient类和SFTPClient类,分别提供SSH和SFTP功能
以下我们介绍Transport、SSHClient、SFTPClient、Key handing四种类来实现SSH基础功能
读取本地的密钥(私钥)创建密钥对象(此对象指的是数字签名),用于SSH公钥认证
使用口令认证(通过用户密码认证)时不需要此类
例子
#从文件读取RSA私钥来创建密钥对象 key=paramiko.RSAKey.from_private_key_file(r'C:\Users\exampleuser\.ssh\id_rsa') #从文件读取DSS私钥来创建密钥对象 key=paramiko.DSSKey.from_private_key_file(r'C:\Users\exampleuser\.ssh\id_rsa')
注意
使用Key handing类时,需要提前把私钥对应的公钥拷贝到SSH服务器上,不然无法完成用户认证
通过IP+端口号建立SSH连接
然后通过口令或公钥进行用户认证(认证通过后建立SSH Transport会话)
常用方法介绍
建立Transport对象,实例化SSH会话通道
paramiko.Transport(sock)
建立SSH会话连接,并使用密码或私钥进行身份认证。
connect(username=“,password=None,pkey=None)
关闭会话
close()
例子1通过口令认证与192.168.56.100建立SSH会话
tran = paramiko.Transport(('192.168.56.100',22)) tran.connect(username=‘client’,password=‘test’) tran.close()
例子2通过公钥认证与192.168.56.100建立SSH会话(提前把公钥复制到服务器上)
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) tran.close() #按照理论来说,公钥认证时不需要配置密码的 #但是华为设备中需要配置密码,不然实现不了
通过一个打开的SSH Transport会话创建SFTP会话通道,完成文件的上传和下载
常用方法介绍
从打开的Transport创建一个SFTP会话连接
paramiko.SFTPClient.from_transport(T,window_size=None, max_packet_size=None)
T
一个打开的Transport会话。
window_size
(可选参数)SFTP会话窗口大小。
max_packet_size
(可选参数)SFTP会话最大数据包大小
下载指定文件
get(remotepath, localpath)
remotepath
远程文件
localpath
本地主机的目的路径(该路径应包含文件名,仅指定目录可能会导致错误)
上传指定文件
put(localpath, remotepath)
localpath
本地文件
remotepath
SFTP服务器上的目的路径(该路径应包含文件名,仅指定目录可能会导致错误)
例子(下载设备的vrpcfg.cfg文件保存到本地改名为vrptest.cfg)
tran = paramiko.Transport(('192.168.56.100',22)) tran.connect(username=‘client’,password=‘test’) 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) tran.close()
可以实现Transport类和SFTPClient类的功能
常用方法介绍
实现远程服务器的连接与认证(完成Transport类的任务,建立SSH会话)
connect(hostname=None,port=None,username=None,password=None,key_filename=None,pkey=None)
hostname
连接的目标主机(只有该参数为必选参数)
port
指定端口(默认为22)
username
进行认证的用户名(默认为空)
password
进行认证的用户密码(默认为空)
key_filename
一个文件名或文件列表,指定私钥文件(默认为空,类似于Key handing类)
pkey
指定私钥(把私钥复制过来,非私钥文件)
设置当连接到 没有已知主机密钥的 服务器时使用的策略(完成客户端对服务器的信任)
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的配置,此为默认选项)
客户端与服务器之间的信任-两者都相互信任之后建立SSH连接
服务器有客户端的公钥(或客户端输入正确的口令),可以实现服务器对客户端的信任(即用户认证可以实现)
客户端有服务器的公钥,可以实现客户端对服务器的信任
此方法解决的是客户端对服务器的信任问题
即如果此时客户端没有服务器的公钥,可以使用此策略(使得客户端直接信任服务器)
从系统文件中加载主机密钥(主机存储的关于服务器的公钥)
load_system_host_keys(filname)
filename
文件名(默认为空)
OpenSSH会把用户访问过每个计算机的公钥(public key)都记录在~/.ssh/known_hosts
在远程服务器执行Linux命令
exec_command()
在远程服务器上启动交互式shell会话
invoke_shell()
在一个会话连接中创建SFTP通道
open_sftp()
关闭连接
close()
例子
#建立SSH会话 client=paramiko.SSHClient() 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') #信任所有服务器(自动接收服务器密钥) client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy()) #基于ssh会话连接,启用一个交互式shell会话 cli = client.invoke_shell() #基于ssh会话连接,在SSH服务器上创建一个SFTP会话 sftp=client.open_sftp() #关闭SSH会话 client.close()
通过SSHClient类进行口令认证配置服务器(不同厂商的实现只是蓝色部分不一致)
前提是设备上已经配置好SSH用户等其它操作
import paramiko
import time
ip = '192.168.0.1'
username = 'admin'
password = 'admin@123'
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip,username=username,password=password)
#进入网络设备(交换机)的命令模式了
command = ssh_client.invoke_shell()
print('已经成功登录')
#输入命令(不同厂商的命令不一致,此处以华为为例子)
command.send(‘screen-length 0 temporary\n’)
# screen-length 0 temporary 显示时不分屏
#例如dis cu查看配置时直接全部显示,不用再按回车/空格键逐页/逐行显示了
command.send('sys\n')
command.send('dis cu\n ')
command.send('dis memory\n')
time.sleep(1) #在敲命令时间隔一段时间在敲下一跳命令
#截屏 将输入的命令显示的内容显示出来
outup = command.recv(65535).decode('ascii')
print(outup)
#关闭会话
ssh_client.close()