通过SSH搭建C++与Python端ZMQ收发连接报错如何解决?
错误根因
该异常是SSH连接阶段的公钥校验失败导致:运行Python代码的设备发起SSH连接时,目标主机的公钥未收录到当前用户的~/.ssh/known_hosts文件中。终端手动连接时会弹出公钥确认提示,确认后系统会自动写入公钥到文件,所以可以正常连接;但ZMQ默认的SSH隧道逻辑不会自动确认未知公钥,因此直接抛出异常。
另外你当前代码中的tcp://0.0.0:55555写法存在错误:0.0.0.0是服务端绑定所有网卡时使用的监听地址,客户端连接时不能使用该地址,需替换为隧道对端可访问的IP,比如本机隧道的话填127.0.0.1即可。
修复方案
方案1:手动写入公钥到known_hosts(最安全,推荐)
在运行Python代码的设备上,切换到执行代码的对应系统用户,手动执行一次SSH连接到目标服务器,公钥确认提示输入yes后,公钥就会自动存入~/.ssh/known_hosts,之后再运行代码即可正常通过校验。
如果之前已经手动连过还是报错,检查执行代码的用户身份,不同系统用户的known_hosts文件相互独立,比如用root执行代码的话就要切换到root用户做一次手动SSH连接。
方案2:切换为paramiko后端并关闭公钥校验
ZMQ的SSH隧道支持openssh和paramiko两种后端,默认的openssh后端无法直接跳过公钥校验,切换为paramiko后端后可配置自动添加未知公钥:
- 先安装paramiko依赖:
pip install paramiko
- 修改代码如下:
from zmq import ssh import zmq import paramiko # 初始化paramiko客户端,配置自动接受未知公钥 ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) context = zmq.Context() socket = context.socket(zmq.REQ) # 修正地址写法 tcp_address = "tcp://127.0.0.1:55555" # 传入paramiko客户端实例,指定用paramiko建立隧道 ssh.tunnel_connection( socket, tcp_address, 'username@remote', password='remoteloginpassword', paramiko=ssh_client ) request = b'someRequest' socket.send(request) print("request sent") reply = float(socket.recv()) print("Reply received: {}".format(reply))
方案3:修改SSH配置跳过公钥校验(仅临时测试使用,不推荐生产环境)
如果你不想用paramiko,可以修改运行Python代码设备的~/.ssh/config文件,添加对应主机的配置跳过校验:
Host 你的远程服务器地址 StrictHostKeyChecking no UserKnownHostsFile /dev/null
该方案会绕过SSH公钥校验,存在中间人攻击风险,仅适合本地测试场景使用。
内容的提问来源于stack exchange,提问作者Claudio LoBraico
相关产品推荐
相关产品推荐

