1. 程式人生 > >ZMQ示例:使用 curve 進行加密通信

ZMQ示例:使用 curve 進行加密通信

pubkey style sets 打印 發送 ons nts page 我們

1. ZMQ 官方文檔

ZMQ 的官方文檔中關於 curve 的介紹如下:

Client and server roles

A socket using CURVE can be either client or server, at any moment, but not both. The role is independent of bind/connect direction.

A socket can change roles at any point by setting new options. The role affects all zmq_connect and zmq_bind calls that follow it.

To become a CURVE server, the application sets the ZMQ_CURVE_SERVER option on the socket, and then sets the ZMQ_CURVE_SECRETKEY option to provide the socket with its long-term secret key. The application does not provide the socket with its long-term public key, which is used only by clients.

To become a CURVE client, the application sets the ZMQ_CURVE_SERVERKEY option with the long-term public key of the server it intends to connect to, or accept connections from, next. The application then sets the ZMQ_CURVE_PUBLICKEY and ZMQ_CURVE_SECRETKEY options with its client long-term key pair.

If the server does authentication it will be based on the client‘s long term public key.

  

官方文檔中提到的幾個點都很關鍵:

  • 一個 curve socket 既可以是服務端,也可以是客戶端。但不可以既是服務端的同時又是客戶端
  • 一個 socket 可以在任何 point (不知道怎麽翻譯 point 才合適)上通過設置新屬性的方式改變角色, 改變一個 socket 角色後,會影響接下來對這個 socket 做的所有 zmq_connect() 和 zmq_bind() 調用, 也就是說需要在這兩個調用之前進行 curve 屬性的設置。
  • 如果要把一個 socket 作為 curve server ,需要設置 ZMQ_CURVE_SERVER 和 ZMQ_CURVE_SECRETKEY 屬性
  • 如果要把一個 socket 作為 curve client,需要設置 ZMQ_CURVE_SERVERKEY 以及 ZMQ_CURVE_PUBLICKEY、ZMQ_CURVE_SECRETKEY 這三個屬性

2. 幾行核心代碼

想要使用 ZMQ curve 進行加密通信,需要在 ZMQ 的 server 端和 client 端進行相應的配置, 幾行需要進行的配置代碼如下:

2.1 curve server 端

1 char szsecertkey[128] = {0};
2 char szpublickey[128] = {0}; //需要把這個 curve 公鑰發給 client
3 zmq_curve_keypair(szpublickey, szsecertkey); 4 5 int option = 1; 6 zmq_setsockopt(sock, ZMQ_CURVE_SERVER, &option, sizeof(option)); 7 zmq_setsockopt(sock, ZMQ_CURVE_SECRETKEY, szsecertkey, strlen(szsecertkey)); 8 9 zmq_bind(sock, szaddr);

2.2 curve client 端

//這個 server_publickey 就是從 server 端拿到的 curve 公鑰
zmq_setsockopt(sock, ZMQ_CURVE_SERVERKEY, server_publickey, strlen(server_publickey));

char szpubkey[128] = {0};
char szprikey[128] = {0};
zmq_curve_keypair(szpubkey, szprikey); 
zmq_setsockopt(sock, ZMQ_CURVE_PUBLICKEY, szpubkey, strlen(szpubkey));
zmq_setsockopt(sock, ZMQ_CURVE_SECRETKEY, szprikey, strlen(szprikey));

zmq_connect(sock, szaddr);

3. 完整代碼及執行
3.1 完整代碼

代碼鏈接: https://pan.baidu.com/s/1ytJdEa2VmYWfSx6mxIKYVw 提取碼: ebyv

下載代碼後,解壓,執行編譯命令:

g++ -g -o server server.c -lzmq -lpthread 
g++ -g -o client client.c -lzmq


3.2 程序執行

代碼演示了兩個模式,一個是使用 curve 加密的傳輸模式,另一個是不使用 curve 加密的傳輸模式。 如果要使用 curve 加密的傳輸模式,需要在執行 server 和 client 程序的時候都加上 -s 參數。

1) 先執行 server

1 [root@fengbo 14:46:19 curve]$ ./server -s
2 server.c 80 : test tZMQ with curve
3 server.c 90 : szsecertkey = [I%43ZHg-Bnls&6rZ&)<J6hwGlD&I5l7]mi]{Ch-7]
4 server.c 91 : szpublickey = [kvIP^po{(kRL<eib#Zv=.cE%BpNom2DY#jl0-Ro[]
5 server.c 102 : start secert comunication
6 server.c 112 : recv msg : [I say 1]
7 server.c 119 : send msg : [I say 1, too]

2) 再執行 Client

1 [root@fengbo 14:46:18 curve]$ ./client -s
2 client.c 82 : test tZMQ with curve
3 client.c 94 : server publickey : [kvIP^po{(kRL<eib#Zv=.cE%BpNom2DY#jl0-Ro[]
4 client.c 102 : start secert comunication
5 client.c 109 : send msg : [I say 1]
6 client.c 112 : recv msg : [I say 1, too]

4. ZMQ curve 加密效果分析
通過對加密前與加密後的 ZMQ 消息進行 tcpdump 抓包,可以看到 ZMQ curve 的加密效果如何。

因為使用的是 127.0.0.1 作為測試地址,所以在使用 tcpdump 抓包的時候選擇 lo 網口:

tcpdump -i lo -A -vv -X


4.1 加密前的抓包記錄

對於不可打印的字符,tcpdump 都以點號 ‘.‘ 進行了顯示

 1 14:13:49.788893 >.E.........
 2 10:53:07.333841 <.E.>.E.....
 3 14:13:49.788919 >.E.
 4 14:13:49.788990 <.E...........
 5 14:13:49.788997 >.E.
 6 14:13:49.789294 <.E............
 7 14:13:49.789303 >.E.
 8 14:13:49.789634 <.E...NULL................................................
 9 14:13:49.789875 >.E..NULL................................................
10 14:13:49.789900 <.E..).READY.Socket-Type....DEALER.Identity....
11 14:13:49.790309 >.E.
12 14:13:49.790369 <.E..).READY.Socket-Type....DEALER.Identity......I.say.1
13 14:13:49.790561 >.E...I.say.1,.too
14 14:13:49.829945 <.E.

上面顯示的信息是經過簡化後的解析數據,不過可以看到 ZMQ 的兩個 socket 之間通信的細節,例如可以看到幾個 ZMQ 的關鍵字: DEALERSocket-TypeIdentity

以及 client 發送的數據 I say 1 ,和 server 返回的數據 I say 1, too

很明顯,數據在 ZMQ 中是以明文進行傳輸的。

4.2 加密後的抓包記錄

15:05:06.178841 ....>.6/........
09:09:44.849972 ....>.6/>.6/....
15:05:06.178864 >.6/>.6/
15:05:06.178975 >.6/>.6/..........
15:05:06.178982 >.6/>.6/
15:05:06.179369 >.6/>.6/...........
15:05:06.179376 >.6/>.6/
15:05:06.180410 >.60>.6/..NULL................................................
15:05:06.180571 >.61>.60.NULL................................................
15:05:06.180588 >.61>.60.).READY.Socket-Type....DEALER.Identity....
15:05:06.181017 >.61>.61
15:05:06.181064 >.61>.61.).READY.Socket-Type....DEALER.Identity......request.publickey
15:05:06.181191 >.61>.61.((#65P{8?aJEt@lWf/DDeQo@QX@gN{4nF3:?jz<^-
15:05:06.183369 ....>.63........
09:10:02.029846 ....>.63>.63....
15:05:06.183389 >.63>.63
15:05:06.183485 >.64>.63..........
15:05:06.183491 >.64>.64
15:05:06.183676 >.64>.64...........
15:05:06.183681 >.64>.64
15:05:06.184210 >.64>.64..CURVE...............................................
15:05:06.185457 >.66>.64.CURVE...............................................
15:05:06.188362 >.68>.66...HELLO........................................................
                 ....................{...:H_....."R&.....w.N..r..L...........Rv(b...F...
                 -+u.w....M...j).B.!<j....(..j...*..Qw........G.....c.....Y....:...
15:05:06.190931 >.6;>.68...WELCOME..6k.......,......a}.R..C.....>....|..a.z#...A[;..Yy..
                 ..F`......k.......~...k.fDa./../.A7..m..J......i.b.......<.k.....T.....
                 ..{[email protected]
15:05:06.196571 >.6A>.6;........$.INITIATEX......fXA..{J%D<...O\.i?4.3$.../.../J#....ZpF
                 xZ...r...pj...C.&.k,...]`KF..|.i4.H(K..W..Fm".BU...........!...x....<..
                 ....T....Z...6a....A....P.......c.V...........[E.n...|`@.~..5.aua..p...
                 #..N.7...._.....A....!.}....^Y2=2..)5..K.(.6+.e6]..`..$;..k".g.].~.A.Hn
                 ...GS%.U.ot..whb<..>..D15:05:06.201254 >.6E>.6A.A.READY.........H.f.n....sS.....p\.y.ZM..F........l........wY.3?G.
15:05:06.202853 >.6G>.6E.(.MESSAGE..........t.oR..&:.SI..QI.m.....
15:05:06.203034 >.6G>.6G.-.MESSAGE.............O]i.......9.M....to....#
15:05:06.220452 >.6Y>.61
15:05:06.242435 >.6o>.6G
15:05:08.539483 >.?h>.6G.(.MESSAGE.........3n..l6~~..N.....\..[:T.
15:05:08.539814 >.?h>.?h.-.MESSAGE...........<.3..A.9..Mq..=.........vs
15:05:08.539824 >.?h>.?h

從 tcpdump 抓取的數據可以看到 CURVE 這樣的字符,這說明 ZMQ 開始建立 curve 加密鏈接了。 不過在建立 curve 鏈接之前,有一個 client 向 server 請求公鑰的操作,我們甚至可以在抓到的數 據中看到 server 發送給 client 的公鑰 [(#65P{8?aJEt@lWf/DDeQo@QX@gN{4nF3:?jz<^-]。

因為傳輸公鑰是在建立 curve 鏈接之前進行的, 所以我們還是可以看到明文數據的。

在上面的抓包數據中, CURVE 關鍵字出現的時候,就是 server 和client 開始進行 curve 鏈接的過程了, 可以看到這幾個關鍵字:HELLO、WELCOME、INITIATEX、READY、MESSAGE。這些都是 ZMQ 的 curve 協議的一部分。

在上面的抓包數據中,我們沒有看到 I say 1,也沒有看到 I say 1, too。因為這些數據已經被加密傳輸了。 不過我們可以猜到,I say 1 和 I say 1, too 就跟在最後三行的兩個 MESSAGE 的後面,只不過被加密了,我們看不到。


同步發表:https://www.fengbohello.top/archives/zeromq-curve

ZMQ示例:使用 curve 進行加密通信