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