Mercurial > hg > nginx
comparison src/stream/ngx_stream_proxy_module.c @ 6184:fa663739e115
Stream: client-side PROXY protocol.
The new directive "proxy_protocol" toggles sending out PROXY protocol header
to upstream once connection is established.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 16 Jun 2015 13:45:16 +0300 |
parents | 4dcffe43a7ea |
children | abee77018d3a |
comparison
equal
deleted
inserted
replaced
6183:4dcffe43a7ea | 6184:fa663739e115 |
---|---|
19 ngx_msec_t next_upstream_timeout; | 19 ngx_msec_t next_upstream_timeout; |
20 size_t downstream_buf_size; | 20 size_t downstream_buf_size; |
21 size_t upstream_buf_size; | 21 size_t upstream_buf_size; |
22 ngx_uint_t next_upstream_tries; | 22 ngx_uint_t next_upstream_tries; |
23 ngx_flag_t next_upstream; | 23 ngx_flag_t next_upstream; |
24 ngx_flag_t proxy_protocol; | |
24 ngx_addr_t *local; | 25 ngx_addr_t *local; |
25 | 26 |
26 #if (NGX_STREAM_SSL) | 27 #if (NGX_STREAM_SSL) |
27 ngx_flag_t ssl_enable; | 28 ngx_flag_t ssl_enable; |
28 ngx_flag_t ssl_session_reuse; | 29 ngx_flag_t ssl_session_reuse; |
65 void *child); | 66 void *child); |
66 static char *ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, | 67 static char *ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, |
67 void *conf); | 68 void *conf); |
68 static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, | 69 static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, |
69 void *conf); | 70 void *conf); |
71 static ngx_int_t ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s); | |
70 | 72 |
71 #if (NGX_STREAM_SSL) | 73 #if (NGX_STREAM_SSL) |
72 | 74 |
73 static char *ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf, | 75 static char *ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf, |
74 ngx_command_t *cmd, void *conf); | 76 ngx_command_t *cmd, void *conf); |
152 { ngx_string("proxy_next_upstream_timeout"), | 154 { ngx_string("proxy_next_upstream_timeout"), |
153 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, | 155 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, |
154 ngx_conf_set_msec_slot, | 156 ngx_conf_set_msec_slot, |
155 NGX_STREAM_SRV_CONF_OFFSET, | 157 NGX_STREAM_SRV_CONF_OFFSET, |
156 offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_timeout), | 158 offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_timeout), |
159 NULL }, | |
160 | |
161 { ngx_string("proxy_protocol"), | |
162 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, | |
163 ngx_conf_set_flag_slot, | |
164 NGX_STREAM_SRV_CONF_OFFSET, | |
165 offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol), | |
157 NULL }, | 166 NULL }, |
158 | 167 |
159 #if (NGX_STREAM_SSL) | 168 #if (NGX_STREAM_SSL) |
160 | 169 |
161 { ngx_string("proxy_ssl"), | 170 { ngx_string("proxy_ssl"), |
326 && u->peer.tries > pscf->next_upstream_tries) | 335 && u->peer.tries > pscf->next_upstream_tries) |
327 { | 336 { |
328 u->peer.tries = pscf->next_upstream_tries; | 337 u->peer.tries = pscf->next_upstream_tries; |
329 } | 338 } |
330 | 339 |
340 u->proxy_protocol = pscf->proxy_protocol; | |
341 | |
331 p = ngx_pnalloc(c->pool, pscf->downstream_buf_size); | 342 p = ngx_pnalloc(c->pool, pscf->downstream_buf_size); |
332 if (p == NULL) { | 343 if (p == NULL) { |
333 ngx_stream_proxy_finalize(s, NGX_ERROR); | 344 ngx_stream_proxy_finalize(s, NGX_ERROR); |
334 return; | 345 return; |
335 } | 346 } |
339 u->downstream_buf.pos = p; | 350 u->downstream_buf.pos = p; |
340 u->downstream_buf.last = p; | 351 u->downstream_buf.last = p; |
341 | 352 |
342 c->write->handler = ngx_stream_proxy_downstream_handler; | 353 c->write->handler = ngx_stream_proxy_downstream_handler; |
343 c->read->handler = ngx_stream_proxy_downstream_handler; | 354 c->read->handler = ngx_stream_proxy_downstream_handler; |
355 | |
356 if (u->proxy_protocol | |
357 #if (NGX_STREAM_SSL) | |
358 && pscf->ssl == NULL | |
359 #endif | |
360 && pscf->downstream_buf_size >= NGX_PROXY_PROTOCOL_MAX_HEADER | |
361 ) | |
362 { | |
363 /* optimization for a typical case */ | |
364 | |
365 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, | |
366 "stream proxy send PROXY protocol header"); | |
367 | |
368 p = ngx_proxy_protocol_write(c, u->downstream_buf.last, | |
369 u->downstream_buf.end); | |
370 if (p == NULL) { | |
371 ngx_stream_proxy_finalize(s, NGX_ERROR); | |
372 return; | |
373 } | |
374 | |
375 u->downstream_buf.last = p; | |
376 u->proxy_protocol = 0; | |
377 } | |
344 | 378 |
345 if (ngx_stream_proxy_process(s, 0, 0) != NGX_OK) { | 379 if (ngx_stream_proxy_process(s, 0, 0) != NGX_OK) { |
346 return; | 380 return; |
347 } | 381 } |
348 | 382 |
415 ngx_connection_t *c, *pc; | 449 ngx_connection_t *c, *pc; |
416 ngx_log_handler_pt handler; | 450 ngx_log_handler_pt handler; |
417 ngx_stream_upstream_t *u; | 451 ngx_stream_upstream_t *u; |
418 ngx_stream_proxy_srv_conf_t *pscf; | 452 ngx_stream_proxy_srv_conf_t *pscf; |
419 | 453 |
454 u = s->upstream; | |
455 | |
456 if (u->proxy_protocol) { | |
457 if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { | |
458 return; | |
459 } | |
460 | |
461 u->proxy_protocol = 0; | |
462 } | |
463 | |
420 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); | 464 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); |
421 | |
422 u = s->upstream; | |
423 | 465 |
424 pc = u->peer.connection; | 466 pc = u->peer.connection; |
425 | 467 |
426 #if (NGX_STREAM_SSL) | 468 #if (NGX_STREAM_SSL) |
427 if (pscf->ssl && pc->ssl == NULL) { | 469 if (pscf->ssl && pc->ssl == NULL) { |
469 if (ngx_stream_proxy_process(s, 1, 0) != NGX_OK) { | 511 if (ngx_stream_proxy_process(s, 1, 0) != NGX_OK) { |
470 return; | 512 return; |
471 } | 513 } |
472 | 514 |
473 ngx_stream_proxy_process(s, 0, 1); | 515 ngx_stream_proxy_process(s, 0, 1); |
516 } | |
517 | |
518 | |
519 static ngx_int_t | |
520 ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s) | |
521 { | |
522 u_char *p; | |
523 ssize_t n, size; | |
524 ngx_connection_t *c, *pc; | |
525 ngx_stream_upstream_t *u; | |
526 ngx_stream_proxy_srv_conf_t *pscf; | |
527 u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; | |
528 | |
529 c = s->connection; | |
530 | |
531 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, | |
532 "stream proxy send PROXY protocol header"); | |
533 | |
534 p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER); | |
535 if (p == NULL) { | |
536 ngx_stream_proxy_finalize(s, NGX_ERROR); | |
537 return NGX_ERROR; | |
538 } | |
539 | |
540 u = s->upstream; | |
541 | |
542 pc = u->peer.connection; | |
543 | |
544 size = p - buf; | |
545 | |
546 n = pc->send(pc, buf, size); | |
547 | |
548 if (n == NGX_AGAIN) { | |
549 if (ngx_handle_write_event(pc->write, 0) != NGX_OK) { | |
550 ngx_stream_proxy_finalize(s, NGX_ERROR); | |
551 return NGX_ERROR; | |
552 } | |
553 | |
554 pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); | |
555 | |
556 ngx_add_timer(pc->write, pscf->timeout); | |
557 | |
558 pc->write->handler = ngx_stream_proxy_connect_handler; | |
559 | |
560 return NGX_AGAIN; | |
561 } | |
562 | |
563 if (n == NGX_ERROR) { | |
564 ngx_stream_proxy_finalize(s, NGX_DECLINED); | |
565 return NGX_ERROR; | |
566 } | |
567 | |
568 if (n != size) { | |
569 | |
570 /* | |
571 * PROXY protocol specification: | |
572 * The sender must always ensure that the header | |
573 * is sent at once, so that the transport layer | |
574 * maintains atomicity along the path to the receiver. | |
575 */ | |
576 | |
577 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
578 "could not send PROXY protocol header at once"); | |
579 | |
580 ngx_stream_proxy_finalize(s, NGX_DECLINED); | |
581 | |
582 return NGX_ERROR; | |
583 } | |
584 | |
585 return NGX_OK; | |
474 } | 586 } |
475 | 587 |
476 | 588 |
477 #if (NGX_STREAM_SSL) | 589 #if (NGX_STREAM_SSL) |
478 | 590 |
1103 conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC; | 1215 conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC; |
1104 conf->downstream_buf_size = NGX_CONF_UNSET_SIZE; | 1216 conf->downstream_buf_size = NGX_CONF_UNSET_SIZE; |
1105 conf->upstream_buf_size = NGX_CONF_UNSET_SIZE; | 1217 conf->upstream_buf_size = NGX_CONF_UNSET_SIZE; |
1106 conf->next_upstream_tries = NGX_CONF_UNSET_UINT; | 1218 conf->next_upstream_tries = NGX_CONF_UNSET_UINT; |
1107 conf->next_upstream = NGX_CONF_UNSET; | 1219 conf->next_upstream = NGX_CONF_UNSET; |
1220 conf->proxy_protocol = NGX_CONF_UNSET; | |
1108 conf->local = NGX_CONF_UNSET_PTR; | 1221 conf->local = NGX_CONF_UNSET_PTR; |
1109 | 1222 |
1110 #if (NGX_STREAM_SSL) | 1223 #if (NGX_STREAM_SSL) |
1111 conf->ssl_enable = NGX_CONF_UNSET; | 1224 conf->ssl_enable = NGX_CONF_UNSET; |
1112 conf->ssl_session_reuse = NGX_CONF_UNSET; | 1225 conf->ssl_session_reuse = NGX_CONF_UNSET; |
1144 ngx_conf_merge_uint_value(conf->next_upstream_tries, | 1257 ngx_conf_merge_uint_value(conf->next_upstream_tries, |
1145 prev->next_upstream_tries, 0); | 1258 prev->next_upstream_tries, 0); |
1146 | 1259 |
1147 ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1); | 1260 ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1); |
1148 | 1261 |
1262 ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0); | |
1263 | |
1149 ngx_conf_merge_ptr_value(conf->local, prev->local, NULL); | 1264 ngx_conf_merge_ptr_value(conf->local, prev->local, NULL); |
1150 | 1265 |
1151 #if (NGX_STREAM_SSL) | 1266 #if (NGX_STREAM_SSL) |
1152 | 1267 |
1153 ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0); | 1268 ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0); |