1ZPROXY(3) CZMQ Manual ZPROXY(3)
2
3
4
6 zproxy - run a steerable proxy in the background
7
9 // Create new zproxy actor instance. The proxy switches messages between
10 // a frontend socket and a backend socket; use the FRONTEND and BACKEND
11 // commands to configure these:
12 //
13 // zactor_t *proxy = zactor_new (zproxy, NULL);
14 //
15 // Destroy zproxy instance. This destroys the two sockets and stops any
16 // message flow between them:
17 //
18 // zactor_destroy (&proxy);
19 //
20 // Note that all zproxy commands are synchronous, so your application always
21 // waits for a signal from the actor after each command.
22 //
23 // Enable verbose logging of commands and activity:
24 //
25 // zstr_send (proxy, "VERBOSE");
26 // zsock_wait (proxy);
27 //
28 // Specify frontend socket type -- see zsock_type_str () -- and attach to
29 // endpoints, see zsock_attach (). Note that a proxy socket is always
30 // serverish:
31 //
32 // zstr_sendx (proxy, "FRONTEND", "XSUB", endpoints, NULL);
33 // zsock_wait (proxy);
34 //
35 // Specify backend socket type -- see zsock_type_str () -- and attach to
36 // endpoints, see zsock_attach (). Note that a proxy socket is always
37 // serverish:
38 //
39 // zstr_sendx (proxy, "BACKEND", "XPUB", endpoints, NULL);
40 // zsock_wait (proxy);
41 //
42 // Capture all proxied messages; these are delivered to the application
43 // via an inproc PULL socket that you have already bound to the specified
44 // endpoint:
45 //
46 // zstr_sendx (proxy, "CAPTURE", endpoint, NULL);
47 // zsock_wait (proxy);
48 //
49 // Pause the proxy. A paused proxy will cease processing messages, causing
50 // them to be queued up and potentially hit the high-water mark on the
51 // frontend or backend socket, causing messages to be dropped, or writing
52 // applications to block:
53 //
54 // zstr_sendx (proxy, "PAUSE", NULL);
55 // zsock_wait (proxy);
56 //
57 // Resume the proxy. Note that the proxy starts automatically as soon as it
58 // has a properly attached frontend and backend socket:
59 //
60 // zstr_sendx (proxy, "RESUME", NULL);
61 // zsock_wait (proxy);
62 //
63 // Configure an authentication domain for the "FRONTEND" or "BACKEND" proxy
64 // socket -- see zsock_set_zap_domain (). Call before binding socket:
65 //
66 // zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
67 // zsock_wait (proxy);
68 //
69 // Configure PLAIN authentication for the "FRONTEND" or "BACKEND" proxy
70 // socket -- see zsock_set_plain_server (). Call before binding socket:
71 //
72 // zstr_sendx (proxy, "PLAIN", "BACKEND", NULL);
73 // zsock_wait (proxy);
74 //
75 // Configure CURVE authentication for the "FRONTEND" or "BACKEND" proxy
76 // socket -- see zsock_set_curve_server () -- specifying both the public and
77 // secret keys of a certificate as Z85 armored strings -- see
78 // zcert_public_txt () and zcert_secret_txt (). Call before binding socket:
79 //
80 // zstr_sendx (proxy, "CURVE", "FRONTEND", public_txt, secret_txt, NULL);
81 // zsock_wait (proxy);
82 //
83 // This is the zproxy constructor as a zactor_fn; the argument is a
84 // character string specifying frontend and backend socket types as two
85 // uppercase strings separated by a hyphen:
86 CZMQ_EXPORT void
87 zproxy (zsock_t *pipe, void *unused);
88
89 // Selftest
90 CZMQ_EXPORT void
91 zproxy_test (bool verbose);
92 Please add '@interface' section in './../src/zproxy.c'.
93
95 A zproxy actor switches messages between a frontend and a backend
96 socket. It acts much like the zmq_proxy_steerable method, though it
97 makes benefit of CZMQ’s facilities, to be somewhat simpler to set-up.
98
99 This class replaces zproxy_v2, and is meant for applications that use
100 the CZMQ v3 API (meaning, zsock).
101
103 From zproxy_test method.
104
105 // Create and configure our proxy
106 zactor_t *proxy = zactor_new (zproxy, NULL);
107 assert (proxy);
108 if (verbose) {
109 zstr_sendx (proxy, "VERBOSE", NULL);
110 zsock_wait (proxy);
111 }
112 zstr_sendx (proxy, "FRONTEND", "PULL", "inproc://frontend", NULL);
113 zsock_wait (proxy);
114 zstr_sendx (proxy, "BACKEND", "PUSH", "inproc://backend", NULL);
115 zsock_wait (proxy);
116
117 // Connect application sockets to proxy
118 zsock_t *faucet = zsock_new_push (">inproc://frontend");
119 assert (faucet);
120 zsock_t *sink = zsock_new_pull (">inproc://backend");
121 assert (sink);
122
123 // Send some messages and check they arrived
124 char *hello, *world;
125 zstr_sendx (faucet, "Hello", "World", NULL);
126 zstr_recvx (sink, &hello, &world, NULL);
127 assert (streq (hello, "Hello"));
128 assert (streq (world, "World"));
129 zstr_free (&hello);
130 zstr_free (&world);
131
132 // Test pause/resume functionality
133 zstr_sendx (proxy, "PAUSE", NULL);
134 zsock_wait (proxy);
135 zstr_sendx (faucet, "Hello", "World", NULL);
136 zsock_set_rcvtimeo (sink, 100);
137 zstr_recvx (sink, &hello, &world, NULL);
138 assert (!hello && !world);
139
140 zstr_sendx (proxy, "RESUME", NULL);
141 zsock_wait (proxy);
142 zstr_recvx (sink, &hello, &world, NULL);
143 assert (streq (hello, "Hello"));
144 assert (streq (world, "World"));
145 zstr_free (&hello);
146 zstr_free (&world);
147
148 // Test capture functionality
149 zsock_t *capture = zsock_new_pull ("inproc://capture");
150 assert (capture);
151
152 // Switch on capturing, check that it works
153 zstr_sendx (proxy, "CAPTURE", "inproc://capture", NULL);
154 zsock_wait (proxy);
155 zstr_sendx (faucet, "Hello", "World", NULL);
156 zstr_recvx (sink, &hello, &world, NULL);
157 assert (streq (hello, "Hello"));
158 assert (streq (world, "World"));
159 zstr_free (&hello);
160 zstr_free (&world);
161
162 zstr_recvx (capture, &hello, &world, NULL);
163 assert (streq (hello, "Hello"));
164 assert (streq (world, "World"));
165 zstr_free (&hello);
166 zstr_free (&world);
167
168 zsock_destroy (&faucet);
169 zsock_destroy (&sink);
170 zsock_destroy (&capture);
171 zactor_destroy (&proxy);
172
173 // Test socket creation dependency
174 proxy = zactor_new (zproxy, NULL);
175 assert (proxy);
176
177 sink = zsock_new_sub (">ipc://backend", "whatever");
178 assert (sink);
179
180 zstr_sendx (proxy, "BACKEND", "XPUB", "ipc://backend", NULL);
181 zsock_wait (proxy);
182
183 zsock_destroy(&sink);
184 zactor_destroy(&proxy);
185
186 #if (ZMQ_VERSION_MAJOR == 4)
187 // Test authentication functionality
188 # define TESTDIR ".test_zproxy"
189
190 // Create temporary directory for test files
191 zsys_dir_create (TESTDIR);
192
193 char *frontend = NULL;
194 char *backend = NULL;
195
196 // Check there's no authentication
197 s_create_test_sockets (&proxy, &faucet, &sink, verbose);
198 s_bind_test_sockets (proxy, &frontend, &backend);
199 bool success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
200 assert (success);
201
202 // Install the authenticator
203 zactor_t *auth = zactor_new (zauth, NULL);
204 assert (auth);
205 if (verbose) {
206 zstr_sendx (auth, "VERBOSE", NULL);
207 zsock_wait (auth);
208 }
209
210 // Check there's no authentication on a default NULL server
211 s_bind_test_sockets (proxy, &frontend, &backend);
212 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
213 assert (success);
214
215 // When we set a domain on the server, we switch on authentication
216 // for NULL sockets, but with no policies, the client connection
217 // will be allowed.
218 zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
219 zsock_wait (proxy);
220 s_bind_test_sockets (proxy, &frontend, &backend);
221 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
222 assert (success);
223
224 // Blacklist 127.0.0.1, connection should fail
225 zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
226 zsock_wait (proxy);
227 s_bind_test_sockets (proxy, &frontend, &backend);
228 zstr_sendx (auth, "DENY", "127.0.0.1", NULL);
229 zsock_wait (auth);
230 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
231 assert (!success);
232
233 // Whitelist our address, which overrides the blacklist
234 zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
235 zsock_wait (proxy);
236 zstr_sendx (proxy, "DOMAIN", "BACKEND", "global", NULL);
237 zsock_wait (proxy);
238 s_bind_test_sockets (proxy, &frontend, &backend);
239 zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL);
240 zsock_wait (auth);
241 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
242 assert (success);
243
244 // Try PLAIN authentication
245
246 // Test negative case (no server-side passwords defined)
247 zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
248 zsock_wait (proxy);
249 s_bind_test_sockets (proxy, &frontend, &backend);
250 zsock_set_plain_username (faucet, "admin");
251 zsock_set_plain_password (faucet, "Password");
252 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
253 assert (!success);
254
255 // Test positive case (server-side passwords defined)
256 FILE *password = fopen (TESTDIR "/password-file", "w");
257 assert (password);
258 fprintf (password, "admin=Password\n");
259 fclose (password);
260 zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
261 zsock_wait (proxy);
262 zstr_sendx (proxy, "PLAIN", "BACKEND", NULL);
263 zsock_wait (proxy);
264 s_bind_test_sockets (proxy, &frontend, &backend);
265 zsock_set_plain_username (faucet, "admin");
266 zsock_set_plain_password (faucet, "Password");
267 zsock_set_plain_username (sink, "admin");
268 zsock_set_plain_password (sink, "Password");
269 zstr_sendx (auth, "PLAIN", TESTDIR "/password-file", NULL);
270 zsock_wait (auth);
271 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
272 assert (success);
273
274 // Test negative case (bad client password)
275 zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
276 zsock_wait (proxy);
277 s_bind_test_sockets (proxy, &frontend, &backend);
278 zsock_set_plain_username (faucet, "admin");
279 zsock_set_plain_password (faucet, "Bogus");
280 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
281 assert (!success);
282
283 if (zsys_has_curve ()) {
284 // We'll create two new certificates and save the client public
285 // certificate on disk
286 zcert_t *server_cert = zcert_new ();
287 assert (server_cert);
288 zcert_t *client_cert = zcert_new ();
289 assert (client_cert);
290 const char *public_key = zcert_public_txt (server_cert);
291 const char *secret_key = zcert_secret_txt (server_cert);
292
293 // Try CURVE authentication
294
295 // Test without setting-up any authentication
296 zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
297 zsock_wait (proxy);
298 s_bind_test_sockets (proxy, &frontend, &backend);
299 zcert_apply (client_cert, faucet);
300 zsock_set_curve_serverkey (faucet, public_key);
301 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
302 assert (!success);
303
304 // Test CURVE_ALLOW_ANY
305 zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
306 zsock_wait (proxy);
307 s_bind_test_sockets (proxy, &frontend, &backend);
308 zcert_apply (client_cert, faucet);
309 zsock_set_curve_serverkey (faucet, public_key);
310 zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
311 zsock_wait (auth);
312 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
313 assert (success);
314
315 // Test with client certificate file in authentication folder
316 zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
317 zsock_wait (proxy);
318 zstr_sendx (proxy, "CURVE", "BACKEND", public_key, secret_key, NULL);
319 zsock_wait (proxy);
320 s_bind_test_sockets (proxy, &frontend, &backend);
321 zcert_apply (client_cert, faucet);
322 zsock_set_curve_serverkey (faucet, public_key);
323 zcert_apply (client_cert, sink);
324 zsock_set_curve_serverkey (sink, public_key);
325 zcert_save_public (client_cert, TESTDIR "/mycert.txt");
326 zstr_sendx (auth, "CURVE", TESTDIR, NULL);
327 zsock_wait (auth);
328 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
329 assert (success);
330
331 zcert_destroy (&server_cert);
332 zcert_destroy (&client_cert);
333 }
334
335 // Remove the authenticator and check a normal connection works
336 zactor_destroy (&auth);
337 s_bind_test_sockets (proxy, &frontend, &backend);
338 success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose);
339 assert (success);
340
341 // Cleanup
342 zsock_destroy (&faucet);
343 zsock_destroy (&sink);
344 zactor_destroy (&proxy);
345 zstr_free (&frontend);
346 zstr_free (&backend);
347
348 // Delete temporary directory and test files
349 zsys_file_delete (TESTDIR "/password-file");
350 zsys_file_delete (TESTDIR "/mycert.txt");
351 zsys_dir_delete (TESTDIR);
352 #endif
353
354
356 The czmq manual was written by the authors in the AUTHORS file.
357
359 Main web site:
360
361 Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
362
364 Copyright (c) the Contributors as noted in the AUTHORS file. This file
365 is part of CZMQ, the high-level C binding for 0MQ:
366 http://czmq.zeromq.org. This Source Code Form is subject to the terms
367 of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
368 distributed with this file, You can obtain one at
369 http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
370 distribution.
371
373 1. zeromq-dev@lists.zeromq.org
374 mailto:zeromq-dev@lists.zeromq.org
375
376
377
378CZMQ 4.0.2 12/31/2016 ZPROXY(3)