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       //  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

DESCRIPTION

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

EXAMPLE

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           #ifdef  WIN32
178                   sink = zsock_new_sub(">inproc://backend", "whatever");
179           #else
180           // vagrant vms don't like using shared storage for ipc pipes..
181           if (getenv("USER") && streq(getenv("USER"), "vagrant"))
182               sink = zsock_new_sub (">ipc:///tmp/backend", "whatever");
183           else
184                       sink = zsock_new_sub (">ipc://backend", "whatever");
185           #endif //  WIN32
186                   assert (sink);
187
188           #ifdef WIN32
189                   zstr_sendx (proxy, "BACKEND", "XPUB", "inproc://backend", NULL);
190           #else
191           // vagrant vms don't like using shared storage for ipc pipes..
192           if (getenv("USER") && streq(getenv("USER"), "vagrant"))
193               zstr_sendx(proxy, "BACKEND", "XPUB", "ipc:///tmp/backend", NULL);
194           else
195               zstr_sendx(proxy, "BACKEND", "XPUB", "ipc://backend", NULL);
196           #endif
197           zsock_wait (proxy);
198
199           zsock_destroy(&sink);
200           zactor_destroy(&proxy);
201
202           #if (ZMQ_VERSION_MAJOR == 4)
203           // Test authentication functionality
204           const char *basedirpath = "src/selftest-rw/.test_zproxy";
205           const char *passfilepath = "src/selftest-rw/.test_zproxy/password-file";
206           const char *certfilepath = "src/selftest-rw/.test_zproxy/mycert.txt";
207
208           // Make sure old aborted tests do not hinder us
209           zdir_t *dir = zdir_new (basedirpath, NULL);
210           if (dir) {
211               zdir_remove (dir, true);
212               zdir_destroy (&dir);
213           }
214           zsys_file_delete (passfilepath);
215           zsys_file_delete (certfilepath);
216           zsys_dir_delete (basedirpath);
217
218           //  Create temporary directory for test files
219           zsys_dir_create (basedirpath);
220
221           char *frontend = NULL;
222           char *backend = NULL;
223
224           //  Check there's no authentication
225           s_create_test_sockets (&proxy, &faucet, &sink, verbose);
226           s_bind_test_sockets (proxy, &frontend, &backend);
227           bool success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
228               verbose, true);
229           assert (success);
230
231           //  Install the authenticator
232           zactor_t *auth = zactor_new (zauth, NULL);
233           assert (auth);
234           if (verbose) {
235               zstr_sendx (auth, "VERBOSE", NULL);
236               zsock_wait (auth);
237           }
238
239           //  Check there's no authentication on a default NULL server
240           s_bind_test_sockets (proxy, &frontend, &backend);
241           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
242               true);
243           assert (success);
244
245           //  When we set a domain on the server, we switch on authentication
246           //  for NULL sockets, but with no policies, the client connection
247           //  will be allowed.
248           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
249           zsock_wait (proxy);
250           s_bind_test_sockets (proxy, &frontend, &backend);
251           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
252               true);
253           assert (success);
254
255           //  Blacklist 127.0.0.1, connection should fail
256           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
257           zsock_wait (proxy);
258           s_bind_test_sockets (proxy, &frontend, &backend);
259           zstr_sendx (auth, "DENY", "127.0.0.1", NULL);
260           zsock_wait (auth);
261           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
262               false);
263           assert (!success);
264
265           //  Whitelist our address, which overrides the blacklist
266           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
267           zsock_wait (proxy);
268           zstr_sendx (proxy, "DOMAIN", "BACKEND", "global", NULL);
269           zsock_wait (proxy);
270           s_bind_test_sockets (proxy, &frontend, &backend);
271           zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL);
272           zsock_wait (auth);
273           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
274               true);
275           assert (success);
276
277           //  Try PLAIN authentication
278
279           //  Test negative case (no server-side passwords defined)
280           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
281           zsock_wait (proxy);
282           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
283           zsock_wait (proxy);
284           s_bind_test_sockets (proxy, &frontend, &backend);
285           zsock_set_plain_username (faucet, "admin");
286           zsock_set_plain_password (faucet, "Password");
287           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
288               false);
289           assert (!success);
290
291           //  Test positive case (server-side passwords defined)
292           FILE *password = fopen (passfilepath, "w");
293           assert (password);
294           fprintf (password, "admin=Password\n");
295           fclose (password);
296           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
297           zsock_wait (proxy);
298           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
299           zsock_wait (proxy);
300           zstr_sendx (proxy, "PLAIN", "BACKEND", NULL);
301           zsock_wait (proxy);
302           zstr_sendx (proxy, "DOMAIN", "BACKEND", "global", NULL);
303           zsock_wait (proxy);
304           s_bind_test_sockets (proxy, &frontend, &backend);
305           zsock_set_plain_username (faucet, "admin");
306           zsock_set_plain_password (faucet, "Password");
307           zsock_set_plain_username (sink, "admin");
308           zsock_set_plain_password (sink, "Password");
309           zstr_sendx (auth, "PLAIN", passfilepath, NULL);
310           zsock_wait (auth);
311           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
312               true);
313           assert (success);
314
315           //  Test negative case (bad client password)
316           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
317           zsock_wait (proxy);
318           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
319           zsock_wait (proxy);
320           s_bind_test_sockets (proxy, &frontend, &backend);
321           zsock_set_plain_username (faucet, "admin");
322           zsock_set_plain_password (faucet, "Bogus");
323           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
324               false);
325           assert (!success);
326
327           if (zsys_has_curve ()) {
328               //  We'll create two new certificates and save the client public
329               //  certificate on disk
330               zcert_t *server_cert = zcert_new ();
331               assert (server_cert);
332               zcert_t *client_cert = zcert_new ();
333               assert (client_cert);
334               const char *public_key = zcert_public_txt (server_cert);
335               const char *secret_key = zcert_secret_txt (server_cert);
336
337               //  Try CURVE authentication
338
339               //  Test without setting-up any authentication
340               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
341               zsock_wait (proxy);
342               zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
343               zsock_wait (proxy);
344               s_bind_test_sockets (proxy, &frontend, &backend);
345               zcert_apply (client_cert, faucet);
346               zsock_set_curve_serverkey (faucet, public_key);
347               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
348                   verbose, false);
349               assert (!success);
350
351               //  Test CURVE_ALLOW_ANY
352               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
353               zsock_wait (proxy);
354               s_bind_test_sockets (proxy, &frontend, &backend);
355               zcert_apply (client_cert, faucet);
356               zsock_set_curve_serverkey (faucet, public_key);
357               zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
358               zsock_wait (auth);
359               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
360                   verbose, true);
361               assert (success);
362
363               //  Test with client certificate file in authentication folder
364               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
365               zsock_wait (proxy);
366               zstr_sendx (proxy, "CURVE", "BACKEND", public_key, secret_key, NULL);
367               zsock_wait (proxy);
368               s_bind_test_sockets (proxy, &frontend, &backend);
369               zcert_apply (client_cert, faucet);
370               zsock_set_curve_serverkey (faucet, public_key);
371               zcert_apply (client_cert, sink);
372               zsock_set_curve_serverkey (sink, public_key);
373               zcert_save_public (client_cert, certfilepath);
374               zstr_sendx (auth, "CURVE", basedirpath, NULL);
375               zsock_wait (auth);
376               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
377                   verbose, true);
378               assert (success);
379
380               zcert_destroy (&server_cert);
381               zcert_destroy (&client_cert);
382           }
383
384           //  Remove the authenticator and check a normal connection works
385           zactor_destroy (&auth);
386           s_bind_test_sockets (proxy, &frontend, &backend);
387           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
388               true);
389           assert (success);
390
391           //  Cleanup
392           zsock_destroy (&faucet);
393           zsock_destroy (&sink);
394           zactor_destroy (&proxy);
395           zstr_free (&frontend);
396           zstr_free (&backend);
397
398           //  Delete temporary directory and test files
399           zsys_file_delete (passfilepath);
400           zsys_file_delete (certfilepath);
401           zsys_dir_delete (basedirpath);
402           #endif
403
404           #if defined (__WINDOWS__)
405           zsys_shutdown();
406           #endif
407
408

AUTHORS

410       The czmq manual was written by the authors in the AUTHORS file.
411

RESOURCES

413       Main web site:
414
415       Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
416
418       Copyright (c) the Contributors as noted in the AUTHORS file. This file
419       is part of CZMQ, the high-level C binding for 0MQ:
420       http://czmq.zeromq.org. This Source Code Form is subject to the terms
421       of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
422       distributed with this file, You can obtain one at
423       http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
424       distribution.
425

NOTES

427        1. zeromq-dev@lists.zeromq.org
428           mailto:zeromq-dev@lists.zeromq.org
429
430
431
432CZMQ 4.1.1                        01/31/2019                         ZPROXY(3)
Impressum