Tawy
Tawy

Reputation: 629

RPyC connection through proxy

Context

I have a private server, reachable by using a public server as a proxy

|------|       |------|       |-------|
|Remote|  ->   |Public|  ->   |Private|
|------|       |------|       |-------|

I can connect to the private server (ssh keys are correctly set up) with

user@remote:$ ssh user@public
user@public:$ ssh user@private
user@private:$

Or in one line:

user@remote:$ ssh -o ProxyCommand='ssh -W %h:%p user@public' user@private

Problem:

Now, I wish to be able to send RPyC requests from the remote machine directly to the private server.

As an insight for why I need it: the remote machine has a camera while the private server has gpus (and there is a good connection between the two)

What I've tried so far

I managed to run a SSL connection as in RPyC SSH connection

conn = rpyc.ssl_connect("private", port = 12345, keyfile="/path/to/my.key", certfile="/path/to/my.cert")

with key and certificate obtained with something like Create a self signed X509 certificate in Python.

Now, it works IF the client has been launched from the public server. I don't know how to redirect the SSL connection from the remote machine.

Something else that I have tried is to declare a plumbum SshMachine as the Zero-Deploy tutorial indicate (https://rpyc.readthedocs.io/en/latest/docs/zerodeploy.html)

mach = SshMachine("user@private", ssh_opts=["-o ProxyCommand='ssh -W %h:%p user@public'"]

I can launch a Zero-Deploy server using this, but this is not satisfying because it uses a fresh (temporary) copy of python and I need to use the installed libraries from private server (e.g. cuda setup).

Of course, I cannot combine the two approaches since ssl_connect requires a string as hostname and raises an exception if given a SshMachine.

Constraints

I don't have root access neither to private nor public servers, but any library that can be installed with pip is ok. I have tried looking e.g. at paramiko but I am not sure where to start...

Update

I found a solution (see answer https://stackoverflow.com/a/68535406/6068769), but I still have a few questions so I don't accept it yet:

plumbum.machine.session.SSHCommsError: SSH communication failed
Return code:   | 255
Command line:  | 'true '
stderr:        | /bin/bash: line 0 : exec: ssh -W private:22 user@public : not found

I can live with opening the connection beforehand but it would be cleaner if I don't have to.

Upvotes: 1

Views: 693

Answers (1)

Tawy
Tawy

Reputation: 629

Ok, I was not far, I just missed the method rpyc.ssh_connect.

Here is the MWE:

## Server
import rpyc

class MyService(rpyc.Service):
    def on_connect(self, conn):
        pass

    def on_disconnect(self, conn):
        pass

    def exposed_some_computations(self, input):
        return 2*input

if __name__ == "__main__":
        from rpyc.utils.server import ThreadedServer
        server = ThreadedServer(MyService, port=12345)
        server.start()
## Client
from plumbum import SshMachine
import rpyc

mach = SshMachine("user@private", ssh_opts=["-o ProxyCommand='ssh -W %h:%p user@public'"])

conn = rpyc.ssh_connect(mach, 12345)
result = conn.root.exposed_some_computations(18)

Upvotes: 3

Related Questions