Bi-directional communication using sockets via ssh tunnel

Viewed 2351

I have a server host (S) and a bunch of clients (C1, C2, C3, ...). I would like to open connection between S and C1, C2, C3 respectively for bi-directional communication. Ideally using sockets. SSH for authorisation purposes is preferred.

Ideally:

  1. Client C1 creates SSH reverse tunnel to S, forwarding C1's port so it is accessible on S as it's own port.
  2. Client program running on C1 creates a socket and binds to forwarded port.
  3. Server program running on S creates a socket and binds to forwarded port.
  4. Client and server can exchange data.

Is something like that possible? I tried coding up a draft using Python but to no avail:

Firstly, I run on C1: ssh -N -R 9999:localhost:15432 root@example.com - OK

Secondly, on server I run:

import socket

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 9999))
serversocket.listen(5)

while True:
    connection, address = serversocket.accept()
    buf = connection.recv(64)
    if len(buf) > 0:
        print buf
        break

Thirdly, on client I run:

import socket

clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 15432))
clientsocket.send('hello')

But I'm getting socket.error: [Errno 111] Connection refused on client. Also if I set up tunnel first and then launch server program, I'm getting [Errno 98] Address already in use. It only works when I first start the program, then set up a tunnel.

If aforementioned concept does not make sense, what would you suggest to create sort of synchronisation tool so any client listens for queries from the server and can respond with data? (preferrably in Python).

Thanks in advance.

1 Answers

-N doesn't do what you seem to think it does: it's intended for the ssh-destination to be able to connect back to the originator. But that would make the originating side the server.

It sounds like you should be using -L to simply create a connection from the client through the ssh tunnel to the server.

To demonstrate: I have a local server named 'bree'. On that machine, I execute (this could also be your python server listening on port 9999):

nc -l 9999

Now on my client machine, I execute this in one window (or could put it in the background):

ssh -N -L 9999:bree:9999 bree

This says: listen on the local (client) machine to port 9999, and when a connection to it is made, forward the request through the tunnel, and connect to port 9999 on bree.

Now, in a second window on the client machine, I execute:

nc localhost 9999

The two nc instances are connected.

Related