SSL

Python 2.6 introduced the ssl module, and RPyC can now integrate with it. If you wish to use ssl on versions earlier than Python 2.6, see the ssl-wrapper.

Using external tools, you can generate client and server certificates, and a certificate authority. After going through this setup stage, you can easily establish an SSL-enabled connection.

Server side:

from rpyc.utils.authenticators import SSLAuthenticator
from rpyc.utils.server import ThreadedServer

# ...

authenticator = SSLAuthenticator("myserver.key", "myserver.cert")
server = ThreadedServer(SlaveService, port = 12345, authenticator = authenticator)
server.start()

Client side:

import rpyc

conn = rpyc.ssl_connect("hostname", port = 12345, keyfile="client.key",
                        certfile="client.cert")

For more info, see the documentation of ssl module.

SSH Tunneling

SSL is a bit too complicated: you must generate certificates for each client and server, sign them, manage the CA chains, etc. It’s usually an overkill for the normal use-case of RPyC. Instead, SSH offers a much easier approach. Conceptually, SSH is similar to SSL, but requires considerably less setup: once two machines are acquainted, you can easily set the trust-relations between them using the authorized_keys and known_hosts configuration files. You can also use interactive password authentication, in case it’s desired.

SSH is first-and-foremost a shell-protocol, but it includes tunneling support. This means you can route “unaware” connections over a tunnel, and get encryption and authentication for free. Setting up tunnels is not at all complicated, but in order to make life even easier, RPyC comes bundled with SSH-tunneling support (of course you’ll need an SSH client installed and configured, in order to use it).

Usage

In order to use the built-in SSH tunneling support, you’ll first have to start a server on you host, binding the server to the localhost on some port, say 12345. Binding the server to the localhost means that the server cannot accept external connections – which is crucial for our security scheme.

Next, from your client machine, you’ll create an SshContext. The context object holds all the information required to establish an SSH connection from your client machine to the host machine – host name, port, user name, keyfile, SSH program, etc. If the two machines are “acquainted” and your ssh/config is set up accordingly, the context can be pretty much empty, as all the required information already exists. If not, you’ll need to include this information programmatically, like so:

from rpyc.utils.ssh import SshContext

sshctx = SshContext("myserver", user = "foo", keyfile = r"/path/to/my/keyfile")

And then, establishing a connection over SSH is a one-liner:

conn = rpyc.ssh_connect(sshctx, 12345)

When establishing the connection, RPyC will first set up an SSH tunnel from your client machine to the host machine, using the credentials given by the SshContext, and then use this tunnel to create the actual RPyC connection.

The tunneled-connection consists of three parts:

  • A socket from port X on the client machine (the RPyC client) to port Y on the client machine (first side of the tunnel)
  • A socket from port Y on the client machine (the first side of the tunnel) to port Z on the server machine (second side of the tunnel) – this is the encrypted connection.
  • A socket from port Z on the server machine (the second side of the tunnel) to port W on the server machine (the RPyC server itself)

And RPyC makes the necessary arrangements to hide these details from you.