[nanomsg] Adding support for TLS

  • From: Garrett D'Amore <garrett@xxxxxxxxxx>
  • To: nanomsg@xxxxxxxxxxxxx
  • Date: Sun, 23 Mar 2014 18:34:34 -0700

I’d like to add support to my Go based SP implementation for encrypted TLS as a 
transport.

From a code standpoint, this is pretty trivial.  There are some details I’d 
have to arrange in the setup, as we would need to establish certificates, etc.  
But those are API details, and not terribly difficult to handle in Go.  (Far 
uglier in C with OpenSSL… Gak… or even worse, libnss and PKCS#11!)  Most modern 
languages offer a very sane and natural way to interact with SSL or TLS.

It took me about 20 minutes to add IPC based on Unix domain sockets, given TCP. 
 I suspect TLS will take longer… maybe 30 - 40 minutes. :-)  That includes 
writing the tests. :-)

Anyway, we need to have a common agreement about wire formats, and addresses.  
This becomes more important now that there exists more than a single 
implementation of nanomsg’s SP protocols.  (Btw, I’m *not* sure this can be 
said to be true of 0MQ. :-)

I propose that for TLS, we would have the following:

1. Addresses look the same as TCP, but take the form “tis://<server>:<port>” .  
No provision is made in the *address* for specify certificates, SSL/TLS 
protocol version, cipher options, etc. The natural way to handle those is via 
socket options or something similar.  (“Implementation specific.”)

2. The “wire-format” packet exchanges follow the same format as for TCP, except 
that the message exchanges will occur over an encrypted TLS stream, rather than 
a TCP stream.  That is, the same 8 byte bi-directional handshake will occur at 
the start of the connection, and the same 8 byte length (big endian) will 
precede each message exchanged.  

None of the above is meant to be a surprise.  In fact, it is meant to be the 
most trivial mapping of the TCP protocol to layer on top of TLS.  But doing 
this gives immediate usability of the nanomsg protocols over untrusted 
transports.  I’d be happy to spend some cycles implementing C extensions to 
support this as well in libnanomsg itself, but that will require importing 
OpenSSL.  (I have *no* desire to reimplement all of SSL/TLS from scratch, and 
any the most naive and security-ignorant fool would desire this, given the 
“challenges” associated in creating a “correct” implementation of SSL/TLS. :-)

As a side note, I noticed that when we “package” nanomsg, we don’t include the 
RFC subdirectory.  I think this is a mistake.  There are various legitimate 
reasons why the protocol details should be readily available to other 
consumers.  (Indeed, I’ve considered writing snoop or tcpdump extensions to 
decode the handshake… I think this would be useful to administrators trying to 
figure out what is going on.  I spent a bunch of time debugging my 
implementation only to discover that I had a bug where I had stashed REP 
instead of REQ during the protocol negotiation.   The silent hangup and retry 
behavior of nanomsg made debugging this scenario more challenging that I would 
have expected. ;-)

Thanks.

        - Garrett


Other related posts: