comparison src/stream/ngx_stream_proxy_module.c @ 6115:61d7ae76647d

Stream: port from NGINX+.
author Ruslan Ermilov <ru@nginx.com>
date Mon, 20 Apr 2015 13:05:11 +0300
parents
children f1f222db290b
comparison
equal deleted inserted replaced
6114:4a640716f4e2 6115:61d7ae76647d
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 void (*ngx_stream_proxy_handler_pt)(ngx_stream_session_t *s);
14
15
16 typedef struct {
17 ngx_msec_t connect_timeout;
18 ngx_msec_t timeout;
19 ngx_msec_t next_upstream_timeout;
20 size_t downstream_buf_size;
21 size_t upstream_buf_size;
22 ngx_uint_t next_upstream_tries;
23 ngx_flag_t next_upstream;
24
25 #if (NGX_STREAM_SSL)
26 ngx_flag_t ssl_enable;
27 ngx_flag_t ssl_session_reuse;
28 ngx_uint_t ssl_protocols;
29 ngx_str_t ssl_ciphers;
30 ngx_str_t ssl_name;
31 ngx_flag_t ssl_server_name;
32
33 ngx_flag_t ssl_verify;
34 ngx_uint_t ssl_verify_depth;
35 ngx_str_t ssl_trusted_certificate;
36 ngx_str_t ssl_crl;
37 ngx_str_t ssl_certificate;
38 ngx_str_t ssl_certificate_key;
39 ngx_array_t *ssl_passwords;
40
41 ngx_ssl_t *ssl;
42 #endif
43
44 ngx_stream_upstream_srv_conf_t *upstream;
45 } ngx_stream_proxy_srv_conf_t;
46
47
48 static void ngx_stream_proxy_handler(ngx_stream_session_t *s);
49 static void ngx_stream_proxy_connect(ngx_stream_session_t *s);
50 static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s);
51 static void ngx_stream_proxy_upstream_handler(ngx_event_t *ev);
52 static void ngx_stream_proxy_downstream_handler(ngx_event_t *ev);
53 static void ngx_stream_proxy_connect_handler(ngx_event_t *ev);
54 static ngx_int_t ngx_stream_proxy_test_connect(ngx_connection_t *c);
55 static ngx_int_t ngx_stream_proxy_process(ngx_stream_session_t *s,
56 ngx_uint_t from_upstream, ngx_uint_t do_write);
57 static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s);
58 static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_int_t rc);
59 static u_char *ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf,
60 size_t len);
61
62 static void *ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf);
63 static char *ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent,
64 void *child);
65 static char *ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
66 void *conf);
67
68 #if (NGX_STREAM_SSL)
69
70 static char *ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf,
71 ngx_command_t *cmd, void *conf);
72 static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s);
73 static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc);
74 static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s);
75 static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf,
76 ngx_stream_proxy_srv_conf_t *pscf);
77
78
79 static ngx_conf_bitmask_t ngx_stream_proxy_ssl_protocols[] = {
80 { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
81 { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
82 { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
83 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
84 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
85 { ngx_null_string, 0 }
86 };
87
88 #endif
89
90
91 static ngx_command_t ngx_stream_proxy_commands[] = {
92
93 { ngx_string("proxy_pass"),
94 NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
95 ngx_stream_proxy_pass,
96 NGX_STREAM_SRV_CONF_OFFSET,
97 0,
98 NULL },
99
100 { ngx_string("proxy_connect_timeout"),
101 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
102 ngx_conf_set_msec_slot,
103 NGX_STREAM_SRV_CONF_OFFSET,
104 offsetof(ngx_stream_proxy_srv_conf_t, connect_timeout),
105 NULL },
106
107 { ngx_string("proxy_timeout"),
108 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
109 ngx_conf_set_msec_slot,
110 NGX_STREAM_SRV_CONF_OFFSET,
111 offsetof(ngx_stream_proxy_srv_conf_t, timeout),
112 NULL },
113
114 { ngx_string("proxy_downstream_buffer"),
115 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
116 ngx_conf_set_size_slot,
117 NGX_STREAM_SRV_CONF_OFFSET,
118 offsetof(ngx_stream_proxy_srv_conf_t, downstream_buf_size),
119 NULL },
120
121 { ngx_string("proxy_upstream_buffer"),
122 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
123 ngx_conf_set_size_slot,
124 NGX_STREAM_SRV_CONF_OFFSET,
125 offsetof(ngx_stream_proxy_srv_conf_t, upstream_buf_size),
126 NULL },
127
128 { ngx_string("proxy_next_upstream"),
129 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
130 ngx_conf_set_flag_slot,
131 NGX_STREAM_SRV_CONF_OFFSET,
132 offsetof(ngx_stream_proxy_srv_conf_t, next_upstream),
133 NULL },
134
135 { ngx_string("proxy_next_upstream_tries"),
136 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
137 ngx_conf_set_num_slot,
138 NGX_STREAM_SRV_CONF_OFFSET,
139 offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_tries),
140 NULL },
141
142 { ngx_string("proxy_next_upstream_timeout"),
143 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
144 ngx_conf_set_msec_slot,
145 NGX_STREAM_SRV_CONF_OFFSET,
146 offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_timeout),
147 NULL },
148
149 #if (NGX_STREAM_SSL)
150
151 { ngx_string("proxy_ssl"),
152 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
153 ngx_conf_set_flag_slot,
154 NGX_STREAM_SRV_CONF_OFFSET,
155 offsetof(ngx_stream_proxy_srv_conf_t, ssl_enable),
156 NULL },
157
158 { ngx_string("proxy_ssl_session_reuse"),
159 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
160 ngx_conf_set_flag_slot,
161 NGX_STREAM_SRV_CONF_OFFSET,
162 offsetof(ngx_stream_proxy_srv_conf_t, ssl_session_reuse),
163 NULL },
164
165 { ngx_string("proxy_ssl_protocols"),
166 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
167 ngx_conf_set_bitmask_slot,
168 NGX_STREAM_SRV_CONF_OFFSET,
169 offsetof(ngx_stream_proxy_srv_conf_t, ssl_protocols),
170 &ngx_stream_proxy_ssl_protocols },
171
172 { ngx_string("proxy_ssl_ciphers"),
173 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
174 ngx_conf_set_str_slot,
175 NGX_STREAM_SRV_CONF_OFFSET,
176 offsetof(ngx_stream_proxy_srv_conf_t, ssl_ciphers),
177 NULL },
178
179 { ngx_string("proxy_ssl_name"),
180 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
181 ngx_conf_set_str_slot,
182 NGX_STREAM_SRV_CONF_OFFSET,
183 offsetof(ngx_stream_proxy_srv_conf_t, ssl_name),
184 NULL },
185
186 { ngx_string("proxy_ssl_server_name"),
187 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
188 ngx_conf_set_flag_slot,
189 NGX_STREAM_SRV_CONF_OFFSET,
190 offsetof(ngx_stream_proxy_srv_conf_t, ssl_server_name),
191 NULL },
192
193 { ngx_string("proxy_ssl_verify"),
194 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
195 ngx_conf_set_flag_slot,
196 NGX_STREAM_SRV_CONF_OFFSET,
197 offsetof(ngx_stream_proxy_srv_conf_t, ssl_verify),
198 NULL },
199
200 { ngx_string("proxy_ssl_verify_depth"),
201 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
202 ngx_conf_set_num_slot,
203 NGX_STREAM_SRV_CONF_OFFSET,
204 offsetof(ngx_stream_proxy_srv_conf_t, ssl_verify_depth),
205 NULL },
206
207 { ngx_string("proxy_ssl_trusted_certificate"),
208 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
209 ngx_conf_set_str_slot,
210 NGX_STREAM_SRV_CONF_OFFSET,
211 offsetof(ngx_stream_proxy_srv_conf_t, ssl_trusted_certificate),
212 NULL },
213
214 { ngx_string("proxy_ssl_crl"),
215 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
216 ngx_conf_set_str_slot,
217 NGX_STREAM_SRV_CONF_OFFSET,
218 offsetof(ngx_stream_proxy_srv_conf_t, ssl_crl),
219 NULL },
220
221 { ngx_string("proxy_ssl_certificate"),
222 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
223 ngx_conf_set_str_slot,
224 NGX_STREAM_SRV_CONF_OFFSET,
225 offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate),
226 NULL },
227
228 { ngx_string("proxy_ssl_certificate_key"),
229 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
230 ngx_conf_set_str_slot,
231 NGX_STREAM_SRV_CONF_OFFSET,
232 offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_key),
233 NULL },
234
235 { ngx_string("proxy_ssl_password_file"),
236 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
237 ngx_stream_proxy_ssl_password_file,
238 NGX_STREAM_SRV_CONF_OFFSET,
239 0,
240 NULL },
241
242 #endif
243
244 ngx_null_command
245 };
246
247
248 static ngx_stream_module_t ngx_stream_proxy_module_ctx = {
249 NULL, /* create main configuration */
250 NULL, /* init main configuration */
251
252 ngx_stream_proxy_create_srv_conf, /* create server configuration */
253 ngx_stream_proxy_merge_srv_conf /* merge server configuration */
254 };
255
256
257 ngx_module_t ngx_stream_proxy_module = {
258 NGX_MODULE_V1,
259 &ngx_stream_proxy_module_ctx, /* module context */
260 ngx_stream_proxy_commands, /* module directives */
261 NGX_STREAM_MODULE, /* module type */
262 NULL, /* init master */
263 NULL, /* init module */
264 NULL, /* init process */
265 NULL, /* init thread */
266 NULL, /* exit thread */
267 NULL, /* exit process */
268 NULL, /* exit master */
269 NGX_MODULE_V1_PADDING
270 };
271
272
273 static void
274 ngx_stream_proxy_handler(ngx_stream_session_t *s)
275 {
276 u_char *p;
277 ngx_connection_t *c;
278 ngx_stream_upstream_t *u;
279 ngx_stream_proxy_srv_conf_t *pscf;
280 ngx_stream_upstream_srv_conf_t *uscf;
281
282 c = s->connection;
283
284 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
285
286 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
287 "proxy connection handler");
288
289 u = ngx_pcalloc(c->pool, sizeof(ngx_stream_upstream_t));
290 if (u == NULL) {
291 ngx_stream_proxy_finalize(s, NGX_ERROR);
292 return;
293 }
294
295 s->upstream = u;
296
297 s->log_handler = ngx_stream_proxy_log_error;
298
299 u->peer.log = c->log;
300 u->peer.log_error = NGX_ERROR_ERR;
301
302 uscf = pscf->upstream;
303
304 if (uscf->peer.init(s, uscf) != NGX_OK) {
305 ngx_stream_proxy_finalize(s, NGX_ERROR);
306 return;
307 }
308
309 u->peer.start_time = ngx_current_msec;
310
311 if (pscf->next_upstream_tries
312 && u->peer.tries > pscf->next_upstream_tries)
313 {
314 u->peer.tries = pscf->next_upstream_tries;
315 }
316
317 p = ngx_pnalloc(c->pool, pscf->downstream_buf_size);
318 if (p == NULL) {
319 ngx_stream_proxy_finalize(s, NGX_ERROR);
320 return;
321 }
322
323 u->downstream_buf.start = p;
324 u->downstream_buf.end = p + pscf->downstream_buf_size;
325 u->downstream_buf.pos = p;
326 u->downstream_buf.last = p;
327
328 c->write->handler = ngx_stream_proxy_downstream_handler;
329 c->read->handler = ngx_stream_proxy_downstream_handler;
330
331 if (ngx_stream_proxy_process(s, 0, 0) != NGX_OK) {
332 return;
333 }
334
335 ngx_stream_proxy_connect(s);
336 }
337
338
339 static void
340 ngx_stream_proxy_connect(ngx_stream_session_t *s)
341 {
342 ngx_int_t rc;
343 ngx_connection_t *c, *pc;
344 ngx_stream_upstream_t *u;
345 ngx_stream_proxy_srv_conf_t *pscf;
346
347 c = s->connection;
348
349 c->log->action = "connecting to upstream";
350
351 u = s->upstream;
352
353 rc = ngx_event_connect_peer(&u->peer);
354
355 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc);
356
357 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
358
359 if (rc == NGX_ERROR) {
360 ngx_stream_proxy_finalize(s, NGX_ERROR);
361 return;
362 }
363
364 if (rc == NGX_BUSY) {
365 ngx_log_error(NGX_LOG_ERR, c->log, 0, "no live upstreams");
366 ngx_stream_proxy_finalize(s, NGX_DECLINED);
367 return;
368 }
369
370 if (rc == NGX_DECLINED) {
371 ngx_stream_proxy_next_upstream(s);
372 return;
373 }
374
375 /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */
376
377 pc = u->peer.connection;
378
379 pc->data = s;
380 pc->log = c->log;
381 pc->pool = c->pool;
382 pc->read->log = c->log;
383 pc->write->log = c->log;
384
385 if (rc != NGX_AGAIN) {
386 ngx_stream_proxy_init_upstream(s);
387 return;
388 }
389
390 pc->read->handler = ngx_stream_proxy_connect_handler;
391 pc->write->handler = ngx_stream_proxy_connect_handler;
392
393 ngx_add_timer(pc->write, pscf->connect_timeout);
394 }
395
396
397 static void
398 ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
399 {
400 u_char *p;
401 ngx_connection_t *c, *pc;
402 ngx_log_handler_pt handler;
403 ngx_stream_upstream_t *u;
404 ngx_stream_proxy_srv_conf_t *pscf;
405
406 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
407
408 u = s->upstream;
409
410 pc = u->peer.connection;
411
412 #if (NGX_STREAM_SSL)
413 if (pscf->ssl && pc->ssl == NULL) {
414 ngx_stream_proxy_ssl_init_connection(s);
415 return;
416 }
417 #endif
418
419 c = s->connection;
420
421 if (c->log->log_level >= NGX_LOG_INFO) {
422 ngx_str_t s;
423 u_char addr[NGX_SOCKADDR_STRLEN];
424
425 s.len = NGX_SOCKADDR_STRLEN;
426 s.data = addr;
427
428 if (ngx_connection_local_sockaddr(pc, &s, 1) == NGX_OK) {
429 handler = c->log->handler;
430 c->log->handler = NULL;
431
432 ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxy %V connected to %V",
433 &s, u->peer.name);
434
435 c->log->handler = handler;
436 }
437 }
438
439 c->log->action = "proxying connection";
440
441 p = ngx_pnalloc(c->pool, pscf->upstream_buf_size);
442 if (p == NULL) {
443 ngx_stream_proxy_finalize(s, NGX_ERROR);
444 return;
445 }
446
447 u->upstream_buf.start = p;
448 u->upstream_buf.end = p + pscf->upstream_buf_size;
449 u->upstream_buf.pos = p;
450 u->upstream_buf.last = p;
451
452 pc->read->handler = ngx_stream_proxy_upstream_handler;
453 pc->write->handler = ngx_stream_proxy_upstream_handler;
454
455 if (ngx_stream_proxy_process(s, 1, 0) != NGX_OK) {
456 return;
457 }
458
459 ngx_stream_proxy_process(s, 0, 1);
460 }
461
462
463 #if (NGX_STREAM_SSL)
464
465 static char *
466 ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
467 void *conf)
468 {
469 ngx_stream_proxy_srv_conf_t *pscf = conf;
470
471 ngx_str_t *value;
472
473 if (pscf->ssl_passwords != NGX_CONF_UNSET_PTR) {
474 return "is duplicate";
475 }
476
477 value = cf->args->elts;
478
479 pscf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
480
481 if (pscf->ssl_passwords == NULL) {
482 return NGX_CONF_ERROR;
483 }
484
485 return NGX_CONF_OK;
486 }
487
488
489 static void
490 ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
491 {
492 ngx_int_t rc;
493 ngx_connection_t *pc;
494 ngx_stream_upstream_t *u;
495 ngx_stream_proxy_srv_conf_t *pscf;
496
497 u = s->upstream;
498
499 pc = u->peer.connection;
500
501 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
502
503 if (ngx_ssl_create_connection(pscf->ssl, pc, NGX_SSL_BUFFER|NGX_SSL_CLIENT)
504 != NGX_OK)
505 {
506 ngx_stream_proxy_finalize(s, NGX_ERROR);
507 return;
508 }
509
510 if (pscf->ssl_server_name || pscf->ssl_verify) {
511 if (ngx_stream_proxy_ssl_name(s) != NGX_OK) {
512 ngx_stream_proxy_finalize(s, NGX_ERROR);
513 return;
514 }
515 }
516
517 if (pscf->ssl_session_reuse) {
518 if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
519 ngx_stream_proxy_finalize(s, NGX_ERROR);
520 return;
521 }
522 }
523
524 s->connection->log->action = "SSL handshaking to upstream";
525
526 rc = ngx_ssl_handshake(pc);
527
528 if (rc == NGX_AGAIN) {
529
530 if (!pc->write->timer_set) {
531 ngx_add_timer(pc->write, pscf->connect_timeout);
532 }
533
534 pc->ssl->handler = ngx_stream_proxy_ssl_handshake;
535 return;
536 }
537
538 ngx_stream_proxy_ssl_handshake(pc);
539 }
540
541
542 static void
543 ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc)
544 {
545 long rc;
546 ngx_stream_session_t *s;
547 ngx_stream_upstream_t *u;
548 ngx_stream_proxy_srv_conf_t *pscf;
549
550 s = pc->data;
551
552 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
553
554 if (pc->ssl->handshaked) {
555
556 if (pscf->ssl_verify) {
557 rc = SSL_get_verify_result(pc->ssl->connection);
558
559 if (rc != X509_V_OK) {
560 ngx_log_error(NGX_LOG_ERR, pc->log, 0,
561 "upstream SSL certificate verify error: (%l:%s)",
562 rc, X509_verify_cert_error_string(rc));
563 goto failed;
564 }
565
566 u = s->upstream;
567
568 if (ngx_ssl_check_host(pc, &u->ssl_name) != NGX_OK) {
569 ngx_log_error(NGX_LOG_ERR, pc->log, 0,
570 "upstream SSL certificate does not match \"%V\"",
571 &u->ssl_name);
572 goto failed;
573 }
574 }
575
576 if (pscf->ssl_session_reuse) {
577 u = s->upstream;
578 u->peer.save_session(&u->peer, u->peer.data);
579 }
580
581 ngx_stream_proxy_init_upstream(s);
582
583 return;
584 }
585
586 failed:
587
588 ngx_stream_proxy_next_upstream(s);
589 }
590
591
592 static ngx_int_t
593 ngx_stream_proxy_ssl_name(ngx_stream_session_t *s)
594 {
595 u_char *p, *last;
596 ngx_str_t name;
597 ngx_stream_upstream_t *u;
598 ngx_stream_proxy_srv_conf_t *pscf;
599
600 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
601
602 u = s->upstream;
603
604 name = pscf->ssl_name;
605
606 if (name.len == 0) {
607 name = pscf->upstream->host;
608 }
609
610 if (name.len == 0) {
611 goto done;
612 }
613
614 /*
615 * ssl name here may contain port, strip it for compatibility
616 * with the http module
617 */
618
619 p = name.data;
620 last = name.data + name.len;
621
622 if (*p == '[') {
623 p = ngx_strlchr(p, last, ']');
624
625 if (p == NULL) {
626 p = name.data;
627 }
628 }
629
630 p = ngx_strlchr(p, last, ':');
631
632 if (p != NULL) {
633 name.len = p - name.data;
634 }
635
636 if (!pscf->ssl_server_name) {
637 goto done;
638 }
639
640 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
641
642 /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */
643
644 if (name.len == 0 || *name.data == '[') {
645 goto done;
646 }
647
648 if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) {
649 goto done;
650 }
651
652 /*
653 * SSL_set_tlsext_host_name() needs a null-terminated string,
654 * hence we explicitly null-terminate name here
655 */
656
657 p = ngx_pnalloc(s->connection->pool, name.len + 1);
658 if (p == NULL) {
659 return NGX_ERROR;
660 }
661
662 (void) ngx_cpystrn(p, name.data, name.len + 1);
663
664 name.data = p;
665
666 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
667 "upstream SSL server name: \"%s\"", name.data);
668
669 if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection, name.data)
670 == 0)
671 {
672 ngx_ssl_error(NGX_LOG_ERR, s->connection->log, 0,
673 "SSL_set_tlsext_host_name(\"%s\") failed", name.data);
674 return NGX_ERROR;
675 }
676
677 #endif
678
679 done:
680
681 u->ssl_name = name;
682
683 return NGX_OK;
684 }
685
686 #endif
687
688
689 static void
690 ngx_stream_proxy_downstream_handler(ngx_event_t *ev)
691 {
692 ngx_connection_t *c;
693 ngx_stream_session_t *s;
694 ngx_stream_upstream_t *u;
695
696 c = ev->data;
697 s = c->data;
698
699 if (ev->timedout) {
700 ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out");
701 ngx_stream_proxy_finalize(s, NGX_DECLINED);
702 return;
703 }
704
705 u = s->upstream;
706
707 if (!ev->write) {
708 ngx_stream_proxy_process(s, 0, 0);
709
710 } else if (u->upstream_buf.start) {
711 ngx_stream_proxy_process(s, 1, 1);
712 }
713 }
714
715
716 static void
717 ngx_stream_proxy_upstream_handler(ngx_event_t *ev)
718 {
719 ngx_connection_t *c;
720 ngx_stream_session_t *s;
721 ngx_stream_upstream_t *u;
722
723 c = ev->data;
724 s = c->data;
725
726 u = s->upstream;
727
728 if (ev->write) {
729 ngx_stream_proxy_process(s, 0, 1);
730
731 } else if (u->upstream_buf.start) {
732 ngx_stream_proxy_process(s, 1, 0);
733 }
734 }
735
736
737 static void
738 ngx_stream_proxy_connect_handler(ngx_event_t *ev)
739 {
740 ngx_connection_t *c;
741 ngx_stream_session_t *s;
742
743 c = ev->data;
744 s = c->data;
745
746 if (ev->timedout) {
747 ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "upstream timed out");
748 ngx_stream_proxy_next_upstream(s);
749 return;
750 }
751
752 ngx_del_timer(c->write);
753
754 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
755 "stream proxy connect upstream");
756
757 if (ngx_stream_proxy_test_connect(c) != NGX_OK) {
758 ngx_stream_proxy_next_upstream(s);
759 return;
760 }
761
762 ngx_stream_proxy_init_upstream(s);
763 }
764
765
766 static ngx_int_t
767 ngx_stream_proxy_test_connect(ngx_connection_t *c)
768 {
769 int err;
770 socklen_t len;
771
772 #if (NGX_HAVE_KQUEUE)
773
774 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
775 err = c->write->kq_errno ? c->write->kq_errno : c->read->kq_errno;
776
777 if (err) {
778 (void) ngx_connection_error(c, err,
779 "kevent() reported that connect() failed");
780 return NGX_ERROR;
781 }
782
783 } else
784 #endif
785 {
786 err = 0;
787 len = sizeof(int);
788
789 /*
790 * BSDs and Linux return 0 and set a pending error in err
791 * Solaris returns -1 and sets errno
792 */
793
794 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
795 == -1)
796 {
797 err = ngx_socket_errno;
798 }
799
800 if (err) {
801 (void) ngx_connection_error(c, err, "connect() failed");
802 return NGX_ERROR;
803 }
804 }
805
806 return NGX_OK;
807 }
808
809
810 static ngx_int_t
811 ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
812 ngx_uint_t do_write)
813 {
814 size_t size;
815 ssize_t n;
816 ngx_buf_t *b;
817 ngx_connection_t *c, *pc, *src, *dst;
818 ngx_log_handler_pt handler;
819 ngx_stream_upstream_t *u;
820 ngx_stream_proxy_srv_conf_t *pscf;
821
822 u = s->upstream;
823
824 c = s->connection;
825 pc = u->upstream_buf.start ? u->peer.connection : NULL;
826
827 if (from_upstream) {
828 src = pc;
829 dst = c;
830 b = &u->upstream_buf;
831
832 } else {
833 src = c;
834 dst = pc;
835 b = &u->downstream_buf;
836 }
837
838 for ( ;; ) {
839
840 if (do_write) {
841
842 size = b->last - b->pos;
843
844 if (size && dst && dst->write->ready) {
845
846 n = dst->send(dst, b->pos, size);
847
848 if (n == NGX_ERROR) {
849 ngx_stream_proxy_finalize(s, NGX_DECLINED);
850 return NGX_ERROR;
851 }
852
853 if (n > 0) {
854 b->pos += n;
855
856 if (b->pos == b->last) {
857 b->pos = b->start;
858 b->last = b->start;
859 }
860 }
861 }
862 }
863
864 size = b->end - b->last;
865
866 if (size && src->read->ready) {
867
868 n = src->recv(src, b->last, size);
869
870 if (n == NGX_AGAIN || n == 0) {
871 break;
872 }
873
874 if (n > 0) {
875 if (from_upstream) {
876 u->received += n;
877
878 } else {
879 s->received += n;
880 }
881
882 do_write = 1;
883 b->last += n;
884 continue;
885 }
886
887 if (n == NGX_ERROR) {
888 src->read->eof = 1;
889 }
890 }
891
892 break;
893 }
894
895 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
896
897 if (src->read->eof && (b->pos == b->last || (dst && dst->read->eof))) {
898 handler = c->log->handler;
899 c->log->handler = NULL;
900
901 ngx_log_error(NGX_LOG_INFO, c->log, 0,
902 "%s disconnected"
903 ", bytes from/to client:%O/%O"
904 ", bytes from/to upstream:%O/%O",
905 from_upstream ? "upstream" : "client",
906 s->received, c->sent, u->received, pc ? pc->sent : 0);
907
908 c->log->handler = handler;
909
910 ngx_stream_proxy_finalize(s, NGX_OK);
911 return NGX_DONE;
912 }
913
914 if (ngx_handle_read_event(src->read, 0) != NGX_OK) {
915 ngx_stream_proxy_finalize(s, NGX_ERROR);
916 return NGX_ERROR;
917 }
918
919 if (dst) {
920 if (ngx_handle_write_event(dst->write, 0) != NGX_OK) {
921 ngx_stream_proxy_finalize(s, NGX_ERROR);
922 return NGX_ERROR;
923 }
924
925 ngx_add_timer(c->read, pscf->timeout);
926 }
927
928 return NGX_OK;
929 }
930
931
932 static void
933 ngx_stream_proxy_next_upstream(ngx_stream_session_t *s)
934 {
935 ngx_msec_t timeout;
936 ngx_connection_t *pc;
937 ngx_stream_upstream_t *u;
938 ngx_stream_proxy_srv_conf_t *pscf;
939
940 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
941 "stream proxy next upstream");
942
943 u = s->upstream;
944
945 if (u->peer.sockaddr) {
946 u->peer.free(&u->peer, u->peer.data, NGX_PEER_FAILED);
947 u->peer.sockaddr = NULL;
948 }
949
950 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
951
952 timeout = pscf->next_upstream_timeout;
953
954 if (u->peer.tries == 0
955 || !pscf->next_upstream
956 || (timeout && ngx_current_msec - u->peer.start_time >= timeout))
957 {
958 ngx_stream_proxy_finalize(s, NGX_DECLINED);
959 return;
960 }
961
962 pc = u->peer.connection;
963
964 if (pc) {
965 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
966 "close proxy upstream connection: %d", pc->fd);
967
968 #if (NGX_STREAM_SSL)
969 if (pc->ssl) {
970 pc->ssl->no_wait_shutdown = 1;
971 pc->ssl->no_send_shutdown = 1;
972
973 (void) ngx_ssl_shutdown(pc);
974 }
975 #endif
976
977 ngx_close_connection(pc);
978 u->peer.connection = NULL;
979 }
980
981 ngx_stream_proxy_connect(s);
982 }
983
984
985 static void
986 ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_int_t rc)
987 {
988 ngx_connection_t *pc;
989 ngx_stream_upstream_t *u;
990
991 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
992 "finalize stream proxy: %i", rc);
993
994 u = s->upstream;
995
996 if (u == NULL) {
997 goto noupstream;
998 }
999
1000 if (u->peer.free && u->peer.sockaddr) {
1001 u->peer.free(&u->peer, u->peer.data, 0);
1002 u->peer.sockaddr = NULL;
1003 }
1004
1005 pc = u->peer.connection;
1006
1007 if (pc) {
1008 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
1009 "close stream proxy upstream connection: %d", pc->fd);
1010
1011 #if (NGX_STREAM_SSL)
1012 if (pc->ssl) {
1013 pc->ssl->no_wait_shutdown = 1;
1014 (void) ngx_ssl_shutdown(pc);
1015 }
1016 #endif
1017
1018 ngx_close_connection(pc);
1019 u->peer.connection = NULL;
1020 }
1021
1022 noupstream:
1023
1024 ngx_stream_close_connection(s->connection);
1025 }
1026
1027
1028 static u_char *
1029 ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len)
1030 {
1031 u_char *p;
1032 ngx_connection_t *pc;
1033 ngx_stream_session_t *s;
1034 ngx_stream_upstream_t *u;
1035
1036 s = log->data;
1037
1038 u = s->upstream;
1039
1040 p = buf;
1041
1042 if (u->peer.name) {
1043 p = ngx_snprintf(p, len, ", upstream: \"%V\"", u->peer.name);
1044 len -= p - buf;
1045 }
1046
1047 pc = u->peer.connection;
1048
1049 p = ngx_snprintf(p, len,
1050 ", bytes from/to client:%O/%O"
1051 ", bytes from/to upstream:%O/%O",
1052 s->received, s->connection->sent,
1053 u->received, pc ? pc->sent : 0);
1054
1055 return p;
1056 }
1057
1058
1059 static void *
1060 ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
1061 {
1062 ngx_stream_proxy_srv_conf_t *conf;
1063
1064 conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_proxy_srv_conf_t));
1065 if (conf == NULL) {
1066 return NULL;
1067 }
1068
1069 /*
1070 * set by ngx_pcalloc():
1071 *
1072 * conf->ssl_protocols = 0;
1073 * conf->ssl_ciphers = { 0, NULL };
1074 * conf->ssl_name = { 0, NULL };
1075 * conf->ssl_trusted_certificate = { 0, NULL };
1076 * conf->ssl_crl = { 0, NULL };
1077 * conf->ssl_certificate = { 0, NULL };
1078 * conf->ssl_certificate_key = { 0, NULL };
1079 *
1080 * conf->ssl = NULL;
1081 * conf->upstream = NULL;
1082 */
1083
1084 conf->connect_timeout = NGX_CONF_UNSET_MSEC;
1085 conf->timeout = NGX_CONF_UNSET_MSEC;
1086 conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC;
1087 conf->downstream_buf_size = NGX_CONF_UNSET_SIZE;
1088 conf->upstream_buf_size = NGX_CONF_UNSET_SIZE;
1089 conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
1090 conf->next_upstream = NGX_CONF_UNSET;
1091
1092 #if (NGX_STREAM_SSL)
1093 conf->ssl_enable = NGX_CONF_UNSET;
1094 conf->ssl_session_reuse = NGX_CONF_UNSET;
1095 conf->ssl_server_name = NGX_CONF_UNSET;
1096 conf->ssl_verify = NGX_CONF_UNSET;
1097 conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
1098 conf->ssl_passwords = NGX_CONF_UNSET_PTR;
1099 #endif
1100
1101 return conf;
1102 }
1103
1104
1105 static char *
1106 ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
1107 {
1108 ngx_stream_proxy_srv_conf_t *prev = parent;
1109 ngx_stream_proxy_srv_conf_t *conf = child;
1110
1111 ngx_conf_merge_msec_value(conf->connect_timeout,
1112 prev->connect_timeout, 60000);
1113
1114 ngx_conf_merge_msec_value(conf->timeout,
1115 prev->timeout, 10 * 60000);
1116
1117 ngx_conf_merge_msec_value(conf->next_upstream_timeout,
1118 prev->next_upstream_timeout, 0);
1119
1120 ngx_conf_merge_size_value(conf->downstream_buf_size,
1121 prev->downstream_buf_size, 16384);
1122
1123 ngx_conf_merge_size_value(conf->upstream_buf_size,
1124 prev->upstream_buf_size, 16384);
1125
1126 ngx_conf_merge_uint_value(conf->next_upstream_tries,
1127 prev->next_upstream_tries, 0);
1128
1129 ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1);
1130
1131 #if (NGX_STREAM_SSL)
1132
1133 ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0);
1134
1135 ngx_conf_merge_value(conf->ssl_session_reuse,
1136 prev->ssl_session_reuse, 1);
1137
1138 ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
1139 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3
1140 |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
1141 |NGX_SSL_TLSv1_2));
1142
1143 ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT");
1144
1145 ngx_conf_merge_str_value(conf->ssl_name, prev->ssl_name, "");
1146
1147 ngx_conf_merge_value(conf->ssl_server_name, prev->ssl_server_name, 0);
1148
1149 ngx_conf_merge_value(conf->ssl_verify, prev->ssl_verify, 0);
1150
1151 ngx_conf_merge_uint_value(conf->ssl_verify_depth,
1152 prev->ssl_verify_depth, 1);
1153
1154 ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
1155 prev->ssl_trusted_certificate, "");
1156
1157 ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
1158
1159 ngx_conf_merge_str_value(conf->ssl_certificate,
1160 prev->ssl_certificate, "");
1161
1162 ngx_conf_merge_str_value(conf->ssl_certificate_key,
1163 prev->ssl_certificate_key, "");
1164
1165 ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
1166
1167 if (conf->ssl_enable && ngx_stream_proxy_set_ssl(cf, conf) != NGX_OK) {
1168 return NGX_CONF_ERROR;
1169 }
1170
1171 #endif
1172
1173 return NGX_CONF_OK;
1174 }
1175
1176
1177 #if (NGX_STREAM_SSL)
1178
1179 static ngx_int_t
1180 ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf)
1181 {
1182 ngx_pool_cleanup_t *cln;
1183
1184 pscf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
1185 if (pscf->ssl == NULL) {
1186 return NGX_ERROR;
1187 }
1188
1189 pscf->ssl->log = cf->log;
1190
1191 if (ngx_ssl_create(pscf->ssl, pscf->ssl_protocols, NULL) != NGX_OK) {
1192 return NGX_ERROR;
1193 }
1194
1195 cln = ngx_pool_cleanup_add(cf->pool, 0);
1196 if (cln == NULL) {
1197 return NGX_ERROR;
1198 }
1199
1200 cln->handler = ngx_ssl_cleanup_ctx;
1201 cln->data = pscf->ssl;
1202
1203 if (pscf->ssl_certificate.len) {
1204
1205 if (pscf->ssl_certificate_key.len == 0) {
1206 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1207 "no \"proxy_ssl_certificate_key\" is defined "
1208 "for certificate \"%V\"", &pscf->ssl_certificate);
1209 return NGX_ERROR;
1210 }
1211
1212 if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate,
1213 &pscf->ssl_certificate_key, pscf->ssl_passwords)
1214 != NGX_OK)
1215 {
1216 return NGX_ERROR;
1217 }
1218 }
1219
1220 if (SSL_CTX_set_cipher_list(pscf->ssl->ctx,
1221 (const char *) pscf->ssl_ciphers.data)
1222 == 0)
1223 {
1224 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
1225 "SSL_CTX_set_cipher_list(\"%V\") failed",
1226 &pscf->ssl_ciphers);
1227 return NGX_ERROR;
1228 }
1229
1230 if (pscf->ssl_verify) {
1231 if (pscf->ssl_trusted_certificate.len == 0) {
1232 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1233 "no proxy_ssl_trusted_certificate for proxy_ssl_verify");
1234 return NGX_ERROR;
1235 }
1236
1237 if (ngx_ssl_trusted_certificate(cf, pscf->ssl,
1238 &pscf->ssl_trusted_certificate,
1239 pscf->ssl_verify_depth)
1240 != NGX_OK)
1241 {
1242 return NGX_ERROR;
1243 }
1244
1245 if (ngx_ssl_crl(cf, pscf->ssl, &pscf->ssl_crl) != NGX_OK) {
1246 return NGX_ERROR;
1247 }
1248 }
1249
1250 return NGX_OK;
1251 }
1252
1253 #endif
1254
1255
1256 static char *
1257 ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1258 {
1259 ngx_stream_proxy_srv_conf_t *pscf = conf;
1260
1261 ngx_url_t u;
1262 ngx_str_t *value, *url;
1263 ngx_stream_core_srv_conf_t *cscf;
1264
1265 if (pscf->upstream) {
1266 return "is duplicate";
1267 }
1268
1269 cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module);
1270
1271 cscf->handler = ngx_stream_proxy_handler;
1272
1273 value = cf->args->elts;
1274
1275 url = &value[1];
1276
1277 ngx_memzero(&u, sizeof(ngx_url_t));
1278
1279 u.url = *url;
1280 u.no_resolve = 1;
1281
1282 pscf->upstream = ngx_stream_upstream_add(cf, &u, 0);
1283 if (pscf->upstream == NULL) {
1284 return NGX_CONF_ERROR;
1285 }
1286
1287 return NGX_CONF_OK;
1288 }