Network

1. 前言:

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

   ZMQ社区在20139月发布了zmq4zmq4最大的新功能即提供了一套安全机制,其中有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)则是一个密钥协商协议。非常简单地讲,当AB在一个不受信任的网络中通讯前,AB先生成一对公私钥,并且AB通过某个完全的渠道事先知道对方的公钥,然后AB在握手阶段协商出一个双方公知的私钥供加密接下来的通讯。

    可以理解成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-keysecret-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并且拥有正确证书的客户端的连接,而且通讯通道被加密。

4. 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,否则编译期检查不到错误在运行期会崩溃。

Be the first to comment - What do you think?  Posted by zausiu - January 17, 2017 at 17:35

Categories: Network, Security, Tech Articles   Tags:

原来比特位也有大小端endinness.字节序和比特序的故事

我一直以为大小端endianness只针对字节,不针对比特位。
我一直以为全世界所有的cpu解释bit序都是一样的。

昨天才知道endianness也针对bit。 
于是就想不明白了。
因为观察到用 htonl 函数转换endianness后,bit位没有变化,只有字节顺序改了呀。

于是google呀,找到这篇好文:

http://www.linuxjournal.com/article/6788?page=0,0

Byte and Bit Order Dissection”(字节序和比特序深入剖析)

看了这篇文章,才知道 bit序的翻转是由硬件完成的。原来以前这方面很多概念都没理解对。

Be the first to comment - What do you think?  Posted by zausiu - September 13, 2016 at 19:52

Categories: Network, Tech Articles   Tags:

HTTP2简单教程

译自:http://qnimate.com/post-series/http2-complete-tutorial/

HTTP1.1是在1999年的时候被引入业界的。从当时到现在,WEB已经发生了相当大的变化。很多人开始用移动设备上网,有些移动环境下网络质量非常不稳定。另外,WEB页面的内容也相当的丰富了。这些都负面影响了WEB页面的加载时间。因此,需要一个新的协议来加速WEB的加载。

 

HTTP/2SPDY的区别:

SPDY是谷歌于2009年创造的协议,旨在WEB延迟以及增强安全性。

HTTP/2是SPDY的一个克隆。谷歌已经停止了继续开发SPDY,并且把工作转移到了HTTP/2上来。

 

HTTP/2的目标:

  1. 减少加载延时。
  2. 减少TCP连接数。
  3. 增强的网络安全。
  4. 保持和HTTP/1.1的兼容。

 

HTTP/2的功能:

  1. 多路复用Multiplexing:很多个异步的HTTP请求只使用一个TCP的连接。
  2. 服务端PUSH:对于一个请求可能有多个回复。
  3. 头部压缩:压缩头部(headers)。
  4. 请求分级:对同一个域名的请求可作优先级分级。
  5. 二进制协议:HTTP/2是一个二进制协议,而HTTP/1.1是一个文本协议。

 

HTTP/2解决了HTTP/1.1的哪些问题:

  1. HTTP管道(HTTP pipelining):一些HTTP1.1客户端使用了HTTP管道技术来减少TCP连接数。HTTP管道指的是多个HTTP请求被发往同一个TCP连接,而不等待前一个请求的回复。但是服务端发送回复时的顺序和收到的请求的顺序一样。因此,造成了HOL阻塞问题(head-of-line blocking)。HOL Blocking简单地说是一个回复的延迟会使得排在它后面的回复都会延迟。HTTP/2透过引用多路复用(Multiplexing)解决了这个问题。多个HTTP请求和多个HTTP回复都使用同一个TCP连续,而且HTTP回复的顺序不需要保持HTTP请求到达的顺序。
  2. 同一个域名的多个TCP连接:在使用HTTP/1.1时,需要对同一个域名起多个TCP连接来增加吞吐量。而使用HTTP/2时,对于每个域名,只充许有一个TCP连接(only one TCP connection per domain is allowed)。所有的请求和回复都通过唯一的一个TCP连接进行。
  3. TCP连接的关闭时间:使用HTTP1.1时,一个TCP连接在请求完成时立刻被关闭。但对于HTTP/2,TCP连接能存活相当成地一段时间。
  4. 头部压缩:HTTP/1.1是没有头部压缩的,但HTTP/2引入头部压缩进一步的减少了延时。

 

HTTP/2如何兼容HTT/1?

HTTP/2客户端在不确定对方服务器是否支持HTTP/2时,会用HTTP/1协议向服务器发送请求时带上Upgrade: HTTP/2.0这个头部。如果对方服务器支持HTTP/2,就会回复HTTP1.1 101,表示切换协议(Switching Protocols status)。而对于老旧的服务器则简单地返回HTTP/1.1的状态。

HTTP/2客户端可以记下哪些服务器支持HTTP/2,这样,下次就可以直接发起HTTP/2请求,而不必再经过一个询问和回复(Upgrade Round Trip).

 

HTTP/2中的多路复用是怎么回事?

HTTP/2使用多路复用,多个请求和回复全异步的通过同一个TCP连接收发。

HTTP/2是一个二进制的协议。每一个请求和回复都被分配了一个流标志(Stream ID),而且请求和回复被切成了很多帧(Frame),属于同一个请求或回复帧的Stream ID相同。因为有了这个Stream ID和Frame的机制,请求和回复可以在服务器和客户程序两端同时全异步的发送。因此,HTTP2没有了Head-of-line Blocking的问题。

每一个Stream还可以被赋于一个优先级,服务器可以分配更多的系统资源处理高优级的Stream。

HTTP/2还有一个传输层级别的流控。它协商了客户程序和服务器两端最多使用多少个Stream,服务器能处理的最大尺寸的Stream以及整个连接最多处理多少字节,以及数据被发送的速率。

 

HTTP/2中的服务器推送(Server Push)和承诺(Promise)

当服务器“感觉”到客户程序需要更多的资源时,就会给客户程序发送一个Promise Stream ,提醒客户程序需要什么资源。这些stream比一般的stream的优先级要高。

这项技术在加载网页时非常用户,因为网页的大量css和javascrpit可能通过这种方式发送。而HTTP/1的作法是把css和js都combine到一起。

服务器发送Promise Stream时提醒的资源遵守同源策略(same origin policy)

HTTP/2中的头部压缩:

HTTP/2的头部压缩和HTTP/1.1中早有的用gzip压缩Body不一样。使用HTTP/2时,在客户程序和服务器两端,都会保存一张表,记录了收到过的头部。它们在发送HTTP时不会重复发送一样的头部,当再次发送相同的头部时,只会发送该头部对应的表的索引号。

copyright blog.ykyi.net

Be the first to comment - What do you think?  Posted by zausiu - April 3, 2015 at 16:22

Categories: Network, Tech Articles   Tags:

Next Page »