ZMQ send/receive connection over ssh

Viewed 243

I'm attempting to create a ZMQ send/receive connection between my local machine in c++ and a remote machine in python. I'm accessing the remote machine through SSH.

Right now, I connect to a socket tcp successfully on my local C++ code, which outputs the port number. Then, I take this port number and plug it into this python code on my remote machine:

from zmq import ssh
import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)
tcp_address = "tcp://0.0.0:" + str(55555) # tcp address output from local machine
ssh.tunnel_connection(socket,tcp_address,'username@remote',password='remoteloginpassword')   
 
request = b'someRequest'
socket.send(request)
print("request sent")
reply = float(socket.recv())
print("Reply received: {}".format(reply))

Unfortunately, ZMQ throws an exception (cutting some out to protect private info):

    133 
    134     """
--> 135     new_url, tunnel = open_tunnel(addr, server, keyfile=keyfile, password=password, paramiko=paramiko, timeout=timeout)
    136     socket.connect(new_url)
    137     return tunnel

~/.virtualenvs/preboa-env/lib/python3.5/site-packages/zmq/ssh/tunnel.py in open_tunnel(addr, server, keyfile, password, paramiko, timeout)
    161         tunnelf = openssh_tunnel
    162 
--> 163     tunnel = tunnelf(lport, rport, server, remoteip=ip, keyfile=keyfile, password=password, timeout=timeout)
    164     return 'tcp://127.0.0.1:%i'%lport, tunnel
    165 

~/.virtualenvs/preboa-env/lib/python3.5/site-packages/zmq/ssh/tunnel.py in openssh_tunnel(lport, rport, server, remoteip, keyfile, password, timeout)
    234             i = tunnel.expect([ssh_newkey, _password_pat], timeout=.1)
    235             if i==0:
--> 236                 raise SSHException('The authenticity of the host can\'t be established.')
    237         except pexpect.TIMEOUT:
    238             continue

SSHException: The authenticity of the host can't be established.

Does anyone have any suggestions as to what I need to do to fix this? Mind you, I can easily connect to the server through my terminal with just a password (don't need any SSH keys or anything beyond that). In fact, I see this exception when I connect to the remote server for the first time but it does not prevent me from connecting. Also, I know for sure it is on the remote side of things, because this code and the tcp port work fine when I run it locally.

I referenced ZMQ's documentation but don't see any issues with my implementation. I looked around on stack overflow and didn't find anything that helped me.

Thank you!

1 Answers

Q : Does anyone have any suggestions as to what I need to do to fix this?

Yes, let's start, step by step:

  1. your SSH-connection got rejected, so first repair the SSH-service

  2. once SSH-connection will hold, without rejected connection setups, I would rather use an extended SSH-service, using so called port-forwarding. Given this, a configuration will allow us to use any of the free local/remote port-numbers to get served by the SSH-connection port-forwarding/ssh-tunneling features, so that your actual application does not recognise any of these setup tricks and just keeps to .bind()/.connect() onto these localhost mapped port#-s

  3. maintaining your port-forwarding/ssh-tunneling configurations helps you keep you network-of-ZeroMQ-agents work in any external world, isolating the processing of any actual changes just by "administrative"-only-maintenance, performed on the SSH-configuration port-mapping setup.

...
aSocketA.bind( "tcp://{0:}:{1:}".format( config_localhost_IP,
                                         config_service_X_PORT ) )
...

Sure, the SSH-port-forwarding cannot "groom" many-to-one connections, yet there is no need to expect this from the SSH-sevice-plane, this is a native property built-in into the ZeroMQ engine, so we can just .bind() as many incoming ( SSH-port-forwarded )-ports as needed.

...
for aPortToBIND in ( config_service_X_PORT,
                     config_service_Y_PORT,
                     config_service_Z_PORT,
                     config_service_U_PORT,
                     ...
                     ):
    aSocketA.bind( "tcp://{0:}:{1:}".format( config_localhost_IP,
                                             aPortToBIND ) )
...

That helped me keep my infrastructure up and running for more than 10-years

... hard to believe, how fast is the time passing ;)

Related