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);