boxmoe_header_banner_img

⋅無⋅限⋅進⋅步⋅

加载中

文章导读

SSH原理与实践


avatar
yuhui 2025年10月21日 82

SSH原理与实践

使用python工具,围绕python中的Paramiko模块编写自动化脚本实现SHH的初级网络自动化

::::::::::::::::::::::::::::::::::

SSH Secure Shell 用在不安全网络进行安全远程登录和实现其他安全网络服务的协议

三个组件:

SSH传输层协议,SSH用户认证协议,SSH连接协议

1741920650706-834627e1-2649-4996-8712-d49007b9c388.png

SSH传输层通常建立在TCP/IP连接上,也可以建立在其他可靠的数据流上

SSH传输层协议写上了所有的密钥交换算法,公钥算法,对称加密算法,消息认证算法等

1741920650719-01e6c8be-9959-4220-953a-d49ead0d888d.png

完美前向保密 PFS perfect forwward secrecy

安全通信协议的一种属性,PFS最初用于定义会话密钥交换协议的一种安全性。指用来产生会话密钥的长期协议(通常为是要或者相关认证材料)的泄露,不会导致过去的会话密钥泄露,前向保密能够保护历史通讯和会话不受密码或密钥在未来暴露的威胁,即使攻击者主动干预

使用diffie-hellman密钥交换算法可以提供近乎完美的前向保密性

用户认证协议:

为服务器提供客户端的用户鉴别,运行在传输层协议上

两种认证方法:口令,公钥

1741920650691-e854348f-2912-4a15-9af0-0abaec05cca0.png

口令:客户端通过用户名和密码登录

1741920650732-ddf7dbfb-ffa3-4a6e-97cf-ad6cc2f88915.png

公钥:服务器通过公钥解密客户端数字签名

公钥用来解密信息,确保别人知道这条信息是真的,接受者由此可知这条信息来自拥有私钥的某人,称作数字签名,公钥形式是数字证书

此协议启动时,从SSH传输层协议接受会话ID,会话ID唯一标识一个会话,并且参与签名以证明私钥的所有权

SSH连接协议:

将加密的会话连接多路复用或若干个逻辑通道,提供了交互式登录会话,远程执行命令,TCP/IP连接转发和X11连接转发等功能,所有通道复用一个会话连接

连接协议在传输层和用户认证协议之上运行

1741920650686-c332d55e-abe6-4351-a0c2-0617443f2b23.png

1741920653994-bf3b765d-b3d6-44ca-8b81-fef074333d2c.png

工作原理

1741920653912-e71f5e6c-776f-45c5-9a91-fed22a6ff01a.png

版本协商:包括SSH1和SSH2两个版本,通过版本协商确定要使用的版本

算法协商:双方根据本段和对端支持的算法,协商出最终使用的加密算法

密钥交换:通过密钥交换算法生成会话密钥,伺候双方单段会话均通过会话密钥加密

用户认证:SSH客户端向服务器发起认证请求,服务器端对客户端进行认证

会话交互:认证通过后,服务器和客户进行信息交互

版本协商:

服务器端打开端口22等待客户端连接,

客户端向服务器端发送第一个报文,包括版本标志字符串,

格式为:协议版本号 次协议版本号 软件版本号

服务端收到报文后,解析协议版本号,如果客户端的协议版本号比自己的低,且服务端嫩支持客户端的低版本,就使用客户端的协议号,否则使用自己的协议版本号

1741920653929-4bcd848a-e5c6-4752-9066-d753120f65cc.png

算法协商:

从客户端算法list取出第一个算法

服务器在自身的算法列表查找,若匹配上相同的算法则协商成功,继续协商下一种算法,否则继续从客户端的该种算法列表中取出下一个算法,在服务器端的算法列表中匹配,直到成功

1741920654040-6ff84832-fd31-4781-8b1e-1d85d8253823.png

密钥交换:

客户端和服务器约定两个公开的质数p and g

客户端和服务器各自随机产生一个数Xc,Xs作为自身私钥

各自计算出自己的公钥Yc,Ys

交换公钥

根据公钥计算出加密用的会话密钥

具体密钥交换算法是DH算法,基于数学的离散对数,在交换过程中,私钥是保密的不传播的,其他用户即使获取了p,g,Yc,Ys也无法推断私钥

该阶段产生的公钥私钥仅用于产生会话密钥,与后续用户认证无关,交换阶段完成后,后续所有报文交互均为会话密钥加密过的报文

1741920654003-039cb867-4820-4ebd-b22f-e959552353f7.png

口令认证:

客户端发送携带用户名和口令的认证请求,服务器与本地用户数据进行匹配认证

1741920654467-3f98aa6f-7817-4858-83c1-063ec0425d81.png

公钥认证:

客户端发送携带数字签名的认证请求,服务器通过公钥解密数字签名进行认证

1741920654541-0b8351fb-7247-46cd-9724-59eddf190eda.png

会话交互:

完成认证后,客户端向服务器发起建立通道请求进行数据传输

通道类型:会话通道,x11通道,转发的tcp-ip通道,非转发的(直连)tcp-ip通道

1741920654513-f594bcf8-b5bc-4c15-8e54-ad5254699989.png

Paramiko:

此模块是python实现SSH⒈1模块,支持两种认证方式

可基于该模块编写python代码实现SSH相关功能

组件架构:SSHClient和SFTPClient,分别提供SSH和SFTP功能

1741920654479-d008ea93-fb09-4cda-9aa3-ca1d3e3b925e.png

常用类:

channel:创建SSH transport上的安全通道,包含执行命令,请求x11会话,发送数据,打开交互式会话等

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

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

transport:在现有套接字或类套接字对象上创建一个transport会话对象,包含公钥认证,打开channel

SFTPClient:通过一个打开的SSH Transport创建SFTP会话通道并执行远程文件操作,包含文件上传和下载

SSHClient:SSHclient类是与SSH服务器会话的高级表示,集成transport,channel,SFTPClient 包含建立连接,打开交互式会话等方法

1741920654538-b326a06f-4f8b-4256-b2af-fec6f0f6f669.png

密钥相关

SSH Agent:用于SSH代理

host keys:与OpenSSH known_hosts相关,用于创建一个hostkeys对象

key handling:创建对应密钥类型的实例,如RSA,DSS密钥

Opessh是SSH协议免费开源实现,OpenSSH提供了服务端后台程序和客户端工具,所有的Linux操作系统均集成了OpenSSH,OpenSSH把用户访问过每个计算机的公钥都有记录在~/.ssh/known_hosts当下次访问相同计算机,OpenSSH会核对公钥,如果不同则发出警告

Paramiko使用流程:

以SFTP会话为例,由于SSHClient集成了transport,channel,SFTPClient,下面均可用SSHClient实现

1741920655778-3fd09aa5-e47b-45dd-90d4-db5738b88102.png

Transport:

一个SSH Transport连接一个流,协商加密会话,进行认证,后续可以在加密会话上创建通道,多个通道可以在单个会话连接中多路复用

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

1741920655809-c1cc902d-9856-41ea-bbfd-dc076a9c41d5.png

Key handling:

创建对应密钥类型的实例,如RSA密钥DSS密钥,包含密钥的读取、写入等方法

1741920655745-0139f7a2-b8f1-49e7-bd3f-5d90d8be854c.png

SFTPClient:

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

1741920656303-327882cd-e3a0-4904-8d94-0efcc9f957f4.png

from_transport:

从开启的Transport通道创建一个SFTP客户端通道

1741920655749-d02bd98b-3ea9-4dc5-ab34-f92910177426.png

get:

将远程文件从SFTP服务器复制到本地主机的指定路径,操作引发的任何异常都将被传递

1741920657444-8425e9ae-4c5c-4314-9190-5e115dfa51f9.png

put:

将本地文件从本地主机复制到SFTP服务器指定路径中,操作引发的异常将被传递

1741920657458-b8053563-7fc2-4da8-96ab-63e0ac849b81.png

SSHClient:

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

1741920657537-bdb5d005-f64f-4093-8b6c-733b08ba1a36.png

connect:

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

1741920657550-2d9a0ec0-0470-4d4d-8cd6-374ca7b7266c.png

set_missing_host_key_policy:

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

1741920657547-17dd5c0b-a8cb-436b-ad40-7dd36170a3cb.png

load_system_host_keys:

从系统文件加载主机密钥,如果没有参数,就尝试从用户本地的knownhosts文件中读取密钥

1741920659074-cabb31da-9fe8-49bc-883c-f20bac2abae6.png

exec_command:

在远程服务器执行Linux命令

1741920659081-ed580c7b-2a53-458a-9003-7b4fbce4346b.png

invoke_shell:

基于SSH会话连接,启动一个交互式shell会话

1741920659120-4b13cc96-c463-4f47-8995-ce5526eb347c.png

open_sftp:

在SSH服务器上创建打开一个SFTP会话

1741920659098-89421067-4cc3-4a68-a979-6ecfbed8b425.png

例:使用SSH登录设备

1741920659163-0de130d9-b996-4053-ad10-a1e316e3b74a.png

1741920660829-8e31436d-0673-4848-ae42-44e2413e1877.png

1741920660958-153e71de-1cd8-408b-a3b9-5d52c2d7640d.png

1741920660829-9aa0b9b0-7869-4670-a450-5853d04f413d.png

1741920660927-e63df91a-77ee-432e-8ff6-7dd95931ad94.png

1741920660841-75636d53-14cf-444a-88e4-86a604358b0a.png

1741920662749-fde20edd-b809-44ea-9f06-e1fec7f0b0f1.png

导入模块

import paramiko

import time

实例化ssh对象,赋值给ssh

ssh = paramiko.SSHClient()

新建立ssh连接时不需要再输入yes或no确认

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

目的服务器192.168.56.100 端口22 用户名client key_filename指定客户端本地的私钥文件,上文中r’路径’的形式是使用转义字符,表示”内部的无其他语义,下文双与r”为不同类型的同一用法

ssh.connect(hostname=’192.168.56.100′,port=22,username=’client’,key_filename=’C:Users用户名.sshid_rsa’)

SSh到设备后,使用python脚本向ce发送命令

cli = ssh.invoke_shell()

cli.send(‘screen-length 0 temporaryn’)

send发送命令行

Screen-length 0 temporary为取消分屏,一次性输出所有回显命令

display cu为显示当前配置

cli.send(‘display cun’)

cli.send(‘sys n’)

cli.send(‘sys SSHPython Successful!!n’)

设置等待时间

time.sleep(3)

invoke_shell已经创建了一个channel逻辑通道,所有的输入输出信息都在里面,获取这些逻辑通道里面的信息,显示到编译器,调用cli.recv 然后使用decode进行解码,赋值给dis_cu,其中999999表示数据最大接收量,decode默认解码格式为utf-8,解码的作用是方便阅读,结果将换行呈现

dis_cu = cli.recv(999999).decode()

print(dis_cu)

关闭会话连接

ssh.close()

例:使用SFTP上传和下载文件

1741920662710-89706479-39c6-4a48-89e0-62015e23dbfd.png

1741920662765-3ae9547c-3b44-4332-a5e7-6e07b319ff9f.png

1741920662731-cc19ec8d-40b4-448a-baa8-76881ce7ef6d.png

1741920662814-0f8653aa-07b0-435a-aa5f-ff55712a3314.png

1741920664732-0c0a3116-93b4-408e-825b-30ce6c551b79.png

1741920664701-2bcf9c77-d18a-41c7-b8b6-52e59bba0141.png

更新: 2025-03-14 10:51:11
原文: https://www.yuque.com/yuhui.net/network/er9lqk3nzk74gmzy



评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码