SSH代理-Paramiko实现案例

本文最后更新于 2025年6月11日 下午

SSH代理-Paramiko实现案例

一、背景

在网络管理中,常需通过代理服务器(跳板机)访问内部设备。SSH提供了便捷的代理跳转机制,Python的Paramiko库可程序化实现这一功能。

二、SSH代理连接核心原理

通过SSH协议的TCP转发功能,在代理服务器上创建到目标设备的转发通道,实现间接连接。核心流程:

  1. 连接代理服务器
  2. 创建到目标设备的转发通道
  3. 通过通道连接目标设备

三、ssh -J 命令解释

1
ssh -J admin@192.168.1.2 admin@192.168.1.3
  • -J 选项:指定通过代理服务器连接目标主机(OpenSSH 7.3+ 支持)
  • 作用:通过 admin@192.168.1.2 代理服务器连接 admin@192.168.1.3 目标主机
  • 等价于
    1
    ssh -o ProxyCommand="ssh -W %h:%p admin@192.168.1.2" admin@192.168.1.3
  • 优势:一行命令实现跳转,无需手动配置~/.ssh/config

四、Paramiko实现方式

4.1 方式一:交互式Shell + 提示符等待

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import paramiko

def get_ruijie_config_with_shell():
# 代理服务器配置
PROXY_IP = "192.168.1.2"
PROXY_USER = "admin"
PROXY_PASS = "12345"

# 锐捷设备配置
DEVICE_IP = "192.168.1.100"
DEVICE_USER = "admin"
DEVICE_PASS = "ruijie123"
ENABLE_PASS = "ruijieenable" # 特权模式密码

transport = None
client = None
shell = None

try:
# 1. 连接代理服务器
transport = paramiko.Transport((PROXY_IP, 22))
transport.connect(username=PROXY_USER, password=PROXY_PASS)

# 2. 创建到锐捷设备的转发通道
channel = transport.open_channel('direct-tcpip', (DEVICE_IP, 22), ('', 0))

# 3. 通过通道连接锐捷设备
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
hostname=DEVICE_IP,
username=DEVICE_USER,
password=DEVICE_PASS,
sock=channel,
timeout=10
)

# 4. 获取交互式Shell
shell = client.invoke_shell()
shell.settimeout(15)
time.sleep(1)
shell.recv(65535) # 清除欢迎信息

# 5. 进入特权模式(锐捷设备使用enable命令)
shell.send("enable\n")
output = _await_prompt(shell, ["Password:", "#"], timeout=5)

if "Password" in output:
shell.send(f"{ENABLE_PASS}\n") # 发送特权密码
_await_prompt(shell, ["#"], timeout=5)

# 6. 执行show running-config命令
shell.send("show running-config\n")
config_output = _await_prompt(shell, ["#"], timeout=20) # 等待配置输出完成

# 7. 提取配置内容(示例:简单分割命令输出)
config_start = config_output.find("Building configuration")
config = config_output[config_start:] if config_start > 0 else config_output

print(f"锐捷设备配置:\n{config}")

except Exception as e:
print(f"错误: {str(e)}")
finally:
# 8. 资源清理
for resource in [shell, client, transport]:
if resource:
resource.close()

# 辅助函数:等待提示符(简化版)
def _await_prompt(shell, prompts, timeout=10):
start_time = time.time()
output = ""
while time.time() - start_time < timeout:
if shell.recv_ready():
output += shell.recv(4096).decode('utf-8', 'ignore')
if any(prompt in output for prompt in prompts):
return output
time.sleep(0.1)
return output

特点

  • 适用于需要交互式操作场景
  • 通过循环等待提示符判断命令完成
  • 灵活性高但性能较差

4.2 方式二:exec_command直接执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import paramiko

def get_ruijie_config_with_exec():
# 代理与设备配置(同交互式方式)
PROXY_IP = "192.168.1.2"
PROXY_USER = "admin"
PROXY_PASS = "12345"
DEVICE_IP = "192.168.1.100"
DEVICE_USER = "admin"
DEVICE_PASS = "ruijie123"

transport = None
client = None

try:
# 1. 连接代理服务器并创建转发通道
transport = paramiko.Transport((PROXY_IP, 22))
transport.connect(username=PROXY_USER, password=PROXY_PASS)
channel = transport.open_channel('direct-tcpip', (DEVICE_IP, 22), ('', 0))

# 2. 连接锐捷设备
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
hostname=DEVICE_IP,
username=DEVICE_USER,
password=DEVICE_PASS,
sock=channel,
timeout=10
)

# 3. 直接执行show running-config命令(锐捷设备无需进入特权模式也可执行部分查询)
# 注意:实际环境可能需要先进入特权模式
stdin, stdout, stderr = client.exec_command(
"show running-config", # 直接执行命令
timeout=20 # 配置输出可能较大,延长超时
)

# 4. 获取配置内容
config = stdout.read().decode('utf-8')
error = stderr.read().decode('utf-8')

if error:
print(f"命令错误: {error}")
else:
print(f"锐捷设备配置:\n{config[:100]}... (总长度: {len(config)}字符)")

except Exception as e:
print(f"错误: {str(e)}")
finally:
# 5. 资源清理
for resource in [client, transport]:
if resource:
resource.close()

特点

  • 直接执行命令并获取结果
  • 适用于非交互式简单命令
  • 性能好但灵活性低

五、两种方式对比

方式 交互式Shell exec_command
核心 模拟人工交互 直接执行命令
场景 配置设备、复杂交互 查询信息、简单命令
性能 较差(循环等待) 较好(阻塞执行)
资源 CPU占用高 CPU占用低

六、适用建议

  • 交互式Shell:设备配置、需要多步交互的场景
  • exec_command:信息查询、性能要求高的批量操作
  • ssh -J:手动命令行跳转,简单快捷

七、关键优势

  • 安全性:所有流量通过SSH加密
  • 便捷性:无需开放目标设备公网访问
  • 灵活性:支持复杂网络环境下的设备管理

SSH代理-Paramiko实现案例
http://example.com/2025/06/11/SSH代理Paramiko实现案例/
作者
xinhaojin
发布于
2025年6月11日
许可协议