尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python 通过跳板机连接远程服务器:Paramiko 实战指南
1. 引言在实际的企业级开发和运维场景中出于安全考虑我们通常无法直接访问生产环境服务器而是需要通过一个跳板机Bastion Host作为中转。本文将详细介绍如何使用 Python 的 Paramiko 库通过跳板机安全地连接远程服务器并实现命令执行和文件传输功能。2. 环境准备2.1 安装 Paramikopipinstallparamiko2.2 基础概念跳板机位于公网和内网之间的安全网关所有对内网服务器的访问都必须经过它SSH 隧道通过跳板机建立的加密通道用于安全地访问内网服务器ParamikoPython 的 SSHv2 协议实现库支持 SSH 连接和 SFTP 文件传输3. 核心实现代码以下是完整的实现类支持通过跳板机连接远程服务器#!/usr/bin/env python3# -*- coding: utf-8 -*-importosimportparamikofromtypingimportOptional,Tuple,UnionclassSSHJumpHostConnector: 通过跳板机连接远程服务器的 SSH/SFTP 客户端 功能 1. 通过跳板机建立 SSH 连接 2. 执行远程命令 3. 上传/下载文件 4. 安全关闭连接 def__init__(self,jump_host:str,jump_user:str,jump_password:str,target_host:str,target_user:str,target_password:str,jump_port:int22,target_port:int22): 初始化跳板机连接 Args: jump_host: 跳板机 IP 地址 jump_user: 跳板机用户名 jump_password: 跳板机密码 target_host: 目标服务器 IP 地址 target_user: 目标服务器用户名 target_password: 目标服务器密码 jump_port: 跳板机 SSH 端口默认 22 target_port: 目标服务器 SSH 端口默认 22 self.jump_hostjump_host self.target_hosttarget_host# 第一步连接跳板机self.jump_sshparamiko.SSHClient()self.jump_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())self.jump_ssh.connect(hostnamejump_host,portjump_port,usernamejump_user,passwordjump_password)# 第二步通过跳板机建立到目标服务器的通道jump_transportself.jump_ssh.get_transport()src_addr(jump_host,jump_port)dest_addr(target_host,target_port)jump_channeljump_transport.open_channel(kinddirect-tcpip,dest_addrdest_addr,src_addrsrc_addr)# 第三步连接目标服务器self.target_sshparamiko.SSHClient()self.target_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())self.target_ssh.connect(hostnametarget_host,porttarget_port,usernametarget_user,passwordtarget_password,sockjump_channel)# 第四步创建 SFTP 客户端target_transportself.target_ssh.get_transport()self.sftpparamiko.SFTPClient.from_transport(target_transport)print(f✅ 成功连接到目标服务器{target_host}通过跳板机{jump_host})defexecute_command(self,command:str,timeout:int30)-Tuple[str,str,int]: 在目标服务器上执行命令 Args: command: 要执行的命令 timeout: 命令执行超时时间秒 Returns: tuple: (stdout, stderr, return_code) stdin,stdout,stderrself.target_ssh.exec_command(command,timeouttimeout)stdout_strstdout.read().decode(utf-8).strip()stderr_strstderr.read().decode(utf-8).strip()return_codestdout.channel.recv_exit_status()print(f 执行命令:{command})print(f 输出:{stdout_str})ifstderr_str:print(f⚠️ 错误:{stderr_str})print(f 返回码:{return_code})returnstdout_str,stderr_str,return_codedefupload_file(self,local_path:str,remote_path:str)-None: 上传本地文件到远程服务器 Args: local_path: 本地文件路径 remote_path: 远程文件路径 ifnotos.path.exists(local_path):raiseFileNotFoundError(f本地文件不存在:{local_path})self.sftp.put(local_path,remote_path)print(f 上传成功:{local_path}→{remote_path})defdownload_file(self,remote_path:str,local_path:str)-None: 从远程服务器下载文件到本地 Args: remote_path: 远程文件路径 local_path: 本地文件路径 # 确保本地目录存在local_diros.path.dirname(local_path)iflocal_dirandnotos.path.exists(local_dir):os.makedirs(local_dir)self.sftp.get(remote_path,local_path)print(f 下载成功:{remote_path}→{local_path})defclose(self)-None:安全关闭所有连接ifhasattr(self,sftp):self.sftp.close()print( 已关闭 SFTP 连接)ifhasattr(self,target_ssh):self.target_ssh.close()print( 已关闭目标服务器 SSH 连接)ifhasattr(self,jump_ssh):self.jump_ssh.close()print( 已关闭跳板机 SSH 连接)print(✅ 所有连接已安全关闭)# 使用示例if__name____main__:# 配置连接信息实际使用时请替换为真实信息JUMP_HOST10.110.19.100# 跳板机 IPJUMP_USERjump_user# 跳板机用户名JUMP_PASSWORDjump_password# 跳板机密码TARGET_HOST172.20.10.50# 目标服务器 IPTARGET_USERremote_user# 目标服务器用户名TARGET_PASSWORDremote_pass# 目标服务器密码try:# 创建连接connectorSSHJumpHostConnector(jump_hostJUMP_HOST,jump_userJUMP_USER,jump_passwordJUMP_PASSWORD,target_hostTARGET_HOST,target_userTARGET_USER,target_passwordTARGET_PASSWORD)# 示例 1执行命令print(\n 执行命令示例 )output,error,codeconnector.execute_command(pwd)print(f当前工作目录:{output})# 示例 2查看系统信息output,error,codeconnector.execute_command(uname -a)print(f系统信息:{output})# 示例 3上传文件print(\n 文件传输示例 )# connector.upload_file(local_file.txt, /tmp/remote_file.txt)# 示例 4下载文件# connector.download_file(/tmp/remote_file.txt, downloaded_file.txt)# 示例 5批量执行命令commands[whoami,date,df -h | head -5]print(\n 批量执行命令 )forcmdincommands:output,error,codeconnector.execute_command(cmd)print(f命令 {cmd} 输出:{output})exceptExceptionase:print(f❌ 连接失败:{e})finally:# 确保连接被关闭ifconnectorinlocals():connector.close()4. 工作原理详解4.1 连接建立流程本地客户端连接跳板机 SSHClient.connect建立SSH隧道 open_channel连接目标服务器 connect sockchannel创建SFTP客户端 from_transport执行命令或传输文件4.2 关键参数说明AutoAddPolicy()自动添加未知主机到 known_hosts生产环境建议使用更安全的策略direct-tcpip建立直接的 TCP/IP 通道用于 SSH 隧道sock参数指定使用已有的 socket 连接实现通过跳板机连接5. 高级用法与最佳实践5.1 使用密钥认证推荐# 使用密钥文件代替密码private_keyparamiko.RSAKey.from_private_key_file(/path/to/private_key.pem)jumpbox_ssh.connect(hostnamejump_host,usernamejump_user,pkeyprivate_key# 使用密钥认证)5.2 连接池管理对于频繁的连接需求可以实现连接池classSSHConnectionPool:def__init__(self,max_connections10):self.pool[]self.max_connectionsmax_connectionsdefget_connection(self,config):# 从池中获取或创建新连接passdefrelease_connection(self,connector):# 释放连接回池中pass5.3 错误处理与重试importtimefromparamiko.ssh_exceptionimportSSHException,AuthenticationExceptiondefconnect_with_retry(connector_class,config,max_retries3):forattemptinrange(max_retries):try:connectorconnector_class(**config)returnconnectorexcept(SSHException,AuthenticationException)ase:ifattemptmax_retries-1:raiseprint(f连接失败{attempt1}秒后重试...)time.sleep(attempt1)5.4 安全建议不要硬编码密码使用环境变量或配置文件使用密钥认证比密码更安全限制权限使用最小权限原则记录日志记录所有连接和操作定期更换密钥定期更新 SSH 密钥6. 常见问题与解决方案Q1: 连接超时怎么办检查网络连通性ping 跳板机IP检查防火墙设置增加超时时间connect(timeout60)Q2: 认证失败怎么办确认用户名/密码正确检查密钥文件权限chmod 600 private_key.pem验证跳板机是否允许该用户连接Q3: SFTP 传输失败怎么办检查文件路径是否存在确认用户有读写权限检查磁盘空间是否充足Q4: 如何提高传输速度使用压缩sftp.get(remotepath, localpath, prefetchFalse)批量传输减少连接开销使用更快的加密算法7. 总结关键点包括安全连接通过跳板机建立加密隧道完整功能支持命令执行和文件传输健壮性完善的错误处理和资源管理可扩展性易于扩展为连接池或集成到自动化工具中附录完整配置示例创建config.yaml配置文件# config.yamljump_host:host:10.110.19.100user:jump_user# 使用密码或密钥文件password:your_password# key_file: /path/to/private_key.pemtarget_hosts:web_server:host:172.20.10.50user:web_userpassword:web_passworddb_server:host:172.20.10.51user:db_userpassword:db_password使用配置文件连接importyamlwithopen(config.yaml,r)asf:configyaml.safe_load(f)# 连接多个服务器forserver_name,server_configinconfig[target_hosts].items():connectorSSHJumpHostConnector(jump_hostconfig[jump_host][host],jump_userconfig[jump_host][user],jump_passwordconfig[jump_host][password],target_hostserver_config[host],target_userserver_config[user],target_passwordserver_config[password])# 执行操作...connector.close()
RELATED

相关推荐

125.BGP路由最常用的属性

125.BGP路由最常用的属性

BGP路由最常用的属性 一、BGP路由属性 二、公认必遵 Origin属性 AS_Path属性 Next_hop属性 三、其他常用属性 Local_Preference属性 MED属性 Community属性 Atomic_Aggregate及Aggregator Preferred-Value 四、总结 一、BGP路由属性 公认属性,公认属性是所有BGP路由器都必须能…

📅 2026/9/17 8:20:34
35+技术人的年中复盘:在大模型浪潮中重新定义自己的技术价值

35+技术人的年中复盘:在大模型浪潮中重新定义自己的技术价值

35技术人的年中复盘:在大模型浪潮中重新定义自己的技术价值 每到年中,总会有一种焦虑悄悄蔓延:大模型来了,我还能做什么?尤其是35岁以上的技术人,这种焦虑更加强烈。但这半年的实践证明,经验的…

📅 2026/9/15 7:43:50
AI数据库产品的商业化思考:从内部工具到对外服务的关键跨越

AI数据库产品的商业化思考:从内部工具到对外服务的关键跨越

AI数据库产品的商业化思考:从内部工具到对外服务的关键跨越 当一个AI数据库工具在内部用得很好时,自然会想到"能不能把它做成产品卖出去"。但从内部工具到商业化产品,中间隔着一道巨大的鸿沟。 一、从"我们团队觉得好用&quo…

📅 2026/9/15 16:21:45
MORE NEWS

更多资讯

📰

superpowers实战:为AI编程助手注入工程化协作能力

如果你最近在终端里用过 Codex CLI 这类 AI 编程助手,大概率会有一种感觉:它很强,但更像一个“听话的实习生”。你每一步都要给它下指令,稍不留神它就跑偏,让它改个东西它可能把不相干的代码也顺手改了。superpowers 这…

📰

Jeepay开源聚合支付系统:Java四方支付底座实战指南

简介:这是一套全开源的Java聚合支付系统(Jeepay),面向中高级Java开发者、支付平台架构师及金融科技领域学习者,用于快速搭建支持多渠道接入的四方支付服务。系统已深度集成微信(V2/V3)、支付宝&…

📰

蓝牙双模配对总翻车?CTKD跨传输密钥派生原理与实测解析

1. 为什么蓝牙耳机配对总让人抓狂我每天早上通勤的固定流程是这样的:从包里掏出真无线耳机,戴上,然后掏出手机解锁——接着在蓝牙设置界面里等着,看它能不能自己连上。大部分时候可以,但总有那么几次,耳机明…

📰

Substrate区块链开发框架详解:从核心概念到自定义链实操

做区块链底层开发这几年,被问得最多的一个问题就是:想自己做一条链,从哪开始?如果放在五年前,答案可能是“先读比特币源码,再读以太坊黄皮书,然后自己造轮子”。现在我的答案很固定:…

📰

Kubernetes、Ray、vLLM 三层调度分工与协同优化

1. 三类调度器不是“谁管谁”,而是各守一段技术栈的边界“Kubernetes、Ray、vLLM 都在调度,它们各自决定了什么?”——这个问题背后藏着一个普遍误解:很多人下意识把这三者当成同一层级的“资源分配工具”,甚至试图比较…

📰

Kubernetes 上构建 Agentic 工作负载的运行时调度层:ax 调度设计与实践

1. 从“ax”这个标题说起:一个被低估的运行时调度命题第一次看到“ax”这个标题,很多人会以为是某个命令行工具的缩写,或者某个内部代号。但把热搜词摊开来看——ax、agentic、orchestration、runtime、Kubernetes——这几个词凑在一起&#…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬