1 
2 /*
3  * Copyright (C) Roman Arutyunyan
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_stream.h>
11 
12 
13 typedef struct {
14     ngx_addr_t                      *addr;
15     ngx_stream_complex_value_t      *value;
16 #if (NGX_HAVE_TRANSPARENT_PROXY)
17     ngx_uint_t                       transparent; /* unsigned  transparent:1; */
18 #endif
19 } ngx_stream_upstream_local_t;
20 
21 
22 typedef struct {
23     ngx_msec_t                       connect_timeout;
24     ngx_msec_t                       timeout;
25     ngx_msec_t                       next_upstream_timeout;
26     size_t                           buffer_size;
27     size_t                           upload_rate;
28     size_t                           download_rate;
29     ngx_uint_t                       requests;
30     ngx_uint_t                       responses;
31     ngx_uint_t                       next_upstream_tries;
32     ngx_flag_t                       next_upstream;
33     ngx_flag_t                       proxy_protocol;
34     ngx_stream_upstream_local_t     *local;
35     ngx_flag_t                       socket_keepalive;
36 
37 #if (NGX_STREAM_SSL)
38     ngx_flag_t                       ssl_enable;
39     ngx_flag_t                       ssl_session_reuse;
40     ngx_uint_t                       ssl_protocols;
41     ngx_str_t                        ssl_ciphers;
42     ngx_stream_complex_value_t      *ssl_name;
43     ngx_flag_t                       ssl_server_name;
44 
45     ngx_flag_t                       ssl_verify;
46     ngx_uint_t                       ssl_verify_depth;
47     ngx_str_t                        ssl_trusted_certificate;
48     ngx_str_t                        ssl_crl;
49     ngx_str_t                        ssl_certificate;
50     ngx_str_t                        ssl_certificate_key;
51     ngx_array_t                     *ssl_passwords;
52 
53     ngx_ssl_t                       *ssl;
54 #endif
55 
56 #if (NGX_HAVE_FSTACK)
57     ngx_flag_t                       kernel_network_stack;
58 #endif
59 
60     ngx_stream_upstream_srv_conf_t  *upstream;
61     ngx_stream_complex_value_t      *upstream_value;
62 } ngx_stream_proxy_srv_conf_t;
63 
64 
65 static void ngx_stream_proxy_handler(ngx_stream_session_t *s);
66 static ngx_int_t ngx_stream_proxy_eval(ngx_stream_session_t *s,
67     ngx_stream_proxy_srv_conf_t *pscf);
68 static ngx_int_t ngx_stream_proxy_set_local(ngx_stream_session_t *s,
69     ngx_stream_upstream_t *u, ngx_stream_upstream_local_t *local);
70 static void ngx_stream_proxy_connect(ngx_stream_session_t *s);
71 static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s);
72 static void ngx_stream_proxy_resolve_handler(ngx_resolver_ctx_t *ctx);
73 static void ngx_stream_proxy_upstream_handler(ngx_event_t *ev);
74 static void ngx_stream_proxy_downstream_handler(ngx_event_t *ev);
75 static void ngx_stream_proxy_process_connection(ngx_event_t *ev,
76     ngx_uint_t from_upstream);
77 static void ngx_stream_proxy_connect_handler(ngx_event_t *ev);
78 static ngx_int_t ngx_stream_proxy_test_connect(ngx_connection_t *c);
79 static void ngx_stream_proxy_process(ngx_stream_session_t *s,
80     ngx_uint_t from_upstream, ngx_uint_t do_write);
81 static ngx_int_t ngx_stream_proxy_test_finalize(ngx_stream_session_t *s,
82     ngx_uint_t from_upstream);
83 static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s);
84 static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc);
85 static u_char *ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf,
86     size_t len);
87 
88 static void *ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf);
89 static char *ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent,
90     void *child);
91 static char *ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
92     void *conf);
93 static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd,
94     void *conf);
95 
96 #if (NGX_STREAM_SSL)
97 
98 static ngx_int_t ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s);
99 static char *ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf,
100     ngx_command_t *cmd, void *conf);
101 static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s);
102 static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc);
103 static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c);
104 static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s);
105 static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf,
106     ngx_stream_proxy_srv_conf_t *pscf);
107 
108 
109 static ngx_conf_bitmask_t  ngx_stream_proxy_ssl_protocols[] = {
110     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
111     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
112     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
113     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
114     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
115     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
116     { ngx_null_string, 0 }
117 };
118 
119 #endif
120 
121 
122 static ngx_conf_deprecated_t  ngx_conf_deprecated_proxy_downstream_buffer = {
123     ngx_conf_deprecated, "proxy_downstream_buffer", "proxy_buffer_size"
124 };
125 
126 static ngx_conf_deprecated_t  ngx_conf_deprecated_proxy_upstream_buffer = {
127     ngx_conf_deprecated, "proxy_upstream_buffer", "proxy_buffer_size"
128 };
129 
130 
131 static ngx_command_t  ngx_stream_proxy_commands[] = {
132 
133     { ngx_string("proxy_pass"),
134       NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
135       ngx_stream_proxy_pass,
136       NGX_STREAM_SRV_CONF_OFFSET,
137       0,
138       NULL },
139 
140     { ngx_string("proxy_bind"),
141       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE12,
142       ngx_stream_proxy_bind,
143       NGX_STREAM_SRV_CONF_OFFSET,
144       0,
145       NULL },
146 
147     { ngx_string("proxy_socket_keepalive"),
148       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
149       ngx_conf_set_flag_slot,
150       NGX_STREAM_SRV_CONF_OFFSET,
151       offsetof(ngx_stream_proxy_srv_conf_t, socket_keepalive),
152       NULL },
153 
154     { ngx_string("proxy_connect_timeout"),
155       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
156       ngx_conf_set_msec_slot,
157       NGX_STREAM_SRV_CONF_OFFSET,
158       offsetof(ngx_stream_proxy_srv_conf_t, connect_timeout),
159       NULL },
160 
161     { ngx_string("proxy_timeout"),
162       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
163       ngx_conf_set_msec_slot,
164       NGX_STREAM_SRV_CONF_OFFSET,
165       offsetof(ngx_stream_proxy_srv_conf_t, timeout),
166       NULL },
167 
168     { ngx_string("proxy_buffer_size"),
169       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
170       ngx_conf_set_size_slot,
171       NGX_STREAM_SRV_CONF_OFFSET,
172       offsetof(ngx_stream_proxy_srv_conf_t, buffer_size),
173       NULL },
174 
175     { ngx_string("proxy_downstream_buffer"),
176       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
177       ngx_conf_set_size_slot,
178       NGX_STREAM_SRV_CONF_OFFSET,
179       offsetof(ngx_stream_proxy_srv_conf_t, buffer_size),
180       &ngx_conf_deprecated_proxy_downstream_buffer },
181 
182     { ngx_string("proxy_upstream_buffer"),
183       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
184       ngx_conf_set_size_slot,
185       NGX_STREAM_SRV_CONF_OFFSET,
186       offsetof(ngx_stream_proxy_srv_conf_t, buffer_size),
187       &ngx_conf_deprecated_proxy_upstream_buffer },
188 
189     { ngx_string("proxy_upload_rate"),
190       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
191       ngx_conf_set_size_slot,
192       NGX_STREAM_SRV_CONF_OFFSET,
193       offsetof(ngx_stream_proxy_srv_conf_t, upload_rate),
194       NULL },
195 
196     { ngx_string("proxy_download_rate"),
197       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
198       ngx_conf_set_size_slot,
199       NGX_STREAM_SRV_CONF_OFFSET,
200       offsetof(ngx_stream_proxy_srv_conf_t, download_rate),
201       NULL },
202 
203     { ngx_string("proxy_requests"),
204       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
205       ngx_conf_set_num_slot,
206       NGX_STREAM_SRV_CONF_OFFSET,
207       offsetof(ngx_stream_proxy_srv_conf_t, requests),
208       NULL },
209 
210     { ngx_string("proxy_responses"),
211       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
212       ngx_conf_set_num_slot,
213       NGX_STREAM_SRV_CONF_OFFSET,
214       offsetof(ngx_stream_proxy_srv_conf_t, responses),
215       NULL },
216 
217     { ngx_string("proxy_next_upstream"),
218       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
219       ngx_conf_set_flag_slot,
220       NGX_STREAM_SRV_CONF_OFFSET,
221       offsetof(ngx_stream_proxy_srv_conf_t, next_upstream),
222       NULL },
223 
224     { ngx_string("proxy_next_upstream_tries"),
225       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
226       ngx_conf_set_num_slot,
227       NGX_STREAM_SRV_CONF_OFFSET,
228       offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_tries),
229       NULL },
230 
231     { ngx_string("proxy_next_upstream_timeout"),
232       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
233       ngx_conf_set_msec_slot,
234       NGX_STREAM_SRV_CONF_OFFSET,
235       offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_timeout),
236       NULL },
237 
238     { ngx_string("proxy_protocol"),
239       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
240       ngx_conf_set_flag_slot,
241       NGX_STREAM_SRV_CONF_OFFSET,
242       offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol),
243       NULL },
244 
245 #if (NGX_STREAM_SSL)
246 
247     { ngx_string("proxy_ssl"),
248       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
249       ngx_conf_set_flag_slot,
250       NGX_STREAM_SRV_CONF_OFFSET,
251       offsetof(ngx_stream_proxy_srv_conf_t, ssl_enable),
252       NULL },
253 
254     { ngx_string("proxy_ssl_session_reuse"),
255       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
256       ngx_conf_set_flag_slot,
257       NGX_STREAM_SRV_CONF_OFFSET,
258       offsetof(ngx_stream_proxy_srv_conf_t, ssl_session_reuse),
259       NULL },
260 
261     { ngx_string("proxy_ssl_protocols"),
262       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
263       ngx_conf_set_bitmask_slot,
264       NGX_STREAM_SRV_CONF_OFFSET,
265       offsetof(ngx_stream_proxy_srv_conf_t, ssl_protocols),
266       &ngx_stream_proxy_ssl_protocols },
267 
268     { ngx_string("proxy_ssl_ciphers"),
269       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
270       ngx_conf_set_str_slot,
271       NGX_STREAM_SRV_CONF_OFFSET,
272       offsetof(ngx_stream_proxy_srv_conf_t, ssl_ciphers),
273       NULL },
274 
275     { ngx_string("proxy_ssl_name"),
276       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
277       ngx_stream_set_complex_value_slot,
278       NGX_STREAM_SRV_CONF_OFFSET,
279       offsetof(ngx_stream_proxy_srv_conf_t, ssl_name),
280       NULL },
281 
282     { ngx_string("proxy_ssl_server_name"),
283       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
284       ngx_conf_set_flag_slot,
285       NGX_STREAM_SRV_CONF_OFFSET,
286       offsetof(ngx_stream_proxy_srv_conf_t, ssl_server_name),
287       NULL },
288 
289     { ngx_string("proxy_ssl_verify"),
290       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
291       ngx_conf_set_flag_slot,
292       NGX_STREAM_SRV_CONF_OFFSET,
293       offsetof(ngx_stream_proxy_srv_conf_t, ssl_verify),
294       NULL },
295 
296     { ngx_string("proxy_ssl_verify_depth"),
297       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
298       ngx_conf_set_num_slot,
299       NGX_STREAM_SRV_CONF_OFFSET,
300       offsetof(ngx_stream_proxy_srv_conf_t, ssl_verify_depth),
301       NULL },
302 
303     { ngx_string("proxy_ssl_trusted_certificate"),
304       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
305       ngx_conf_set_str_slot,
306       NGX_STREAM_SRV_CONF_OFFSET,
307       offsetof(ngx_stream_proxy_srv_conf_t, ssl_trusted_certificate),
308       NULL },
309 
310     { ngx_string("proxy_ssl_crl"),
311       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
312       ngx_conf_set_str_slot,
313       NGX_STREAM_SRV_CONF_OFFSET,
314       offsetof(ngx_stream_proxy_srv_conf_t, ssl_crl),
315       NULL },
316 
317     { ngx_string("proxy_ssl_certificate"),
318       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
319       ngx_conf_set_str_slot,
320       NGX_STREAM_SRV_CONF_OFFSET,
321       offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate),
322       NULL },
323 
324     { ngx_string("proxy_ssl_certificate_key"),
325       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
326       ngx_conf_set_str_slot,
327       NGX_STREAM_SRV_CONF_OFFSET,
328       offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_key),
329       NULL },
330 
331     { ngx_string("proxy_ssl_password_file"),
332       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
333       ngx_stream_proxy_ssl_password_file,
334       NGX_STREAM_SRV_CONF_OFFSET,
335       0,
336       NULL },
337 
338 #endif
339 
340 #if (NGX_HAVE_FSTACK)
341     { ngx_string("proxy_kernel_network_stack"),
342       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
343       ngx_conf_set_flag_slot,
344       NGX_STREAM_SRV_CONF_OFFSET,
345       offsetof(ngx_stream_proxy_srv_conf_t, kernel_network_stack),
346       NULL },
347 #endif
348 
349       ngx_null_command
350 };
351 
352 
353 static ngx_stream_module_t  ngx_stream_proxy_module_ctx = {
354     NULL,                                  /* preconfiguration */
355     NULL,                                  /* postconfiguration */
356 
357     NULL,                                  /* create main configuration */
358     NULL,                                  /* init main configuration */
359 
360     ngx_stream_proxy_create_srv_conf,      /* create server configuration */
361     ngx_stream_proxy_merge_srv_conf        /* merge server configuration */
362 };
363 
364 
365 ngx_module_t  ngx_stream_proxy_module = {
366     NGX_MODULE_V1,
367     &ngx_stream_proxy_module_ctx,          /* module context */
368     ngx_stream_proxy_commands,             /* module directives */
369     NGX_STREAM_MODULE,                     /* module type */
370     NULL,                                  /* init master */
371     NULL,                                  /* init module */
372     NULL,                                  /* init process */
373     NULL,                                  /* init thread */
374     NULL,                                  /* exit thread */
375     NULL,                                  /* exit process */
376     NULL,                                  /* exit master */
377     NGX_MODULE_V1_PADDING
378 };
379 
380 
381 static void
ngx_stream_proxy_handler(ngx_stream_session_t * s)382 ngx_stream_proxy_handler(ngx_stream_session_t *s)
383 {
384     u_char                           *p;
385     ngx_str_t                        *host;
386     ngx_uint_t                        i;
387     ngx_connection_t                 *c;
388     ngx_resolver_ctx_t               *ctx, temp;
389     ngx_stream_upstream_t            *u;
390     ngx_stream_core_srv_conf_t       *cscf;
391     ngx_stream_proxy_srv_conf_t      *pscf;
392     ngx_stream_upstream_srv_conf_t   *uscf, **uscfp;
393     ngx_stream_upstream_main_conf_t  *umcf;
394 
395     c = s->connection;
396 
397     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
398 
399     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
400                    "proxy connection handler");
401 
402     u = ngx_pcalloc(c->pool, sizeof(ngx_stream_upstream_t));
403     if (u == NULL) {
404         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
405         return;
406     }
407 
408     s->upstream = u;
409 
410     s->log_handler = ngx_stream_proxy_log_error;
411 
412     u->requests = 1;
413 
414     u->peer.log = c->log;
415     u->peer.log_error = NGX_ERROR_ERR;
416 
417     if (ngx_stream_proxy_set_local(s, u, pscf->local) != NGX_OK) {
418         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
419         return;
420     }
421 
422     if (pscf->socket_keepalive) {
423         u->peer.so_keepalive = 1;
424     }
425 
426     u->peer.type = c->type;
427     u->start_sec = ngx_time();
428 
429 #if (NGX_HAVE_FSTACK)
430     u->peer.belong_to_host = pscf->kernel_network_stack;
431 #endif
432 
433     c->write->handler = ngx_stream_proxy_downstream_handler;
434     c->read->handler = ngx_stream_proxy_downstream_handler;
435 
436     s->upstream_states = ngx_array_create(c->pool, 1,
437                                           sizeof(ngx_stream_upstream_state_t));
438     if (s->upstream_states == NULL) {
439         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
440         return;
441     }
442 
443     p = ngx_pnalloc(c->pool, pscf->buffer_size);
444     if (p == NULL) {
445         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
446         return;
447     }
448 
449     u->downstream_buf.start = p;
450     u->downstream_buf.end = p + pscf->buffer_size;
451     u->downstream_buf.pos = p;
452     u->downstream_buf.last = p;
453 
454     if (c->read->ready) {
455         ngx_post_event(c->read, &ngx_posted_events);
456     }
457 
458     if (pscf->upstream_value) {
459         if (ngx_stream_proxy_eval(s, pscf) != NGX_OK) {
460             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
461             return;
462         }
463     }
464 
465     if (u->resolved == NULL) {
466 
467         uscf = pscf->upstream;
468 
469     } else {
470 
471 #if (NGX_STREAM_SSL)
472         u->ssl_name = u->resolved->host;
473 #endif
474 
475         host = &u->resolved->host;
476 
477         umcf = ngx_stream_get_module_main_conf(s, ngx_stream_upstream_module);
478 
479         uscfp = umcf->upstreams.elts;
480 
481         for (i = 0; i < umcf->upstreams.nelts; i++) {
482 
483             uscf = uscfp[i];
484 
485             if (uscf->host.len == host->len
486                 && ((uscf->port == 0 && u->resolved->no_port)
487                      || uscf->port == u->resolved->port)
488                 && ngx_strncasecmp(uscf->host.data, host->data, host->len) == 0)
489             {
490                 goto found;
491             }
492         }
493 
494         if (u->resolved->sockaddr) {
495 
496             if (u->resolved->port == 0
497                 && u->resolved->sockaddr->sa_family != AF_UNIX)
498             {
499                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
500                               "no port in upstream \"%V\"", host);
501                 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
502                 return;
503             }
504 
505             if (ngx_stream_upstream_create_round_robin_peer(s, u->resolved)
506                 != NGX_OK)
507             {
508                 ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
509                 return;
510             }
511 
512             ngx_stream_proxy_connect(s);
513 
514             return;
515         }
516 
517         if (u->resolved->port == 0) {
518             ngx_log_error(NGX_LOG_ERR, c->log, 0,
519                           "no port in upstream \"%V\"", host);
520             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
521             return;
522         }
523 
524         temp.name = *host;
525 
526         cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
527 
528         ctx = ngx_resolve_start(cscf->resolver, &temp);
529         if (ctx == NULL) {
530             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
531             return;
532         }
533 
534         if (ctx == NGX_NO_RESOLVER) {
535             ngx_log_error(NGX_LOG_ERR, c->log, 0,
536                           "no resolver defined to resolve %V", host);
537             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
538             return;
539         }
540 
541         ctx->name = *host;
542         ctx->handler = ngx_stream_proxy_resolve_handler;
543         ctx->data = s;
544         ctx->timeout = cscf->resolver_timeout;
545 
546         u->resolved->ctx = ctx;
547 
548         if (ngx_resolve_name(ctx) != NGX_OK) {
549             u->resolved->ctx = NULL;
550             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
551             return;
552         }
553 
554         return;
555     }
556 
557 found:
558 
559     if (uscf == NULL) {
560         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "no upstream configuration");
561         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
562         return;
563     }
564 
565     u->upstream = uscf;
566 
567 #if (NGX_STREAM_SSL)
568     u->ssl_name = uscf->host;
569 #endif
570 
571     if (uscf->peer.init(s, uscf) != NGX_OK) {
572         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
573         return;
574     }
575 
576     u->peer.start_time = ngx_current_msec;
577 
578     if (pscf->next_upstream_tries
579         && u->peer.tries > pscf->next_upstream_tries)
580     {
581         u->peer.tries = pscf->next_upstream_tries;
582     }
583 
584     ngx_stream_proxy_connect(s);
585 }
586 
587 
588 static ngx_int_t
ngx_stream_proxy_eval(ngx_stream_session_t * s,ngx_stream_proxy_srv_conf_t * pscf)589 ngx_stream_proxy_eval(ngx_stream_session_t *s,
590     ngx_stream_proxy_srv_conf_t *pscf)
591 {
592     ngx_str_t               host;
593     ngx_url_t               url;
594     ngx_stream_upstream_t  *u;
595 
596     if (ngx_stream_complex_value(s, pscf->upstream_value, &host) != NGX_OK) {
597         return NGX_ERROR;
598     }
599 
600     ngx_memzero(&url, sizeof(ngx_url_t));
601 
602     url.url = host;
603     url.no_resolve = 1;
604 
605     if (ngx_parse_url(s->connection->pool, &url) != NGX_OK) {
606         if (url.err) {
607             ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
608                           "%s in upstream \"%V\"", url.err, &url.url);
609         }
610 
611         return NGX_ERROR;
612     }
613 
614     u = s->upstream;
615 
616     u->resolved = ngx_pcalloc(s->connection->pool,
617                               sizeof(ngx_stream_upstream_resolved_t));
618     if (u->resolved == NULL) {
619         return NGX_ERROR;
620     }
621 
622     if (url.addrs) {
623         u->resolved->sockaddr = url.addrs[0].sockaddr;
624         u->resolved->socklen = url.addrs[0].socklen;
625         u->resolved->name = url.addrs[0].name;
626         u->resolved->naddrs = 1;
627     }
628 
629     u->resolved->host = url.host;
630     u->resolved->port = url.port;
631     u->resolved->no_port = url.no_port;
632 
633     return NGX_OK;
634 }
635 
636 
637 static ngx_int_t
ngx_stream_proxy_set_local(ngx_stream_session_t * s,ngx_stream_upstream_t * u,ngx_stream_upstream_local_t * local)638 ngx_stream_proxy_set_local(ngx_stream_session_t *s, ngx_stream_upstream_t *u,
639     ngx_stream_upstream_local_t *local)
640 {
641     ngx_int_t    rc;
642     ngx_str_t    val;
643     ngx_addr_t  *addr;
644 
645     if (local == NULL) {
646         u->peer.local = NULL;
647         return NGX_OK;
648     }
649 
650 #if (NGX_HAVE_TRANSPARENT_PROXY)
651     u->peer.transparent = local->transparent;
652 #endif
653 
654     if (local->value == NULL) {
655         u->peer.local = local->addr;
656         return NGX_OK;
657     }
658 
659     if (ngx_stream_complex_value(s, local->value, &val) != NGX_OK) {
660         return NGX_ERROR;
661     }
662 
663     if (val.len == 0) {
664         return NGX_OK;
665     }
666 
667     addr = ngx_palloc(s->connection->pool, sizeof(ngx_addr_t));
668     if (addr == NULL) {
669         return NGX_ERROR;
670     }
671 
672     rc = ngx_parse_addr_port(s->connection->pool, addr, val.data, val.len);
673     if (rc == NGX_ERROR) {
674         return NGX_ERROR;
675     }
676 
677     if (rc != NGX_OK) {
678         ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
679                       "invalid local address \"%V\"", &val);
680         return NGX_OK;
681     }
682 
683     addr->name = val;
684     u->peer.local = addr;
685 
686     return NGX_OK;
687 }
688 
689 
690 static void
ngx_stream_proxy_connect(ngx_stream_session_t * s)691 ngx_stream_proxy_connect(ngx_stream_session_t *s)
692 {
693     ngx_int_t                     rc;
694     ngx_connection_t             *c, *pc;
695     ngx_stream_upstream_t        *u;
696     ngx_stream_proxy_srv_conf_t  *pscf;
697 
698     c = s->connection;
699 
700     c->log->action = "connecting to upstream";
701 
702     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
703 
704     u = s->upstream;
705 
706     u->connected = 0;
707     u->proxy_protocol = pscf->proxy_protocol;
708 
709     if (u->state) {
710         u->state->response_time = ngx_current_msec - u->start_time;
711     }
712 
713     u->state = ngx_array_push(s->upstream_states);
714     if (u->state == NULL) {
715         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
716         return;
717     }
718 
719     ngx_memzero(u->state, sizeof(ngx_stream_upstream_state_t));
720 
721     u->start_time = ngx_current_msec;
722 
723     u->state->connect_time = (ngx_msec_t) -1;
724     u->state->first_byte_time = (ngx_msec_t) -1;
725     u->state->response_time = (ngx_msec_t) -1;
726 
727     rc = ngx_event_connect_peer(&u->peer);
728 
729     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc);
730 
731     if (rc == NGX_ERROR) {
732         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
733         return;
734     }
735 
736     u->state->peer = u->peer.name;
737 
738     if (rc == NGX_BUSY) {
739         ngx_log_error(NGX_LOG_ERR, c->log, 0, "no live upstreams");
740         ngx_stream_proxy_finalize(s, NGX_STREAM_BAD_GATEWAY);
741         return;
742     }
743 
744     if (rc == NGX_DECLINED) {
745         ngx_stream_proxy_next_upstream(s);
746         return;
747     }
748 
749     /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */
750 
751     pc = u->peer.connection;
752 
753     pc->data = s;
754     pc->log = c->log;
755     pc->pool = c->pool;
756     pc->read->log = c->log;
757     pc->write->log = c->log;
758 
759     if (rc != NGX_AGAIN) {
760         ngx_stream_proxy_init_upstream(s);
761         return;
762     }
763 
764     pc->read->handler = ngx_stream_proxy_connect_handler;
765     pc->write->handler = ngx_stream_proxy_connect_handler;
766 
767     ngx_add_timer(pc->write, pscf->connect_timeout);
768 }
769 
770 
771 static void
ngx_stream_proxy_init_upstream(ngx_stream_session_t * s)772 ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
773 {
774     u_char                       *p;
775     ngx_chain_t                  *cl;
776     ngx_connection_t             *c, *pc;
777     ngx_log_handler_pt            handler;
778     ngx_stream_upstream_t        *u;
779     ngx_stream_core_srv_conf_t   *cscf;
780     ngx_stream_proxy_srv_conf_t  *pscf;
781 
782     u = s->upstream;
783     pc = u->peer.connection;
784 
785     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
786 
787     if (pc->type == SOCK_STREAM
788         && cscf->tcp_nodelay
789         && ngx_tcp_nodelay(pc) != NGX_OK)
790     {
791         ngx_stream_proxy_next_upstream(s);
792         return;
793     }
794 
795     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
796 
797 #if (NGX_STREAM_SSL)
798 
799     if (pc->type == SOCK_STREAM && pscf->ssl) {
800 
801         if (u->proxy_protocol) {
802             if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) {
803                 return;
804             }
805 
806             u->proxy_protocol = 0;
807         }
808 
809         if (pc->ssl == NULL) {
810             ngx_stream_proxy_ssl_init_connection(s);
811             return;
812         }
813     }
814 
815 #endif
816 
817     c = s->connection;
818 
819     if (c->log->log_level >= NGX_LOG_INFO) {
820         ngx_str_t  str;
821         u_char     addr[NGX_SOCKADDR_STRLEN];
822 
823         str.len = NGX_SOCKADDR_STRLEN;
824         str.data = addr;
825 
826         if (ngx_connection_local_sockaddr(pc, &str, 1) == NGX_OK) {
827             handler = c->log->handler;
828             c->log->handler = NULL;
829 
830             ngx_log_error(NGX_LOG_INFO, c->log, 0,
831                           "%sproxy %V connected to %V",
832                           pc->type == SOCK_DGRAM ? "udp " : "",
833                           &str, u->peer.name);
834 
835             c->log->handler = handler;
836         }
837     }
838 
839     u->state->connect_time = ngx_current_msec - u->start_time;
840 
841     if (u->peer.notify) {
842         u->peer.notify(&u->peer, u->peer.data,
843                        NGX_STREAM_UPSTREAM_NOTIFY_CONNECT);
844     }
845 
846     if (u->upstream_buf.start == NULL) {
847         p = ngx_pnalloc(c->pool, pscf->buffer_size);
848         if (p == NULL) {
849             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
850             return;
851         }
852 
853         u->upstream_buf.start = p;
854         u->upstream_buf.end = p + pscf->buffer_size;
855         u->upstream_buf.pos = p;
856         u->upstream_buf.last = p;
857     }
858 
859     if (c->buffer && c->buffer->pos < c->buffer->last) {
860         ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
861                        "stream proxy add preread buffer: %uz",
862                        c->buffer->last - c->buffer->pos);
863 
864         cl = ngx_chain_get_free_buf(c->pool, &u->free);
865         if (cl == NULL) {
866             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
867             return;
868         }
869 
870         *cl->buf = *c->buffer;
871 
872         cl->buf->tag = (ngx_buf_tag_t) &ngx_stream_proxy_module;
873         cl->buf->flush = 1;
874 
875         cl->next = u->upstream_out;
876         u->upstream_out = cl;
877     }
878 
879     if (u->proxy_protocol) {
880         ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
881                        "stream proxy add PROXY protocol header");
882 
883         cl = ngx_chain_get_free_buf(c->pool, &u->free);
884         if (cl == NULL) {
885             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
886             return;
887         }
888 
889         p = ngx_pnalloc(c->pool, NGX_PROXY_PROTOCOL_MAX_HEADER);
890         if (p == NULL) {
891             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
892             return;
893         }
894 
895         cl->buf->pos = p;
896 
897         p = ngx_proxy_protocol_write(c, p, p + NGX_PROXY_PROTOCOL_MAX_HEADER);
898         if (p == NULL) {
899             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
900             return;
901         }
902 
903         cl->buf->last = p;
904         cl->buf->temporary = 1;
905         cl->buf->flush = 0;
906         cl->buf->last_buf = 0;
907         cl->buf->tag = (ngx_buf_tag_t) &ngx_stream_proxy_module;
908 
909         cl->next = u->upstream_out;
910         u->upstream_out = cl;
911 
912         u->proxy_protocol = 0;
913     }
914 
915     u->connected = 1;
916 
917     pc->read->handler = ngx_stream_proxy_upstream_handler;
918     pc->write->handler = ngx_stream_proxy_upstream_handler;
919 
920     if (pc->read->ready) {
921         ngx_post_event(pc->read, &ngx_posted_events);
922     }
923 
924     ngx_stream_proxy_process(s, 0, 1);
925 }
926 
927 
928 #if (NGX_STREAM_SSL)
929 
930 static ngx_int_t
ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t * s)931 ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
932 {
933     u_char                       *p;
934     ssize_t                       n, size;
935     ngx_connection_t             *c, *pc;
936     ngx_stream_upstream_t        *u;
937     ngx_stream_proxy_srv_conf_t  *pscf;
938     u_char                        buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
939 
940     c = s->connection;
941 
942     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
943                    "stream proxy send PROXY protocol header");
944 
945     p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER);
946     if (p == NULL) {
947         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
948         return NGX_ERROR;
949     }
950 
951     u = s->upstream;
952 
953     pc = u->peer.connection;
954 
955     size = p - buf;
956 
957     n = pc->send(pc, buf, size);
958 
959     if (n == NGX_AGAIN) {
960         if (ngx_handle_write_event(pc->write, 0) != NGX_OK) {
961             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
962             return NGX_ERROR;
963         }
964 
965         pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
966 
967         ngx_add_timer(pc->write, pscf->timeout);
968 
969         pc->write->handler = ngx_stream_proxy_connect_handler;
970 
971         return NGX_AGAIN;
972     }
973 
974     if (n == NGX_ERROR) {
975         ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
976         return NGX_ERROR;
977     }
978 
979     if (n != size) {
980 
981         /*
982          * PROXY protocol specification:
983          * The sender must always ensure that the header
984          * is sent at once, so that the transport layer
985          * maintains atomicity along the path to the receiver.
986          */
987 
988         ngx_log_error(NGX_LOG_ERR, c->log, 0,
989                       "could not send PROXY protocol header at once");
990 
991         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
992 
993         return NGX_ERROR;
994     }
995 
996     return NGX_OK;
997 }
998 
999 
1000 static char *
ngx_stream_proxy_ssl_password_file(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1001 ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
1002     void *conf)
1003 {
1004     ngx_stream_proxy_srv_conf_t *pscf = conf;
1005 
1006     ngx_str_t  *value;
1007 
1008     if (pscf->ssl_passwords != NGX_CONF_UNSET_PTR) {
1009         return "is duplicate";
1010     }
1011 
1012     value = cf->args->elts;
1013 
1014     pscf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
1015 
1016     if (pscf->ssl_passwords == NULL) {
1017         return NGX_CONF_ERROR;
1018     }
1019 
1020     return NGX_CONF_OK;
1021 }
1022 
1023 
1024 static void
ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t * s)1025 ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
1026 {
1027     ngx_int_t                     rc;
1028     ngx_connection_t             *pc;
1029     ngx_stream_upstream_t        *u;
1030     ngx_stream_proxy_srv_conf_t  *pscf;
1031 
1032     u = s->upstream;
1033 
1034     pc = u->peer.connection;
1035 
1036     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1037 
1038     if (ngx_ssl_create_connection(pscf->ssl, pc, NGX_SSL_BUFFER|NGX_SSL_CLIENT)
1039         != NGX_OK)
1040     {
1041         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1042         return;
1043     }
1044 
1045     if (pscf->ssl_server_name || pscf->ssl_verify) {
1046         if (ngx_stream_proxy_ssl_name(s) != NGX_OK) {
1047             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1048             return;
1049         }
1050     }
1051 
1052     if (pscf->ssl_session_reuse) {
1053         pc->ssl->save_session = ngx_stream_proxy_ssl_save_session;
1054 
1055         if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
1056             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1057             return;
1058         }
1059     }
1060 
1061     s->connection->log->action = "SSL handshaking to upstream";
1062 
1063     rc = ngx_ssl_handshake(pc);
1064 
1065     if (rc == NGX_AGAIN) {
1066 
1067         if (!pc->write->timer_set) {
1068             ngx_add_timer(pc->write, pscf->connect_timeout);
1069         }
1070 
1071         pc->ssl->handler = ngx_stream_proxy_ssl_handshake;
1072         return;
1073     }
1074 
1075     ngx_stream_proxy_ssl_handshake(pc);
1076 }
1077 
1078 
1079 static void
ngx_stream_proxy_ssl_handshake(ngx_connection_t * pc)1080 ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc)
1081 {
1082     long                          rc;
1083     ngx_stream_session_t         *s;
1084     ngx_stream_upstream_t        *u;
1085     ngx_stream_proxy_srv_conf_t  *pscf;
1086 
1087     s = pc->data;
1088 
1089     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1090 
1091     if (pc->ssl->handshaked) {
1092 
1093         if (pscf->ssl_verify) {
1094             rc = SSL_get_verify_result(pc->ssl->connection);
1095 
1096             if (rc != X509_V_OK) {
1097                 ngx_log_error(NGX_LOG_ERR, pc->log, 0,
1098                               "upstream SSL certificate verify error: (%l:%s)",
1099                               rc, X509_verify_cert_error_string(rc));
1100                 goto failed;
1101             }
1102 
1103             u = s->upstream;
1104 
1105             if (ngx_ssl_check_host(pc, &u->ssl_name) != NGX_OK) {
1106                 ngx_log_error(NGX_LOG_ERR, pc->log, 0,
1107                               "upstream SSL certificate does not match \"%V\"",
1108                               &u->ssl_name);
1109                 goto failed;
1110             }
1111         }
1112 
1113         if (pc->write->timer_set) {
1114             ngx_del_timer(pc->write);
1115         }
1116 
1117         ngx_stream_proxy_init_upstream(s);
1118 
1119         return;
1120     }
1121 
1122 failed:
1123 
1124     ngx_stream_proxy_next_upstream(s);
1125 }
1126 
1127 
1128 static void
ngx_stream_proxy_ssl_save_session(ngx_connection_t * c)1129 ngx_stream_proxy_ssl_save_session(ngx_connection_t *c)
1130 {
1131     ngx_stream_session_t   *s;
1132     ngx_stream_upstream_t  *u;
1133 
1134     s = c->data;
1135     u = s->upstream;
1136 
1137     u->peer.save_session(&u->peer, u->peer.data);
1138 }
1139 
1140 
1141 static ngx_int_t
ngx_stream_proxy_ssl_name(ngx_stream_session_t * s)1142 ngx_stream_proxy_ssl_name(ngx_stream_session_t *s)
1143 {
1144     u_char                       *p, *last;
1145     ngx_str_t                     name;
1146     ngx_stream_upstream_t        *u;
1147     ngx_stream_proxy_srv_conf_t  *pscf;
1148 
1149     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1150 
1151     u = s->upstream;
1152 
1153     if (pscf->ssl_name) {
1154         if (ngx_stream_complex_value(s, pscf->ssl_name, &name) != NGX_OK) {
1155             return NGX_ERROR;
1156         }
1157 
1158     } else {
1159         name = u->ssl_name;
1160     }
1161 
1162     if (name.len == 0) {
1163         goto done;
1164     }
1165 
1166     /*
1167      * ssl name here may contain port, strip it for compatibility
1168      * with the http module
1169      */
1170 
1171     p = name.data;
1172     last = name.data + name.len;
1173 
1174     if (*p == '[') {
1175         p = ngx_strlchr(p, last, ']');
1176 
1177         if (p == NULL) {
1178             p = name.data;
1179         }
1180     }
1181 
1182     p = ngx_strlchr(p, last, ':');
1183 
1184     if (p != NULL) {
1185         name.len = p - name.data;
1186     }
1187 
1188     if (!pscf->ssl_server_name) {
1189         goto done;
1190     }
1191 
1192 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1193 
1194     /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */
1195 
1196     if (name.len == 0 || *name.data == '[') {
1197         goto done;
1198     }
1199 
1200     if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) {
1201         goto done;
1202     }
1203 
1204     /*
1205      * SSL_set_tlsext_host_name() needs a null-terminated string,
1206      * hence we explicitly null-terminate name here
1207      */
1208 
1209     p = ngx_pnalloc(s->connection->pool, name.len + 1);
1210     if (p == NULL) {
1211         return NGX_ERROR;
1212     }
1213 
1214     (void) ngx_cpystrn(p, name.data, name.len + 1);
1215 
1216     name.data = p;
1217 
1218     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1219                    "upstream SSL server name: \"%s\"", name.data);
1220 
1221     if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection,
1222                                  (char *) name.data)
1223         == 0)
1224     {
1225         ngx_ssl_error(NGX_LOG_ERR, s->connection->log, 0,
1226                       "SSL_set_tlsext_host_name(\"%s\") failed", name.data);
1227         return NGX_ERROR;
1228     }
1229 
1230 #endif
1231 
1232 done:
1233 
1234     u->ssl_name = name;
1235 
1236     return NGX_OK;
1237 }
1238 
1239 #endif
1240 
1241 
1242 static void
ngx_stream_proxy_downstream_handler(ngx_event_t * ev)1243 ngx_stream_proxy_downstream_handler(ngx_event_t *ev)
1244 {
1245     ngx_stream_proxy_process_connection(ev, ev->write);
1246 }
1247 
1248 
1249 static void
ngx_stream_proxy_resolve_handler(ngx_resolver_ctx_t * ctx)1250 ngx_stream_proxy_resolve_handler(ngx_resolver_ctx_t *ctx)
1251 {
1252     ngx_stream_session_t            *s;
1253     ngx_stream_upstream_t           *u;
1254     ngx_stream_proxy_srv_conf_t     *pscf;
1255     ngx_stream_upstream_resolved_t  *ur;
1256 
1257     s = ctx->data;
1258 
1259     u = s->upstream;
1260     ur = u->resolved;
1261 
1262     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1263                    "stream upstream resolve");
1264 
1265     if (ctx->state) {
1266         ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
1267                       "%V could not be resolved (%i: %s)",
1268                       &ctx->name, ctx->state,
1269                       ngx_resolver_strerror(ctx->state));
1270 
1271         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1272         return;
1273     }
1274 
1275     ur->naddrs = ctx->naddrs;
1276     ur->addrs = ctx->addrs;
1277 
1278 #if (NGX_DEBUG)
1279     {
1280     u_char      text[NGX_SOCKADDR_STRLEN];
1281     ngx_str_t   addr;
1282     ngx_uint_t  i;
1283 
1284     addr.data = text;
1285 
1286     for (i = 0; i < ctx->naddrs; i++) {
1287         addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen,
1288                                  text, NGX_SOCKADDR_STRLEN, 0);
1289 
1290         ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1291                        "name was resolved to %V", &addr);
1292     }
1293     }
1294 #endif
1295 
1296     if (ngx_stream_upstream_create_round_robin_peer(s, ur) != NGX_OK) {
1297         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1298         return;
1299     }
1300 
1301     ngx_resolve_name_done(ctx);
1302     ur->ctx = NULL;
1303 
1304     u->peer.start_time = ngx_current_msec;
1305 
1306     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1307 
1308     if (pscf->next_upstream_tries
1309         && u->peer.tries > pscf->next_upstream_tries)
1310     {
1311         u->peer.tries = pscf->next_upstream_tries;
1312     }
1313 
1314     ngx_stream_proxy_connect(s);
1315 }
1316 
1317 
1318 static void
ngx_stream_proxy_upstream_handler(ngx_event_t * ev)1319 ngx_stream_proxy_upstream_handler(ngx_event_t *ev)
1320 {
1321     ngx_stream_proxy_process_connection(ev, !ev->write);
1322 }
1323 
1324 
1325 static void
ngx_stream_proxy_process_connection(ngx_event_t * ev,ngx_uint_t from_upstream)1326 ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream)
1327 {
1328     ngx_connection_t             *c, *pc;
1329     ngx_log_handler_pt            handler;
1330     ngx_stream_session_t         *s;
1331     ngx_stream_upstream_t        *u;
1332     ngx_stream_proxy_srv_conf_t  *pscf;
1333 
1334     c = ev->data;
1335     s = c->data;
1336     u = s->upstream;
1337 
1338     if (c->close) {
1339         ngx_log_error(NGX_LOG_INFO, c->log, 0, "shutdown timeout");
1340         ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
1341         return;
1342     }
1343 
1344     c = s->connection;
1345     pc = u->peer.connection;
1346 
1347     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1348 
1349     if (ev->timedout) {
1350         ev->timedout = 0;
1351 
1352         if (ev->delayed) {
1353             ev->delayed = 0;
1354 
1355             if (!ev->ready) {
1356                 if (ngx_handle_read_event(ev, 0) != NGX_OK) {
1357                     ngx_stream_proxy_finalize(s,
1358                                               NGX_STREAM_INTERNAL_SERVER_ERROR);
1359                     return;
1360                 }
1361 
1362                 if (u->connected && !c->read->delayed && !pc->read->delayed) {
1363                     ngx_add_timer(c->write, pscf->timeout);
1364                 }
1365 
1366                 return;
1367             }
1368 
1369         } else {
1370             if (s->connection->type == SOCK_DGRAM) {
1371 
1372                 if (pscf->responses == NGX_MAX_INT32_VALUE
1373                     || (u->responses >= pscf->responses * u->requests))
1374                 {
1375 
1376                     /*
1377                      * successfully terminate timed out UDP session
1378                      * if expected number of responses was received
1379                      */
1380 
1381                     handler = c->log->handler;
1382                     c->log->handler = NULL;
1383 
1384                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1385                                   "udp timed out"
1386                                   ", packets from/to client:%ui/%ui"
1387                                   ", bytes from/to client:%O/%O"
1388                                   ", bytes from/to upstream:%O/%O",
1389                                   u->requests, u->responses,
1390                                   s->received, c->sent, u->received,
1391                                   pc ? pc->sent : 0);
1392 
1393                     c->log->handler = handler;
1394 
1395                     ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
1396                     return;
1397                 }
1398 
1399                 ngx_connection_error(pc, NGX_ETIMEDOUT, "upstream timed out");
1400 
1401                 pc->read->error = 1;
1402 
1403                 ngx_stream_proxy_finalize(s, NGX_STREAM_BAD_GATEWAY);
1404 
1405                 return;
1406             }
1407 
1408             ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out");
1409 
1410             ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
1411 
1412             return;
1413         }
1414 
1415     } else if (ev->delayed) {
1416 
1417         ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
1418                        "stream connection delayed");
1419 
1420         if (ngx_handle_read_event(ev, 0) != NGX_OK) {
1421             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1422         }
1423 
1424         return;
1425     }
1426 
1427     if (from_upstream && !u->connected) {
1428         return;
1429     }
1430 
1431     ngx_stream_proxy_process(s, from_upstream, ev->write);
1432 }
1433 
1434 
1435 static void
ngx_stream_proxy_connect_handler(ngx_event_t * ev)1436 ngx_stream_proxy_connect_handler(ngx_event_t *ev)
1437 {
1438     ngx_connection_t      *c;
1439     ngx_stream_session_t  *s;
1440 
1441     c = ev->data;
1442     s = c->data;
1443 
1444     if (ev->timedout) {
1445         ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "upstream timed out");
1446         ngx_stream_proxy_next_upstream(s);
1447         return;
1448     }
1449 
1450     ngx_del_timer(c->write);
1451 
1452     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
1453                    "stream proxy connect upstream");
1454 
1455     if (ngx_stream_proxy_test_connect(c) != NGX_OK) {
1456         ngx_stream_proxy_next_upstream(s);
1457         return;
1458     }
1459 
1460     ngx_stream_proxy_init_upstream(s);
1461 }
1462 
1463 
1464 static ngx_int_t
ngx_stream_proxy_test_connect(ngx_connection_t * c)1465 ngx_stream_proxy_test_connect(ngx_connection_t *c)
1466 {
1467     int        err;
1468     socklen_t  len;
1469 
1470 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK)
1471 
1472     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT)  {
1473         err = c->write->kq_errno ? c->write->kq_errno : c->read->kq_errno;
1474 
1475         if (err) {
1476             (void) ngx_connection_error(c, err,
1477                                     "kevent() reported that connect() failed");
1478             return NGX_ERROR;
1479         }
1480 
1481     } else
1482 #endif
1483     {
1484         err = 0;
1485         len = sizeof(int);
1486 
1487         /*
1488          * BSDs and Linux return 0 and set a pending error in err
1489          * Solaris returns -1 and sets errno
1490          */
1491 
1492         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
1493             == -1)
1494         {
1495             err = ngx_socket_errno;
1496         }
1497 
1498         if (err) {
1499             (void) ngx_connection_error(c, err, "connect() failed");
1500             return NGX_ERROR;
1501         }
1502     }
1503 
1504     return NGX_OK;
1505 }
1506 
1507 
1508 static void
ngx_stream_proxy_process(ngx_stream_session_t * s,ngx_uint_t from_upstream,ngx_uint_t do_write)1509 ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
1510     ngx_uint_t do_write)
1511 {
1512     char                         *recv_action, *send_action;
1513     off_t                        *received, limit;
1514     size_t                        size, limit_rate;
1515     ssize_t                       n;
1516     ngx_buf_t                    *b;
1517     ngx_int_t                     rc;
1518     ngx_uint_t                    flags, *packets;
1519     ngx_msec_t                    delay;
1520     ngx_chain_t                  *cl, **ll, **out, **busy;
1521     ngx_connection_t             *c, *pc, *src, *dst;
1522     ngx_log_handler_pt            handler;
1523     ngx_stream_upstream_t        *u;
1524     ngx_stream_proxy_srv_conf_t  *pscf;
1525 
1526     u = s->upstream;
1527 
1528     c = s->connection;
1529     pc = u->connected ? u->peer.connection : NULL;
1530 
1531     if (c->type == SOCK_DGRAM && (ngx_terminate || ngx_exiting)) {
1532 
1533         /* socket is already closed on worker shutdown */
1534 
1535         handler = c->log->handler;
1536         c->log->handler = NULL;
1537 
1538         ngx_log_error(NGX_LOG_INFO, c->log, 0, "disconnected on shutdown");
1539 
1540         c->log->handler = handler;
1541 
1542         ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
1543         return;
1544     }
1545 
1546     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1547 
1548     if (from_upstream) {
1549         src = pc;
1550         dst = c;
1551         b = &u->upstream_buf;
1552         limit_rate = pscf->download_rate;
1553         received = &u->received;
1554         packets = &u->responses;
1555         out = &u->downstream_out;
1556         busy = &u->downstream_busy;
1557         recv_action = "proxying and reading from upstream";
1558         send_action = "proxying and sending to client";
1559 
1560     } else {
1561         src = c;
1562         dst = pc;
1563         b = &u->downstream_buf;
1564         limit_rate = pscf->upload_rate;
1565         received = &s->received;
1566         packets = &u->requests;
1567         out = &u->upstream_out;
1568         busy = &u->upstream_busy;
1569         recv_action = "proxying and reading from client";
1570         send_action = "proxying and sending to upstream";
1571     }
1572 
1573     for ( ;; ) {
1574 
1575         if (do_write && dst) {
1576 
1577             if (*out || *busy || dst->buffered) {
1578                 c->log->action = send_action;
1579 
1580                 rc = ngx_stream_top_filter(s, *out, from_upstream);
1581 
1582                 if (rc == NGX_ERROR) {
1583                     ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
1584                     return;
1585                 }
1586 
1587                 ngx_chain_update_chains(c->pool, &u->free, busy, out,
1588                                       (ngx_buf_tag_t) &ngx_stream_proxy_module);
1589 
1590                 if (*busy == NULL) {
1591                     b->pos = b->start;
1592                     b->last = b->start;
1593                 }
1594             }
1595         }
1596 
1597         size = b->end - b->last;
1598 
1599         if (size && src->read->ready && !src->read->delayed
1600             && !src->read->error)
1601         {
1602             if (limit_rate) {
1603                 limit = (off_t) limit_rate * (ngx_time() - u->start_sec + 1)
1604                         - *received;
1605 
1606                 if (limit <= 0) {
1607                     src->read->delayed = 1;
1608                     delay = (ngx_msec_t) (- limit * 1000 / limit_rate + 1);
1609                     ngx_add_timer(src->read, delay);
1610                     break;
1611                 }
1612 
1613                 if (c->type == SOCK_STREAM && (off_t) size > limit) {
1614                     size = (size_t) limit;
1615                 }
1616             }
1617 
1618             c->log->action = recv_action;
1619 
1620             n = src->recv(src, b->last, size);
1621 
1622             if (n == NGX_AGAIN) {
1623                 break;
1624             }
1625 
1626             if (n == NGX_ERROR) {
1627                 src->read->eof = 1;
1628                 n = 0;
1629             }
1630 
1631             if (n >= 0) {
1632                 if (limit_rate) {
1633                     delay = (ngx_msec_t) (n * 1000 / limit_rate);
1634 
1635                     if (delay > 0) {
1636                         src->read->delayed = 1;
1637                         ngx_add_timer(src->read, delay);
1638                     }
1639                 }
1640 
1641                 if (from_upstream) {
1642                     if (u->state->first_byte_time == (ngx_msec_t) -1) {
1643                         u->state->first_byte_time = ngx_current_msec
1644                                                     - u->start_time;
1645                     }
1646                 }
1647 
1648                 for (ll = out; *ll; ll = &(*ll)->next) { /* void */ }
1649 
1650                 cl = ngx_chain_get_free_buf(c->pool, &u->free);
1651                 if (cl == NULL) {
1652                     ngx_stream_proxy_finalize(s,
1653                                               NGX_STREAM_INTERNAL_SERVER_ERROR);
1654                     return;
1655                 }
1656 
1657                 *ll = cl;
1658 
1659                 cl->buf->pos = b->last;
1660                 cl->buf->last = b->last + n;
1661                 cl->buf->tag = (ngx_buf_tag_t) &ngx_stream_proxy_module;
1662 
1663                 cl->buf->temporary = (n ? 1 : 0);
1664                 cl->buf->last_buf = src->read->eof;
1665                 cl->buf->flush = 1;
1666 
1667                 (*packets)++;
1668                 *received += n;
1669                 b->last += n;
1670                 do_write = 1;
1671 
1672                 continue;
1673             }
1674         }
1675 
1676         break;
1677     }
1678 
1679     c->log->action = "proxying connection";
1680 
1681     if (ngx_stream_proxy_test_finalize(s, from_upstream) == NGX_OK) {
1682         return;
1683     }
1684 
1685     flags = src->read->eof ? NGX_CLOSE_EVENT : 0;
1686 
1687     if (ngx_handle_read_event(src->read, flags) != NGX_OK) {
1688         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1689         return;
1690     }
1691 
1692     if (dst) {
1693         if (ngx_handle_write_event(dst->write, 0) != NGX_OK) {
1694             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1695             return;
1696         }
1697 
1698         if (!c->read->delayed && !pc->read->delayed) {
1699             ngx_add_timer(c->write, pscf->timeout);
1700 
1701         } else if (c->write->timer_set) {
1702             ngx_del_timer(c->write);
1703         }
1704     }
1705 }
1706 
1707 
1708 static ngx_int_t
ngx_stream_proxy_test_finalize(ngx_stream_session_t * s,ngx_uint_t from_upstream)1709 ngx_stream_proxy_test_finalize(ngx_stream_session_t *s,
1710     ngx_uint_t from_upstream)
1711 {
1712     ngx_connection_t             *c, *pc;
1713     ngx_log_handler_pt            handler;
1714     ngx_stream_upstream_t        *u;
1715     ngx_stream_proxy_srv_conf_t  *pscf;
1716 
1717     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1718 
1719     c = s->connection;
1720     u = s->upstream;
1721     pc = u->connected ? u->peer.connection : NULL;
1722 
1723     if (c->type == SOCK_DGRAM) {
1724 
1725         if (pscf->requests && u->requests < pscf->requests) {
1726             return NGX_DECLINED;
1727         }
1728 
1729         if (pscf->requests) {
1730             ngx_delete_udp_connection(c);
1731         }
1732 
1733         if (pscf->responses == NGX_MAX_INT32_VALUE
1734             || u->responses < pscf->responses * u->requests)
1735         {
1736             return NGX_DECLINED;
1737         }
1738 
1739         if (pc == NULL || c->buffered || pc->buffered) {
1740             return NGX_DECLINED;
1741         }
1742 
1743         handler = c->log->handler;
1744         c->log->handler = NULL;
1745 
1746         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1747                       "udp done"
1748                       ", packets from/to client:%ui/%ui"
1749                       ", bytes from/to client:%O/%O"
1750                       ", bytes from/to upstream:%O/%O",
1751                       u->requests, u->responses,
1752                       s->received, c->sent, u->received, pc ? pc->sent : 0);
1753 
1754         c->log->handler = handler;
1755 
1756         ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
1757 
1758         return NGX_OK;
1759     }
1760 
1761     /* c->type == SOCK_STREAM */
1762 
1763     if (pc == NULL
1764         || (!c->read->eof && !pc->read->eof)
1765         || (!c->read->eof && c->buffered)
1766         || (!pc->read->eof && pc->buffered))
1767     {
1768         return NGX_DECLINED;
1769     }
1770 
1771     handler = c->log->handler;
1772     c->log->handler = NULL;
1773 
1774     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1775                   "%s disconnected"
1776                   ", bytes from/to client:%O/%O"
1777                   ", bytes from/to upstream:%O/%O",
1778                   from_upstream ? "upstream" : "client",
1779                   s->received, c->sent, u->received, pc ? pc->sent : 0);
1780 
1781     c->log->handler = handler;
1782 
1783     ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
1784 
1785     return NGX_OK;
1786 }
1787 
1788 
1789 static void
ngx_stream_proxy_next_upstream(ngx_stream_session_t * s)1790 ngx_stream_proxy_next_upstream(ngx_stream_session_t *s)
1791 {
1792     ngx_msec_t                    timeout;
1793     ngx_connection_t             *pc;
1794     ngx_stream_upstream_t        *u;
1795     ngx_stream_proxy_srv_conf_t  *pscf;
1796 
1797     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1798                    "stream proxy next upstream");
1799 
1800     u = s->upstream;
1801     pc = u->peer.connection;
1802 
1803     if (pc && pc->buffered) {
1804         ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
1805                       "buffered data on next upstream");
1806         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
1807         return;
1808     }
1809 
1810     if (s->connection->type == SOCK_DGRAM) {
1811         u->upstream_out = NULL;
1812     }
1813 
1814     if (u->peer.sockaddr) {
1815         u->peer.free(&u->peer, u->peer.data, NGX_PEER_FAILED);
1816         u->peer.sockaddr = NULL;
1817     }
1818 
1819     pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
1820 
1821     timeout = pscf->next_upstream_timeout;
1822 
1823     if (u->peer.tries == 0
1824         || !pscf->next_upstream
1825         || (timeout && ngx_current_msec - u->peer.start_time >= timeout))
1826     {
1827         ngx_stream_proxy_finalize(s, NGX_STREAM_BAD_GATEWAY);
1828         return;
1829     }
1830 
1831     if (pc) {
1832         ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1833                        "close proxy upstream connection: %d", pc->fd);
1834 
1835 #if (NGX_STREAM_SSL)
1836         if (pc->ssl) {
1837             pc->ssl->no_wait_shutdown = 1;
1838             pc->ssl->no_send_shutdown = 1;
1839 
1840             (void) ngx_ssl_shutdown(pc);
1841         }
1842 #endif
1843 
1844         u->state->bytes_received = u->received;
1845         u->state->bytes_sent = pc->sent;
1846 
1847         ngx_close_connection(pc);
1848         u->peer.connection = NULL;
1849     }
1850 
1851     ngx_stream_proxy_connect(s);
1852 }
1853 
1854 
1855 static void
ngx_stream_proxy_finalize(ngx_stream_session_t * s,ngx_uint_t rc)1856 ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc)
1857 {
1858     ngx_uint_t              state;
1859     ngx_connection_t       *pc;
1860     ngx_stream_upstream_t  *u;
1861 
1862     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1863                    "finalize stream proxy: %i", rc);
1864 
1865     u = s->upstream;
1866 
1867     if (u == NULL) {
1868         goto noupstream;
1869     }
1870 
1871     if (u->resolved && u->resolved->ctx) {
1872         ngx_resolve_name_done(u->resolved->ctx);
1873         u->resolved->ctx = NULL;
1874     }
1875 
1876     pc = u->peer.connection;
1877 
1878     if (u->state) {
1879         if (u->state->response_time == (ngx_msec_t) -1) {
1880             u->state->response_time = ngx_current_msec - u->start_time;
1881         }
1882 
1883         if (pc) {
1884             u->state->bytes_received = u->received;
1885             u->state->bytes_sent = pc->sent;
1886         }
1887     }
1888 
1889     if (u->peer.free && u->peer.sockaddr) {
1890         state = 0;
1891 
1892         if (pc && pc->type == SOCK_DGRAM
1893             && (pc->read->error || pc->write->error))
1894         {
1895             state = NGX_PEER_FAILED;
1896         }
1897 
1898         u->peer.free(&u->peer, u->peer.data, state);
1899         u->peer.sockaddr = NULL;
1900     }
1901 
1902     if (pc) {
1903         ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1904                        "close stream proxy upstream connection: %d", pc->fd);
1905 
1906 #if (NGX_STREAM_SSL)
1907         if (pc->ssl) {
1908             pc->ssl->no_wait_shutdown = 1;
1909             (void) ngx_ssl_shutdown(pc);
1910         }
1911 #endif
1912 
1913         ngx_close_connection(pc);
1914         u->peer.connection = NULL;
1915     }
1916 
1917 noupstream:
1918 
1919     ngx_stream_finalize_session(s, rc);
1920 }
1921 
1922 
1923 static u_char *
ngx_stream_proxy_log_error(ngx_log_t * log,u_char * buf,size_t len)1924 ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len)
1925 {
1926     u_char                 *p;
1927     ngx_connection_t       *pc;
1928     ngx_stream_session_t   *s;
1929     ngx_stream_upstream_t  *u;
1930 
1931     s = log->data;
1932 
1933     u = s->upstream;
1934 
1935     p = buf;
1936 
1937     if (u->peer.name) {
1938         p = ngx_snprintf(p, len, ", upstream: \"%V\"", u->peer.name);
1939         len -= p - buf;
1940     }
1941 
1942     pc = u->peer.connection;
1943 
1944     p = ngx_snprintf(p, len,
1945                      ", bytes from/to client:%O/%O"
1946                      ", bytes from/to upstream:%O/%O",
1947                      s->received, s->connection->sent,
1948                      u->received, pc ? pc->sent : 0);
1949 
1950     return p;
1951 }
1952 
1953 
1954 static void *
ngx_stream_proxy_create_srv_conf(ngx_conf_t * cf)1955 ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
1956 {
1957     ngx_stream_proxy_srv_conf_t  *conf;
1958 
1959     conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_proxy_srv_conf_t));
1960     if (conf == NULL) {
1961         return NULL;
1962     }
1963 
1964     /*
1965      * set by ngx_pcalloc():
1966      *
1967      *     conf->ssl_protocols = 0;
1968      *     conf->ssl_ciphers = { 0, NULL };
1969      *     conf->ssl_name = NULL;
1970      *     conf->ssl_trusted_certificate = { 0, NULL };
1971      *     conf->ssl_crl = { 0, NULL };
1972      *     conf->ssl_certificate = { 0, NULL };
1973      *     conf->ssl_certificate_key = { 0, NULL };
1974      *
1975      *     conf->ssl = NULL;
1976      *     conf->upstream = NULL;
1977      *     conf->upstream_value = NULL;
1978      */
1979 
1980     conf->connect_timeout = NGX_CONF_UNSET_MSEC;
1981     conf->timeout = NGX_CONF_UNSET_MSEC;
1982     conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC;
1983     conf->buffer_size = NGX_CONF_UNSET_SIZE;
1984     conf->upload_rate = NGX_CONF_UNSET_SIZE;
1985     conf->download_rate = NGX_CONF_UNSET_SIZE;
1986     conf->requests = NGX_CONF_UNSET_UINT;
1987     conf->responses = NGX_CONF_UNSET_UINT;
1988     conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
1989     conf->next_upstream = NGX_CONF_UNSET;
1990     conf->proxy_protocol = NGX_CONF_UNSET;
1991     conf->local = NGX_CONF_UNSET_PTR;
1992     conf->socket_keepalive = NGX_CONF_UNSET;
1993 
1994 #if (NGX_STREAM_SSL)
1995     conf->ssl_enable = NGX_CONF_UNSET;
1996     conf->ssl_session_reuse = NGX_CONF_UNSET;
1997     conf->ssl_server_name = NGX_CONF_UNSET;
1998     conf->ssl_verify = NGX_CONF_UNSET;
1999     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
2000     conf->ssl_passwords = NGX_CONF_UNSET_PTR;
2001 #endif
2002 
2003 #if (NGX_HAVE_FSTACK)
2004     conf->kernel_network_stack = NGX_CONF_UNSET;
2005 #endif
2006 
2007     return conf;
2008 }
2009 
2010 
2011 static char *
ngx_stream_proxy_merge_srv_conf(ngx_conf_t * cf,void * parent,void * child)2012 ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
2013 {
2014     ngx_stream_proxy_srv_conf_t *prev = parent;
2015     ngx_stream_proxy_srv_conf_t *conf = child;
2016 
2017     ngx_conf_merge_msec_value(conf->connect_timeout,
2018                               prev->connect_timeout, 60000);
2019 
2020     ngx_conf_merge_msec_value(conf->timeout,
2021                               prev->timeout, 10 * 60000);
2022 
2023     ngx_conf_merge_msec_value(conf->next_upstream_timeout,
2024                               prev->next_upstream_timeout, 0);
2025 
2026     ngx_conf_merge_size_value(conf->buffer_size,
2027                               prev->buffer_size, 16384);
2028 
2029     ngx_conf_merge_size_value(conf->upload_rate,
2030                               prev->upload_rate, 0);
2031 
2032     ngx_conf_merge_size_value(conf->download_rate,
2033                               prev->download_rate, 0);
2034 
2035     ngx_conf_merge_uint_value(conf->requests,
2036                               prev->requests, 0);
2037 
2038     ngx_conf_merge_uint_value(conf->responses,
2039                               prev->responses, NGX_MAX_INT32_VALUE);
2040 
2041     ngx_conf_merge_uint_value(conf->next_upstream_tries,
2042                               prev->next_upstream_tries, 0);
2043 
2044     ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1);
2045 
2046     ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0);
2047 
2048     ngx_conf_merge_ptr_value(conf->local, prev->local, NULL);
2049 
2050     ngx_conf_merge_value(conf->socket_keepalive,
2051                               prev->socket_keepalive, 0);
2052 
2053 #if (NGX_STREAM_SSL)
2054 
2055     ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0);
2056 
2057     ngx_conf_merge_value(conf->ssl_session_reuse,
2058                               prev->ssl_session_reuse, 1);
2059 
2060     ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
2061                               (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
2062                                |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
2063 
2064     ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT");
2065 
2066     if (conf->ssl_name == NULL) {
2067         conf->ssl_name = prev->ssl_name;
2068     }
2069 
2070     ngx_conf_merge_value(conf->ssl_server_name, prev->ssl_server_name, 0);
2071 
2072     ngx_conf_merge_value(conf->ssl_verify, prev->ssl_verify, 0);
2073 
2074     ngx_conf_merge_uint_value(conf->ssl_verify_depth,
2075                               prev->ssl_verify_depth, 1);
2076 
2077     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
2078                               prev->ssl_trusted_certificate, "");
2079 
2080     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
2081 
2082     ngx_conf_merge_str_value(conf->ssl_certificate,
2083                               prev->ssl_certificate, "");
2084 
2085     ngx_conf_merge_str_value(conf->ssl_certificate_key,
2086                               prev->ssl_certificate_key, "");
2087 
2088     ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
2089 
2090     if (conf->ssl_enable && ngx_stream_proxy_set_ssl(cf, conf) != NGX_OK) {
2091         return NGX_CONF_ERROR;
2092     }
2093 
2094 #endif
2095 
2096 #if (NGX_HAVE_FSTACK)
2097     /* By default, we set up a proxy on fstack */
2098     ngx_conf_merge_value(conf->kernel_network_stack,
2099                               prev->kernel_network_stack, 0);
2100 #endif
2101 
2102 
2103     return NGX_CONF_OK;
2104 }
2105 
2106 
2107 #if (NGX_STREAM_SSL)
2108 
2109 static ngx_int_t
ngx_stream_proxy_set_ssl(ngx_conf_t * cf,ngx_stream_proxy_srv_conf_t * pscf)2110 ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf)
2111 {
2112     ngx_pool_cleanup_t  *cln;
2113 
2114     pscf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
2115     if (pscf->ssl == NULL) {
2116         return NGX_ERROR;
2117     }
2118 
2119     pscf->ssl->log = cf->log;
2120 
2121     if (ngx_ssl_create(pscf->ssl, pscf->ssl_protocols, NULL) != NGX_OK) {
2122         return NGX_ERROR;
2123     }
2124 
2125     cln = ngx_pool_cleanup_add(cf->pool, 0);
2126     if (cln == NULL) {
2127         ngx_ssl_cleanup_ctx(pscf->ssl);
2128         return NGX_ERROR;
2129     }
2130 
2131     cln->handler = ngx_ssl_cleanup_ctx;
2132     cln->data = pscf->ssl;
2133 
2134     if (pscf->ssl_certificate.len) {
2135 
2136         if (pscf->ssl_certificate_key.len == 0) {
2137             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
2138                           "no \"proxy_ssl_certificate_key\" is defined "
2139                           "for certificate \"%V\"", &pscf->ssl_certificate);
2140             return NGX_ERROR;
2141         }
2142 
2143         if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate,
2144                                 &pscf->ssl_certificate_key, pscf->ssl_passwords)
2145             != NGX_OK)
2146         {
2147             return NGX_ERROR;
2148         }
2149     }
2150 
2151     if (ngx_ssl_ciphers(cf, pscf->ssl, &pscf->ssl_ciphers, 0) != NGX_OK) {
2152         return NGX_ERROR;
2153     }
2154 
2155     if (pscf->ssl_verify) {
2156         if (pscf->ssl_trusted_certificate.len == 0) {
2157             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
2158                       "no proxy_ssl_trusted_certificate for proxy_ssl_verify");
2159             return NGX_ERROR;
2160         }
2161 
2162         if (ngx_ssl_trusted_certificate(cf, pscf->ssl,
2163                                         &pscf->ssl_trusted_certificate,
2164                                         pscf->ssl_verify_depth)
2165             != NGX_OK)
2166         {
2167             return NGX_ERROR;
2168         }
2169 
2170         if (ngx_ssl_crl(cf, pscf->ssl, &pscf->ssl_crl) != NGX_OK) {
2171             return NGX_ERROR;
2172         }
2173     }
2174 
2175     if (ngx_ssl_client_session_cache(cf, pscf->ssl, pscf->ssl_session_reuse)
2176         != NGX_OK)
2177     {
2178         return NGX_ERROR;
2179     }
2180 
2181     return NGX_OK;
2182 }
2183 
2184 #endif
2185 
2186 
2187 static char *
ngx_stream_proxy_pass(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)2188 ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2189 {
2190     ngx_stream_proxy_srv_conf_t *pscf = conf;
2191 
2192     ngx_url_t                            u;
2193     ngx_str_t                           *value, *url;
2194     ngx_stream_complex_value_t           cv;
2195     ngx_stream_core_srv_conf_t          *cscf;
2196     ngx_stream_compile_complex_value_t   ccv;
2197 
2198     if (pscf->upstream || pscf->upstream_value) {
2199         return "is duplicate";
2200     }
2201 
2202     cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module);
2203 
2204     cscf->handler = ngx_stream_proxy_handler;
2205 
2206     value = cf->args->elts;
2207 
2208     url = &value[1];
2209 
2210     ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
2211 
2212     ccv.cf = cf;
2213     ccv.value = url;
2214     ccv.complex_value = &cv;
2215 
2216     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
2217         return NGX_CONF_ERROR;
2218     }
2219 
2220     if (cv.lengths) {
2221         pscf->upstream_value = ngx_palloc(cf->pool,
2222                                           sizeof(ngx_stream_complex_value_t));
2223         if (pscf->upstream_value == NULL) {
2224             return NGX_CONF_ERROR;
2225         }
2226 
2227         *pscf->upstream_value = cv;
2228 
2229         return NGX_CONF_OK;
2230     }
2231 
2232     ngx_memzero(&u, sizeof(ngx_url_t));
2233 
2234     u.url = *url;
2235     u.no_resolve = 1;
2236 
2237     pscf->upstream = ngx_stream_upstream_add(cf, &u, 0);
2238     if (pscf->upstream == NULL) {
2239         return NGX_CONF_ERROR;
2240     }
2241 
2242     return NGX_CONF_OK;
2243 }
2244 
2245 
2246 static char *
ngx_stream_proxy_bind(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)2247 ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2248 {
2249     ngx_stream_proxy_srv_conf_t *pscf = conf;
2250 
2251     ngx_int_t                            rc;
2252     ngx_str_t                           *value;
2253     ngx_stream_complex_value_t           cv;
2254     ngx_stream_upstream_local_t         *local;
2255     ngx_stream_compile_complex_value_t   ccv;
2256 
2257     if (pscf->local != NGX_CONF_UNSET_PTR) {
2258         return "is duplicate";
2259     }
2260 
2261     value = cf->args->elts;
2262 
2263     if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "off") == 0) {
2264         pscf->local = NULL;
2265         return NGX_CONF_OK;
2266     }
2267 
2268     ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
2269 
2270     ccv.cf = cf;
2271     ccv.value = &value[1];
2272     ccv.complex_value = &cv;
2273 
2274     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
2275         return NGX_CONF_ERROR;
2276     }
2277 
2278     local = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_local_t));
2279     if (local == NULL) {
2280         return NGX_CONF_ERROR;
2281     }
2282 
2283     pscf->local = local;
2284 
2285     if (cv.lengths) {
2286         local->value = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t));
2287         if (local->value == NULL) {
2288             return NGX_CONF_ERROR;
2289         }
2290 
2291         *local->value = cv;
2292 
2293     } else {
2294         local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
2295         if (local->addr == NULL) {
2296             return NGX_CONF_ERROR;
2297         }
2298 
2299         rc = ngx_parse_addr_port(cf->pool, local->addr, value[1].data,
2300                                  value[1].len);
2301 
2302         switch (rc) {
2303         case NGX_OK:
2304             local->addr->name = value[1];
2305             break;
2306 
2307         case NGX_DECLINED:
2308             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2309                                "invalid address \"%V\"", &value[1]);
2310             /* fall through */
2311 
2312         default:
2313             return NGX_CONF_ERROR;
2314         }
2315     }
2316 
2317     if (cf->args->nelts > 2) {
2318         if (ngx_strcmp(value[2].data, "transparent") == 0) {
2319 #if (NGX_HAVE_TRANSPARENT_PROXY)
2320             ngx_core_conf_t  *ccf;
2321 
2322             ccf = (ngx_core_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
2323                                                    ngx_core_module);
2324 
2325             ccf->transparent = 1;
2326             local->transparent = 1;
2327 #else
2328             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2329                                "transparent proxying is not supported "
2330                                "on this platform, ignored");
2331 #endif
2332         } else {
2333             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2334                                "invalid parameter \"%V\"", &value[2]);
2335             return NGX_CONF_ERROR;
2336         }
2337     }
2338 
2339     return NGX_CONF_OK;
2340 }
2341