前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实战ZMQ4.x的安全机制

实战ZMQ4.x的安全机制

原创
作者头像
kamuszhou
发布2018-07-19 17:06:00
2.6K0
发布2018-07-19 17:06:00
举报

这是大概一年半以前(2016年12月)写的一篇旧技术文章,也搬来了!

//////////////////////////////////////

1. 前言:

  ZeroMq aka zmq是最知名的网络消息中间件之一。使有zmq的开源软件中最知名的莫过于Apache基金会下的Storm。我厂内部使用zmq的有即通的yaaf框架。

   ZMQ社区在2013年9月发布了zmq4。zmq4最大的新功能即提供了一套安全机制,其中有IP黑白名单,用户名/密码鉴权,ECC(Elliptic Curve Cryptography)证书鉴权,以及通讯的加密(类似TSL)。

   本文主要介绍zmq4.0的安全机制。

2. ECC的故事:

   这里的ECC不是我厂历史上的电商事业群,而是椭圆曲线加密算法。ECC据说被NSA(美国安全局)操作,在算法中设置了后门。不过好在不是只有一种椭圆曲线,而是有无数种,不同的曲线有不同的优点和缺点,只是其中由NIST(美国标准和技术研究署)推荐的曲线被怀疑设置了后门。

   ZMQ使用的椭圆曲线算法是Curve25519 ,它有开源实现而且没有专利保护。zmq用了长度为256bits的密钥,强度相当于RSA 3072比特的密钥长度。

   ECDH(Elliptic Curve Diffie-Hellman)则是一个密钥协商协议。非常简单地讲,当A与B在一个不受信任的网络中通讯前,A和B先生成一对公私钥,并且A和B通过某个完全的渠道事先知道对方的公钥,然后A和B在握手阶段协商出一个双方公知的私钥供加密接下来的通讯。

    可以理解成zmq设计了一个专门为自己定制的精简的TLS,更多的理论细节在http://curvezmq.org/page:read-the-docs

作为一个码农,下面用代码介绍使用zmq4的Curve安全机制

3. 证书鉴权,通讯加密,IP 白名单

编译zmq4.x以后,会生成一个名叫curve_keygen的程序,用它可以生成zmq 的证书。证书是一个一般的文本文件,如下是一个curve_keygen生成的zmq证书的例子。

#   \*\*\*\*  Generated on 2017-01-02 14:24:20 by CZMQ  \*\*\*\*

#   ZeroMQ CURVE \*\*Secret\*\* Certificate

#   DO NOT PROVIDE THIS FILE TO OTHER USERS nor change its permissions.



metadata

    email = "kamuszhou@tencent.com"

curve

    public-key = "!Upjrn]2Dk)jQkYREsceBnpgoIL7koE{CVnV1j4D"

    secret-key = "ZPT#=l/#Rtg:TeLbofh:uPi7#/w(GDZq[0^qPZA1"

字段很好理解,最重要的是public-key和secret-key字段。

下面是一段客户端的相关代码片断(使用官方的czmq库,czmq是官方维护的High-level C库封装了底层的C API接口):

  // 创建一个DEALER类型的zmq socket

  zsock\_t\* dealer = zsock\_new(ZMQ\_DEALER);

  assert (dealer\_ != NULL)



  // 假设路径~/my.cert存了客户端的证书,证书里需要既有公钥又有私钥,载入证书再应用这个证书到socket句柄上。然后就可以销毁证书句柄了

  zcert\_t\* my\_cert = zcert\_load("~/my.cert");

  assert (my\_cert != NULL);

  zcert\_apply(my\_cert, dealer\_);

  zcert\_destroy(&my\_cert);



  // 设置服务器的公钥

  zsock\_set\_curve\_serverkey(dealer, "I7[{YV4[}q[9a)]b&d>bisoT]UXa/7b$Tp:6yoyq");

    

  // 连接在本机监听8888端口的服务器

  zsock\_connect(dealer, "%s", "tcp://localhost:8888"); 下面是服务端的相关代码片断:

   // 创建一个ROUTER zmq socket

zsock_t* router_sk = zsock_new(ZMQ_ROUTER);

   assert(router_sk != NULL);

  /* CZMQ4库封装了一个actor服务器模型,详细的官方接口说明在http://api.zeromq.org/CZMQ3-0:zactor 其中zactor_new用来创建一个actor,回调函数填zauth。zauth是CZMQ定义好的一个回调函数,里面做了很多鉴权的准备工作。照抄就行。通过向actor通讯设置如何鉴权。*/

   zactor_t* auth = zactor_new(zauth, NULL);

   // 打印详细的鉴权相关日志

zstr_send(auth, "VERBOSE");

// 必须调用这个函数与actor同步。下同

   zsock_wait(auth);

  // 这里开启白名单,允许”127.0.0.1”和"127.0.0.2"访问本服务。如果用黑名单也类似,但第二个参数设为”DENY”

   zstr_sendx(auth, "ALLOW", "127.0.0.1", "127.0.0.2", NULL);

   zsock_wait(auth);

/* 假设 ~/cert目录夹下面存放了客户端的证书(只有公钥) 下面的代码让只有拥有证书的客户端才能连接服务*/

   zstr_sendx(auth, "CURVE", "~/cert", NULL);

   zsock_wait(auth);

// router_sk 这个zmq套接字是作为服务端使用的

   zsock_set_curve_server(router_sk, 1);

// 加载服务端自己的证书,这个证书文件里需要既有公钥也有私钥

   zcert_t* my_cert = zcert_load("~/server.cert");

   assert(my_cert != NULL);

   zcert_apply(my_cert, router_sk);

zcert_destroy(&my_cert);

   // router套接字监听8888端口

   int ret = zsock_bind(router_sk, "%s", "tcp://localhost:8888");

   assert(ret != -1);

 至此,服务端只接受来自127.0.0.1并且拥有正确证书的客户端的连接,而且通讯通道被加密。

  1. Notice & Bug

a. 在实战过程中,发现一个czmq4库的bug,如果一个zmq socket作为server端并使用curve鉴权,就必须调用bind(),而不能调connect(),否则进程会崩溃。但是在zmq的世界中,server端的socket也是可以调connect的。在czmq4的官方github页面上找到有人已经报告了这个bug,可能下个版本会修复吧。

https://github.com/zeromq/czmq/issues/1470

b. czmq4实现的reactor模型不支持监控zactor对象.

c. czmq4有很多函数的参数个数是不确定的,这些函数的最后一个参数并须填NULL,否则编译期检查不到错误在运行期会崩溃。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 前言:
  • 2. ECC的故事:
  • 3. 证书鉴权,通讯加密,IP 白名单
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档