[nanomsg] Re: end-to-end security

  • From: Laurent Alebarde <l.alebarde@xxxxxxx>
  • To: nanomsg@xxxxxxxxxxxxx
  • Date: Tue, 11 Mar 2014 18:00:12 +0100

I did developp a mechanism for libzmq (not published), I came to the conclusion that adding a security mechanism inside libzmq is not a good solution for the following reasons:


1. it complexify the library internals drastically, what is bad for
   quality of its primer objectives.
2. The library was not designed for security at the beginning, so it
   has lead to bad design and hard-to-maintain code.
3. In the case of libzmq, mechanisms are processed in the I/O threads,
   which is not what I wanted.
4. Still with libzmq, I could not easily proxy security mechanisms,
   i.e. end-to-end with intermediate untrusted nodes: I had to stack
   three protocol layers: ZMTP + my security mechanism + ZMTP again, to
   succeed. The result works, but is heavy to maintain.

That made me redevelop my security stack in a separate library, independent from libzmq. So now, I can choose libzmq or nanomsg or whatever. I have a simple API that do not require integration with the messaging library, and that work only on buffers :

1. receive_handcheck_message
2. send_handcheck_message
3. is_handcheck_finished
4. encode
5. decode

The big advantages are:

1. messaging library independence.
2. usable for any SP or transport

The only thing I will add is a structure mapping to the buffers to obtain zero copy.

Just my humble thoughts worthing no more than 2 cts, but I have wasted three months to come out to that. I hope you will save your time and efforts.

Laurent.


Le 11/03/2014 13:59, Drew Crawford a écrit :
Hello folks,

I’ve written before to gauge the interest level on landing encryption support to nanomsg.

After my last post, I tentatively decided to go with a libzmq-based solution. However, for reasons outside the scope of this list, that hasn’t gone as well as I’d liked, and I’m now thinking about nanomsg once again.

The problem is important enough that I actually have time to work on it, and due to time constraints I’m going to settle on some solution in the next few days. The only open question at this point is whether I’m going to land patches in nanomsg, or whether I’m going to be doing some kind of private solution, like a private fork or wrap of some library. I’d prefer the former if possible.

I’d like to make a concrete proposal for comment. As far as I can tell, there hasn’t been further discussion on the subject of encryption since my last post. Here is what I’m thinking on design decisions:

  * End-to-end, “well-above-transport-layer” security.  Don’t get me
    wrong, there is a good case for transport-layer security.  Zeromq
    has used it with some success.  I use it right now.  The thing is,
    I’ve become convinced it’s the wrong approach for **my** set of
    problems.
      o Zeromq's support gets poor when you move out of TCP transport.
         It would be a lot of work for them to support IPC, for
        example, which I’m mildly interested in.  I suspect that UDP
        is somewhat challenging as well, which is a long-term goal.
         Doing security work near the surface means it’s completely
        decoupled from adding new transports, which is good if you
        want new transports, and also good if you want security to
        work with them.
      o Patches to the cryptography require deep knowledge of zeromq
        internals, and the people with the right knowledge are often
        busy.  When minor features to security are needed it creates
        major delays.  If security sits near the surface it requires
        knowledge of mostly public APIs and so cryptography work can
        proceed without scheduling meetings with core committers to
        understand the obscure internal design of the day.
  * Focus on REQ/REP, and maybe DEVICE, which are the sockets I’m
    interested in.  The other socket types can wait until somebody is
    sufficiently motivated to make security work for those socket types.
  * Stick close to CurveCP where sensible, but allow for some
    experimentation.  Maybe the user can choose from several competing
    security mechanisms.


Here are some concrete API proposals:

  * New values for nn_getsockopt, nn_setsockopt:

      o Setting/getting various public and private keys
          + Applications would rely on these values for security, so
            it is important that a remote attacker cannot set
            arbitrary socket options
      o Switching between authentication mechanisms, if several are
        supported, or using no authentication.

  * Reporting authentication errors.  A logical place to do this would
    be from nn_connect, however, my understanding is that the
    transport connection isn’t established at that time.  One
    possibility is to introduce a separate nn_authenticate function,
    called after nn_connect and before send/receive.  Another
    possibility is to report errors from send/receive themselves.
  * On a socket that has opted in to security, nn_send and nn_recv
    encrypt, decrypt, and verify messages as appropriate. Sockets not
    opted in are unaffected.
      o New APIs nn_send_raw and nn_recv_raw allow unencrypted
        reads/writes on sockets that have opted into security
  * The entire enterprise should be documented for the forseeable
    future as experimental, unstable and not for use on nukes


Again, I’m volunteering to land all of this, pretty soonish, if this is basically sounding like a patch you want to merge. And I am happy to collect feedback and refine some of these details as appropriate.

However, I’d rather not bikeshed on this, as I have done enough bikeshedding about encryption features for message-queue projects to last many lifetimes ;) So if this work overall isn’t feeling right for core, I am completely happy to find a place to do it that isn’t in core. My feelings won’t be hurt.

Drew

Other related posts: