SSH原理与实践
-
SSH简介
SSH(Secure Shell,安全外壳协议):是一种用于在不安全网络上进行安全远程登录和实现其他安全网络服务的协议
SSH协议由三个组件组成:SSH传输层协议、SSH用户认证协议、SSH连接协议- SSH传输层协议:一个安全传输协议,建立在TCP/IP连接上,可以在其他可靠数据流上建立
SSH传输层协商了所有的密钥交换算法、公钥算法、对称加密算法、消息认证算法等 - SSH用户认证协议:运行在传输层之上,为服务器提供客户端的用户鉴别
SSH用户认证提供了两种认证方法:口令认证和公钥认证- 口令认证:客户端通过用户名和密码登录到服务器,完成用户认证
- 公钥认证:服务器通过公钥解密客户端的数字签名,完成用户认证
- SSH连接协议:将加密的会话连接多路复用成若干个逻辑通道,提供了交互式登录会话,远程执行命令,TCP/IP连接转发和X11连接转发等,所有通道都复用一个会话连接
- SSH传输层协议:一个安全传输协议,建立在TCP/IP连接上,可以在其他可靠数据流上建立
-
SSH工作原理
SSH工作过程需要经过五个阶段:版本协商阶段、算法协商阶段、密钥交换阶段、用户认证阶段、会话交互阶段- 版本协商阶段:服务器开启22端口,等待客户端发起TCP连接,双方建立连接,客户端向服务器发送第一个报文,携带版本标识,服务器收到报文后,解析协议版本号,如果比自己低,且自己支持客户端的低版本,则使用客户端的协议号,否则使用自己的协议号
- 算法协商阶段:客户端和服务器交互自己支持的算法列表,根据客户端的算法列表取出一个算法,服务器在自身算法列表进行匹配,若每种算法匹配成功,则进入下一个阶段,否则断开连接
- 密钥交换阶段:客户端和服务器首先约定一个公开的质数p和g,客户端和服务器各自产生一个数作为自己的私钥,自行计算出自己的公钥,客户端与服务器双方交换公钥,根据公私密钥计算出加密会话密钥
- 用户认证阶段:用户认证阶段有口令认证和公钥认证两种方式
- 口令认证方式:客户端发送携带用户名和口令的认证请求,服务器与本地用户数据进行匹配认证,匹配一致返回认证成功,匹配失败则断开连接
- 公钥认证方式:客户端发送携带数字签名的认证请求,服务器通过本地保存的公钥解密数字签名,依次检查客户端提供的公钥及数字签名的正确性,正确则返回认证成功,失败则返回认证失败并断开连接
- 会话交互阶段:用户完成认证后,客户端向服务器发送建立通道连请求,服务器匹配是否为支持的通道类型,支持则返回成功建立会话通道,通道类型包括会话通道,x11通道,转发的tcp-ip通道,非转发的(直连的)tcp-ip通道
-
Paramiko简介
Paramiko是Python实现SSHv2协议的模块,支持口令认证和公钥认证两种方式,可以实现安全远程命令执行、文件传输等功能-
Paramiko组件架构
-
Paramiko常用类简介
- Channel类:用于创建在SSH Transport上的安全通道
- Message类:SSH Message是字节流。对字符串、整数、bools和无线精度的某些组合进行编码
- Packetizer类:数据包处理类
- Transport类:用于在现有套接字或类套接字对象上创建一个Transport会话对象
- SFTPClient类:通过一个打开的SSH Transport会话创建SFTP会话通道并执行远程文件操作
- SSHClient类:与SSH服务器会话的高级表示,集成了Transport,Channel和SFTPClient类
-
Paramiko密钥相关类简介
- SSH Agents类:用于SSH代理
- Host Keys类:与OpenSSH known_hosts文件相关,用于创建一个host keys对象
- Key handling类:该类用于创建对应密钥类型的实例,如RSA密钥,DSS(DSA)密钥
-
Transport类及其方法介绍
-
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() 关闭会话 -
Key handling类:用于创建对应密钥类型的实例
方式实例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私钥来创建密钥对象 -
SFTPClinet类:通过一个打开的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,windows_size=None,max_packet_size=Noce) local_path=r'C:\Users\exampleuser\.ssh\vrptest.cfg' remote_path= '/vrpcfg.cfg' sftp.get(remotepath, localpath) sftp.put(localpath, remotepath)
常用方法 功能 from_transport() 从打开的Transport创建一个SFTP会话连接 get() 下载指定文件 put() 上传指定文件 tran 一个认证通过的开启的Transport会话 windwos_size 可选参数,SFTP会话窗口大小 max_packet_size 可选参数,SFTP会话最大数据包大小 remotepath 远程文件 localpath 本地主机的目的路径,该路径应包含文件名,仅指定目录可能会导致错误 localpath 本地文件 remotepath SFTP服务器上的目的路径,该路径应包含文件名,仅指定目录可能会导致错误 -
SSHClinet类:与SSH服务器会话的高级表示,包含了Transport类、Channel类和SFTPClient类进行会话通道的建立和认证
方法实例client=paramiko.client.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’) stdin,stdout,stderr=client.exec_command(‘ls –l’) cli = client.invoke_shell() sftp=client.open_sftp()
常用方法 功能 connect() 实现远程服务器的连接与认证 command linux命令 lnvoke_shell() 基于SSH会话连接,启动一个交互式Shell会话 open_sftp() 在SSH服务器上创建打开一个sftp会话 client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
常用方法 功能 set_missing_host_key_policy() 设置连接到没有已知主机密钥的服务器时使用的策略 client.load_system_host_keys()
常用方法 功能 load_system_host_policy() 从系统文件加载密钥,如果没有参数,尝试从用户本地(known hosts)文件中读取密钥信息 filename 文件名, 默认为空
-
-