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
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)
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.
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...
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:
ssh -o ....
). Otherwise, the SshMachine refuses to connect with the following errors: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.
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)