1ZPROXY(3)                         CZMQ Manual                        ZPROXY(3)
2
3
4

NAME

6       zproxy - Class for run a steerable proxy in the background
7

SYNOPSIS

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       //  When the socket type is XSUB or SUB, topic(s) string(s) can be passed as
36       //  additional arguments (NOTE: in DRAFT state) and the socket will subscribe
37       //  using them.
38       //
39       //  Specify backend socket type -- see zsock_type_str () -- and attach to
40       //  endpoints, see zsock_attach (). Note that a proxy socket is always
41       //  serverish:
42       //
43       //      zstr_sendx (proxy, "BACKEND", "XPUB", endpoints, NULL);
44       //      zsock_wait (proxy);
45       //
46       //  Capture all proxied messages; these are delivered to the application
47       //  via an inproc PULL socket that you have already bound to the specified
48       //  endpoint:
49       //
50       //      zstr_sendx (proxy, "CAPTURE", endpoint, NULL);
51       //      zsock_wait (proxy);
52       //
53       //  Pause the proxy. A paused proxy will cease processing messages, causing
54       //  them to be queued up and potentially hit the high-water mark on the
55       //  frontend or backend socket, causing messages to be dropped, or writing
56       //  applications to block:
57       //
58       //      zstr_sendx (proxy, "PAUSE", NULL);
59       //      zsock_wait (proxy);
60       //
61       //  Resume the proxy. Note that the proxy starts automatically as soon as it
62       //  has a properly attached frontend and backend socket:
63       //
64       //      zstr_sendx (proxy, "RESUME", NULL);
65       //      zsock_wait (proxy);
66       //
67       //  Configure an authentication domain for the "FRONTEND" or "BACKEND" proxy
68       //  socket -- see zsock_set_zap_domain (). Call before binding socket:
69       //
70       //      zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
71       //      zsock_wait (proxy);
72       //
73       //  Configure PLAIN authentication for the "FRONTEND" or "BACKEND" proxy
74       //  socket -- see zsock_set_plain_server (). Call before binding socket:
75       //
76       //      zstr_sendx (proxy, "PLAIN", "BACKEND", NULL);
77       //      zsock_wait (proxy);
78       //
79       //  Configure CURVE authentication for the "FRONTEND" or "BACKEND" proxy
80       //  socket -- see zsock_set_curve_server () -- specifying both the public and
81       //  secret keys of a certificate as Z85 armored strings -- see
82       //  zcert_public_txt () and zcert_secret_txt (). Call before binding socket:
83       //
84       //      zstr_sendx (proxy, "CURVE", "FRONTEND", public_txt, secret_txt, NULL);
85       //      zsock_wait (proxy);
86       //
87       //  This is the zproxy constructor as a zactor_fn; the argument is a
88       //  character string specifying frontend and backend socket types as two
89       //  uppercase strings separated by a hyphen:
90       CZMQ_EXPORT void
91           zproxy (zsock_t *pipe, void *unused);
92
93       //  Selftest
94       CZMQ_EXPORT void
95           zproxy_test (bool verbose);
96       Please add '@interface' section in './../src/zproxy.c'.
97

DESCRIPTION

99       A zproxy actor switches messages between a frontend and a backend
100       socket. It acts much like the zmq_proxy_steerable method, though it
101       makes benefit of CZMQ’s facilities, to be somewhat simpler to set-up.
102
103       This class replaces zproxy_v2, and is meant for applications that use
104       the CZMQ v3 API (meaning, zsock).
105

EXAMPLE

107       From zproxy_test method.
108
109           //  Create and configure our proxy
110           zactor_t *proxy = zactor_new (zproxy, NULL);
111           assert (proxy);
112           if (verbose) {
113               zstr_sendx (proxy, "VERBOSE", NULL);
114               zsock_wait (proxy);
115           }
116           zstr_sendx (proxy, "FRONTEND", "PULL", "inproc://frontend", NULL);
117           zsock_wait (proxy);
118           zstr_sendx (proxy, "BACKEND", "PUSH", "inproc://backend", NULL);
119           zsock_wait (proxy);
120
121           //  Connect application sockets to proxy
122           zsock_t *faucet = zsock_new_push (">inproc://frontend");
123           assert (faucet);
124           zsock_t *sink = zsock_new_pull (">inproc://backend");
125           assert (sink);
126
127           //  Send some messages and check they arrived
128           char *hello, *world;
129           zstr_sendx (faucet, "Hello", "World", NULL);
130           zstr_recvx (sink, &hello, &world, NULL);
131           assert (streq (hello, "Hello"));
132           assert (streq (world, "World"));
133           zstr_free (&hello);
134           zstr_free (&world);
135
136           //  Test pause/resume functionality
137           zstr_sendx (proxy, "PAUSE", NULL);
138           zsock_wait (proxy);
139           zstr_sendx (faucet, "Hello", "World", NULL);
140           zsock_set_rcvtimeo (sink, 100);
141           zstr_recvx (sink, &hello, &world, NULL);
142           assert (!hello && !world);
143
144           zstr_sendx (proxy, "RESUME", NULL);
145           zsock_wait (proxy);
146           zstr_recvx (sink, &hello, &world, NULL);
147           assert (streq (hello, "Hello"));
148           assert (streq (world, "World"));
149           zstr_free (&hello);
150           zstr_free (&world);
151
152           //  Test capture functionality
153           zsock_t *capture = zsock_new_pull ("inproc://capture");
154           assert (capture);
155
156           //  Switch on capturing, check that it works
157           zstr_sendx (proxy, "CAPTURE", "inproc://capture", NULL);
158           zsock_wait (proxy);
159           zstr_sendx (faucet, "Hello", "World", NULL);
160           zstr_recvx (sink, &hello, &world, NULL);
161           assert (streq (hello, "Hello"));
162           assert (streq (world, "World"));
163           zstr_free (&hello);
164           zstr_free (&world);
165
166           zstr_recvx (capture, &hello, &world, NULL);
167           assert (streq (hello, "Hello"));
168           assert (streq (world, "World"));
169           zstr_free (&hello);
170           zstr_free (&world);
171
172           zsock_destroy (&faucet);
173           zsock_destroy (&sink);
174           zsock_destroy (&capture);
175           zactor_destroy (&proxy);
176
177           //  Test socket creation dependency
178           proxy = zactor_new (zproxy, NULL);
179           assert (proxy);
180
181           #ifdef  WIN32
182                   sink = zsock_new_sub(">inproc://backend", "whatever");
183           #else
184           // vagrant vms don't like using shared storage for ipc pipes..
185           if (getenv("USER") && streq(getenv("USER"), "vagrant"))
186               sink = zsock_new_sub (">ipc:///tmp/backend", "whatever");
187           else
188                       sink = zsock_new_sub (">ipc://backend", "whatever");
189           #endif //  WIN32
190                   assert (sink);
191
192           #ifdef WIN32
193                   zstr_sendx (proxy, "BACKEND", "XPUB", "inproc://backend", NULL);
194           #else
195           // vagrant vms don't like using shared storage for ipc pipes..
196           if (getenv("USER") && streq(getenv("USER"), "vagrant"))
197               zstr_sendx(proxy, "BACKEND", "XPUB", "ipc:///tmp/backend", NULL);
198           else
199               zstr_sendx(proxy, "BACKEND", "XPUB", "ipc://backend", NULL);
200           #endif
201           zsock_wait (proxy);
202
203           zsock_destroy(&sink);
204           zactor_destroy(&proxy);
205
206           #ifdef CZMQ_BUILD_DRAFT_API
207           //  Create and configure our proxy with PUB/SUB to test subscriptions
208           proxy = zactor_new (zproxy, NULL);
209           assert (proxy);
210           if (verbose) {
211               zstr_sendx (proxy, "VERBOSE", NULL);
212               zsock_wait (proxy);
213           }
214           zstr_sendx (proxy, "FRONTEND", "SUB", "inproc://frontend", "He", "b", NULL);
215           zsock_wait (proxy);
216           zstr_sendx (proxy, "BACKEND", "PUB", "inproc://backend", NULL);
217           zsock_wait (proxy);
218
219           //  Connect application sockets to proxy
220           faucet = zsock_new_pub (">inproc://frontend");
221           assert (faucet);
222           sink = zsock_new_sub (">inproc://backend", "");
223           assert (sink);
224
225           //  Send some messages and check they arrived
226           zstr_sendx (faucet, "Hello", "World", NULL);
227           // since SUB is binding, subscription might be lost see:
228           // https://github.com/zeromq/libzmq/issues/2267
229           zsock_set_rcvtimeo (sink, 100);
230           hello = zstr_recv (sink);
231           if (hello) {
232               assert (streq (hello, "Hello"));
233               world = zstr_recv (sink);
234               assert (streq (world, "World"));
235               zstr_free (&hello);
236               zstr_free (&world);
237           }
238
239           zsock_destroy (&faucet);
240           zsock_destroy (&sink);
241           zactor_destroy(&proxy);
242           #endif // CZMQ_BUILD_DRAFT_API
243
244           #if (ZMQ_VERSION_MAJOR == 4)
245           // Test authentication functionality
246           const char *basedirpath = "src/selftest-rw/.test_zproxy";
247           const char *passfilepath = "src/selftest-rw/.test_zproxy/password-file";
248           const char *certfilepath = "src/selftest-rw/.test_zproxy/mycert.txt";
249
250           // Make sure old aborted tests do not hinder us
251           zdir_t *dir = zdir_new (basedirpath, NULL);
252           if (dir) {
253               zdir_remove (dir, true);
254               zdir_destroy (&dir);
255           }
256           zsys_file_delete (passfilepath);
257           zsys_file_delete (certfilepath);
258           zsys_dir_delete (basedirpath);
259
260           //  Create temporary directory for test files
261           zsys_dir_create (basedirpath);
262
263           char *frontend = NULL;
264           char *backend = NULL;
265
266           //  Check there's no authentication
267           s_create_test_sockets (&proxy, &faucet, &sink, verbose);
268           s_bind_test_sockets (proxy, &frontend, &backend);
269           bool success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
270               verbose, true);
271           assert (success);
272
273           //  Install the authenticator
274           zactor_t *auth = zactor_new (zauth, NULL);
275           assert (auth);
276           if (verbose) {
277               zstr_sendx (auth, "VERBOSE", NULL);
278               zsock_wait (auth);
279           }
280
281           //  Check there's no authentication on a default NULL server
282           s_bind_test_sockets (proxy, &frontend, &backend);
283           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
284               true);
285           assert (success);
286
287           //  When we set a domain on the server, we switch on authentication
288           //  for NULL sockets, but with no policies, the client connection
289           //  will be allowed.
290           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
291           zsock_wait (proxy);
292           s_bind_test_sockets (proxy, &frontend, &backend);
293           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
294               true);
295           assert (success);
296
297           //  Blacklist 127.0.0.1, connection should fail
298           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
299           zsock_wait (proxy);
300           s_bind_test_sockets (proxy, &frontend, &backend);
301           zstr_sendx (auth, "DENY", "127.0.0.1", NULL);
302           zsock_wait (auth);
303           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
304               false);
305           assert (!success);
306
307           //  Whitelist our address, which overrides the blacklist
308           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
309           zsock_wait (proxy);
310           zstr_sendx (proxy, "DOMAIN", "BACKEND", "global", NULL);
311           zsock_wait (proxy);
312           s_bind_test_sockets (proxy, &frontend, &backend);
313           zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL);
314           zsock_wait (auth);
315           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
316               true);
317           assert (success);
318
319           //  Try PLAIN authentication
320
321           //  Test negative case (no server-side passwords defined)
322           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
323           zsock_wait (proxy);
324           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
325           zsock_wait (proxy);
326           s_bind_test_sockets (proxy, &frontend, &backend);
327           zsock_set_plain_username (faucet, "admin");
328           zsock_set_plain_password (faucet, "Password");
329           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
330               false);
331           assert (!success);
332
333           //  Test positive case (server-side passwords defined)
334           FILE *password = fopen (passfilepath, "w");
335           assert (password);
336           fprintf (password, "admin=Password\n");
337           fclose (password);
338           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
339           zsock_wait (proxy);
340           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
341           zsock_wait (proxy);
342           zstr_sendx (proxy, "PLAIN", "BACKEND", NULL);
343           zsock_wait (proxy);
344           zstr_sendx (proxy, "DOMAIN", "BACKEND", "global", NULL);
345           zsock_wait (proxy);
346           s_bind_test_sockets (proxy, &frontend, &backend);
347           zsock_set_plain_username (faucet, "admin");
348           zsock_set_plain_password (faucet, "Password");
349           zsock_set_plain_username (sink, "admin");
350           zsock_set_plain_password (sink, "Password");
351           zstr_sendx (auth, "PLAIN", passfilepath, NULL);
352           zsock_wait (auth);
353           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
354               true);
355           assert (success);
356
357           //  Test negative case (bad client password)
358           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
359           zsock_wait (proxy);
360           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
361           zsock_wait (proxy);
362           s_bind_test_sockets (proxy, &frontend, &backend);
363           zsock_set_plain_username (faucet, "admin");
364           zsock_set_plain_password (faucet, "Bogus");
365           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
366               false);
367           assert (!success);
368
369           if (zsys_has_curve ()) {
370               //  We'll create two new certificates and save the client public
371               //  certificate on disk
372               zcert_t *server_cert = zcert_new ();
373               assert (server_cert);
374               zcert_t *client_cert = zcert_new ();
375               assert (client_cert);
376               const char *public_key = zcert_public_txt (server_cert);
377               const char *secret_key = zcert_secret_txt (server_cert);
378
379               //  Try CURVE authentication
380
381               //  Test without setting-up any authentication
382               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
383               zsock_wait (proxy);
384               zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
385               zsock_wait (proxy);
386               s_bind_test_sockets (proxy, &frontend, &backend);
387               zcert_apply (client_cert, faucet);
388               zsock_set_curve_serverkey (faucet, public_key);
389               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
390                   verbose, false);
391               assert (!success);
392
393               //  Test CURVE_ALLOW_ANY
394               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
395               zsock_wait (proxy);
396               s_bind_test_sockets (proxy, &frontend, &backend);
397               zcert_apply (client_cert, faucet);
398               zsock_set_curve_serverkey (faucet, public_key);
399               zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
400               zsock_wait (auth);
401               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
402                   verbose, true);
403               assert (success);
404
405               //  Test with client certificate file in authentication folder
406               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
407               zsock_wait (proxy);
408               zstr_sendx (proxy, "CURVE", "BACKEND", public_key, secret_key, NULL);
409               zsock_wait (proxy);
410               s_bind_test_sockets (proxy, &frontend, &backend);
411               zcert_apply (client_cert, faucet);
412               zsock_set_curve_serverkey (faucet, public_key);
413               zcert_apply (client_cert, sink);
414               zsock_set_curve_serverkey (sink, public_key);
415               zcert_save_public (client_cert, certfilepath);
416               zstr_sendx (auth, "CURVE", basedirpath, NULL);
417               zsock_wait (auth);
418               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
419                   verbose, true);
420               assert (success);
421
422               zcert_destroy (&server_cert);
423               zcert_destroy (&client_cert);
424           }
425
426           //  Remove the authenticator and check a normal connection works
427           zactor_destroy (&auth);
428           s_bind_test_sockets (proxy, &frontend, &backend);
429           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
430               true);
431           assert (success);
432
433           //  Cleanup
434           zsock_destroy (&faucet);
435           zsock_destroy (&sink);
436           zactor_destroy (&proxy);
437           zstr_free (&frontend);
438           zstr_free (&backend);
439
440           //  Delete temporary directory and test files
441           zsys_file_delete (passfilepath);
442           zsys_file_delete (certfilepath);
443           zsys_dir_delete (basedirpath);
444           #endif
445
446           #if defined (__WINDOWS__)
447           zsys_shutdown();
448           #endif
449
450

AUTHORS

452       The czmq manual was written by the authors in the AUTHORS file.
453

RESOURCES

455       Main web site:
456
457       Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
458
460       Copyright (c) the Contributors as noted in the AUTHORS file. This file
461       is part of CZMQ, the high-level C binding for 0MQ:
462       http://czmq.zeromq.org. This Source Code Form is subject to the terms
463       of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
464       distributed with this file, You can obtain one at
465       http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
466       distribution.
467

NOTES

469        1. zeromq-dev@lists.zeromq.org
470           mailto:zeromq-dev@lists.zeromq.org
471
472
473
474CZMQ 4.2.0                        01/28/2020                         ZPROXY(3)
Impressum