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.