用zeromq在Python中进行远程TCP连接
我有一个用Python写的客户端,需要和我管理的远程服务器进行通信。它们是通过zeromq来交流的。当我在本地测试客户端和服务器时,一切都运行得很好。但现在我把客户端和服务器都放到了云端,使用的是不同的服务提供商。我的问题是,最简单(而且安全)的方法是什么来建立这个连接?我在想,可能不能直接传递密码,即使可以,我也觉得有更安全的办法。
我知道怎么用ssh-keygen设置一个不需要密码的ssh连接。这样可以吗?客户端在发送tcp请求之前需要先和服务器建立ssh连接吗?如果有一个Python库可以帮助我实现这个,那就太好了。
谢谢!
更新: 超过24小时了,没有人回复我。我觉得我离解决这个问题更近了一步,但还没完全搞定。我把客户端的密钥添加到了服务器的.ssh/authorized_key中,现在我可以从客户端无密码ssh到服务器。接下来,我按照这篇关于“用SSH隧道连接PyZMQ”的帖子进行了操作。以下是我在客户端代码中的内容:
1 context = zmq.Context()
2 socket = context.socket(zmq.REQ)
3 socket.connect("tcp://localhost:5555")
4 ssh.tunnel_connection(socket, "tcp://locahost:5555", "myuser@remote-server-ip:5555")
5 socket.send_string(some_string)
6 reply = socket.recv()
这个不行。我不太理解第3行和第4行的内容,我觉得我可能在这里做错了。而且,我的服务器(托管在linode上)有一个“默认网关”IP和一个“公共IP”——在隧道连接中我只指定了公共IP,这也是我用来ssh连接到机器的IP。
2 个回答
我发现用Python进行ssh连接时,总是有点不稳定,即使使用了paramiko
和fabric
这些库。所以为了排查问题,你可以尝试单独设置一个隧道,看看是不是连接断开的原因。
举个例子:
ssh myuser@remote-server-ip -L 5050:localhost:5555 -N
这个命令的意思是:连接到myuser@remote-server-ip
,然后每当我在自己电脑上请求连接localhost:5050
时,就通过ssh连接把这个请求转发过去,让remote-server-ip
的服务器认为它是从localhost:5555
发来的连接。
-L
是用来建立这个隧道的,而-N
的意思是不要在这个连接上做其他事情。
在你本地开发机器的另一个终端窗口中运行这个命令后,尝试连接到localhost:5050
的zeromq服务器,实际上这个zeromq是在远程服务器上运行的。
你也可以在上面的ssh命令中使用5555:localhost:5555
,但我觉得这样可能会让人困惑,而且常常会和本地的同一服务发生冲突。
确实,ZMQ的方式是通过SSH进行连接隧道。你的例子正是需要做的事情,只是要记住要么使用 connect
,要么使用 tunnel_connection
,不能两个都用。
另外,当你指定要连接的服务器时,确保定义的是SSH端口,而不是ZMQ的REP套接字端口。也就是说,不要写成 myuser@remote-server-ip:5555
,你可以试试 myuser@remote-server-ip
或者 myuser@remote-server-ip:22
。
import zmq
import zmq.ssh
context = zmq.Context()
socket = context.socket(zmq.REQ)
zmq.ssh.tunnel_connection(socket, "tcp://locahost:5555", "myuser@remote-server-ip")
socket.send(b"Hello")
reply = socket.recv()
最后,确保你已经安装了pexpect或paramiko中的一个,它们实际上会负责建立隧道。需要注意的是,如果你使用的是Windows,paramiko是唯一能用的解决方案,因为pexpect的openssh隧道在Windows上是无法工作的。
如果你使用paramiko而不是pexpect,确保在 tunnel_connection
的参数中设置 paramiko=True
。