Foundations of Python Network Programming

(WallPaper) #1

Chapter 6 ■ tLS/SSL


98


There exist more complicated arrangements than a CA that directly signs certificates for server use. For example,
some organizations want their servers to use only short-lived certificates that last a few days or weeks before expiring.
This minimizes the damage if a server is compromised and its private key is stolen. Instead of having to contact (and
pay) the CA organization every few days for a replacement, such an organization can have the CA sign a longer-lived
intermediate certificate whose private key the organization holds as a close secret and uses to sign the user-visible
certificates that actually get put on servers. The resulting certificate chain or chain of trust combines the flexibility of
having your own CA (because you can sign new certificates whenever you please) with the benefit of a recognized
public CA (because you do not have to install a custom CA certificate in every browser or client that wants to talk to
you). As long as your TLS-powered server provides clients with both its own particular server certificate as well as
with the intermediate certificate making the cryptographic link back to the CA certificate that the client knows to trust,
client software should have no problem validating their identity.
Consult books or documentation about certificate signing if you find yourself tasked with establishing the
cryptographic identity of your organization and its services.


Offloading TLS


Before showing you how to use TLS from Python—especially if you are about to write a server—I should note that
many experts would ask why you want to perform encryption directly inside your Python application in the first
place. After all, many tools already exist that have carefully implemented TLS and can take charge of answering client
connections on your behalf and forwarding the unencrypted data to your application if you run it on another port.
A separate daemon or service that provides TLS termination for your Python application might be easier to
upgrade and tweak than the combination of your own server code, Python, and the underlying OpenSSL library.
In addition, a third-party tool will often expose TLS features that the Python ssl module, even under Python 3.4,
does not yet allow you to customize. For example, the vanilla ssl module currently seems to make it impossible to
use ECDSA elliptic curve signatures or to fine-tuning session renegotiation. Session renegotiation is a particularly
important topic. It can significantly reduce the CPU cost of offering TLS, but if configured poorly, it can compromise
your ability to promise Perfect Forward Security (see the “Hand-Picked Ciphers and Perfect Forward Security”
section). The old 2013 blog post at https://www.imperialviolet.org/2013/06/27/botchingpfs.html, “How to
botch TLS forward secrecy,” is still one of the best introductions to the topic.
Front-end HTTPS servers are a good example of third-party daemons that provide TLS termination. It is
particularly easy for a third-party tool to wrap HTTP because the HTTPS standard specifies that the client and server
should go ahead and negotiate encryption first before any protocol-specific messages pass over the channel. Whether
you deploy Apache, nginx, or some other reverse proxy in front of your Python web service as an extra level of defense
or instead subscribe to a content delivery network like Fastly that tunnels requests through to your own servers, you
will find that TLS can disappear from your Python code and into the surrounding infrastructure.
But even a raw socket protocol of your own, for which no third-party tools are available, could accept third-
party TLS protection if you set up a simple daemon such as stunnel to run on your public TCP port and forward the
connections to your service privately.
If you do choose the course of offloading TLS to another tool, then you can probably just skim the rest of
this chapter (to get familiar with the knobs for which you will be looking) before getting started on the tool’s
documentation. It will be that tool, and not Python itself, which will load your certificate and private key, and it will
need to be properly configured to provide the level of protection against weak ciphers that you require. The only
question to ask is how your front end of choice will tell your Python service the remote IP address and (if you are
using client certificates) the identity of each client that has connected. For HTTP connections, information about the
client can be added to the request as additional headers. For more primitive tools like stunnel or haproxy that might
not actually be speaking HTTP, extra information like the client IP address will have to be prepended as extra bytes in
front of the incoming data stream. Either way, the tool itself will be providing the TLS superpowers that the rest of this
chapter will illustrate using pure Python sockets instead.

Free download pdf