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.