comparison src/stream/ngx_stream_proxy_module.c @ 6530:1d0e03db9f8e

Upstream: the "transparent" parameter of proxy_bind and friends. This parameter lets binding the proxy connection to a non-local address. Upstream will see the connection as coming from that address. When used with $remote_addr, upstream will accept the connection from real client address. Example: proxy_bind $remote_addr transparent;
author Roman Arutyunyan <arut@nginx.com>
date Fri, 18 Dec 2015 19:05:27 +0300
parents cb8177ca0990
children 04d8d1f85649
comparison
equal deleted inserted replaced
6529:cb8177ca0990 6530:1d0e03db9f8e
10 #include <ngx_stream.h> 10 #include <ngx_stream.h>
11 11
12 12
13 typedef struct { 13 typedef struct {
14 ngx_addr_t *addr; 14 ngx_addr_t *addr;
15 #if (NGX_HAVE_TRANSPARENT_PROXY)
16 ngx_uint_t transparent; /* unsigned transparent:1; */
17 #endif
15 } ngx_stream_upstream_local_t; 18 } ngx_stream_upstream_local_t;
16 19
17 20
18 typedef struct { 21 typedef struct {
19 ngx_msec_t connect_timeout; 22 ngx_msec_t connect_timeout;
118 NGX_STREAM_SRV_CONF_OFFSET, 121 NGX_STREAM_SRV_CONF_OFFSET,
119 0, 122 0,
120 NULL }, 123 NULL },
121 124
122 { ngx_string("proxy_bind"), 125 { ngx_string("proxy_bind"),
123 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, 126 NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE12,
124 ngx_stream_proxy_bind, 127 ngx_stream_proxy_bind,
125 NGX_STREAM_SRV_CONF_OFFSET, 128 NGX_STREAM_SRV_CONF_OFFSET,
126 0, 129 0,
127 NULL }, 130 NULL },
128 131
441 444
442 static ngx_int_t 445 static ngx_int_t
443 ngx_stream_proxy_set_local(ngx_stream_session_t *s, ngx_stream_upstream_t *u, 446 ngx_stream_proxy_set_local(ngx_stream_session_t *s, ngx_stream_upstream_t *u,
444 ngx_stream_upstream_local_t *local) 447 ngx_stream_upstream_local_t *local)
445 { 448 {
449 ngx_addr_t *addr;
450 ngx_connection_t *c;
451 struct sockaddr_in *sin;
452 #if (NGX_HAVE_INET6)
453 struct sockaddr_in6 *sin6;
454 #endif
455
446 if (local == NULL) { 456 if (local == NULL) {
447 u->peer.local = NULL; 457 u->peer.local = NULL;
448 return NGX_OK; 458 return NGX_OK;
449 } 459 }
450 460
461 #if (NGX_HAVE_TRANSPARENT_PROXY)
462 u->peer.transparent = local->transparent;
463 #endif
464
451 if (local->addr) { 465 if (local->addr) {
452 u->peer.local = local->addr; 466 u->peer.local = local->addr;
453 return NGX_OK; 467 return NGX_OK;
454 } 468 }
469
470 /* $remote_addr */
471
472 c = s->connection;
473
474 addr = ngx_palloc(c->pool, sizeof(ngx_addr_t));
475 if (addr == NULL) {
476 return NGX_ERROR;
477 }
478
479 addr->socklen = c->socklen;
480
481 addr->sockaddr = ngx_palloc(c->pool, addr->socklen);
482 if (addr->sockaddr == NULL) {
483 return NGX_ERROR;
484 }
485
486 ngx_memcpy(addr->sockaddr, c->sockaddr, c->socklen);
487
488 switch (addr->sockaddr->sa_family) {
489
490 case AF_INET:
491 sin = (struct sockaddr_in *) addr->sockaddr;
492 sin->sin_port = 0;
493 break;
494
495 #if (NGX_HAVE_INET6)
496 case AF_INET6:
497 sin6 = (struct sockaddr_in6 *) addr->sockaddr;
498 sin6->sin6_port = 0;
499 break;
500 #endif
501 }
502
503 addr->name = c->addr_text;
504 u->peer.local = addr;
455 505
456 return NGX_OK; 506 return NGX_OK;
457 } 507 }
458 508
459 509
1674 return "is duplicate"; 1724 return "is duplicate";
1675 } 1725 }
1676 1726
1677 value = cf->args->elts; 1727 value = cf->args->elts;
1678 1728
1679 if (ngx_strcmp(value[1].data, "off") == 0) { 1729 if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "off") == 0) {
1680 pscf->local = NULL; 1730 pscf->local = NULL;
1681 return NGX_CONF_OK; 1731 return NGX_CONF_OK;
1682 } 1732 }
1683 1733
1684 local = ngx_palloc(cf->pool, sizeof(ngx_stream_upstream_local_t)); 1734 local = ngx_palloc(cf->pool, sizeof(ngx_stream_upstream_local_t));
1686 return NGX_CONF_ERROR; 1736 return NGX_CONF_ERROR;
1687 } 1737 }
1688 1738
1689 pscf->local = local; 1739 pscf->local = local;
1690 1740
1691 local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t)); 1741 if (ngx_strcmp(value[1].data, "$remote_addr") != 0) {
1692 if (local->addr == NULL) { 1742 local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
1693 return NGX_CONF_ERROR; 1743 if (local->addr == NULL) {
1694 } 1744 return NGX_CONF_ERROR;
1695 1745 }
1696 rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len); 1746
1697 1747 rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len);
1698 switch (rc) { 1748
1699 case NGX_OK: 1749 switch (rc) {
1700 local->addr->name = value[1]; 1750 case NGX_OK:
1701 break; 1751 local->addr->name = value[1];
1702 1752 break;
1703 case NGX_DECLINED: 1753
1704 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1754 case NGX_DECLINED:
1705 "invalid address \"%V\"", &value[1]); 1755 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1706 /* fall through */ 1756 "invalid address \"%V\"", &value[1]);
1707 1757 /* fall through */
1708 default: 1758
1709 return NGX_CONF_ERROR; 1759 default:
1760 return NGX_CONF_ERROR;
1761 }
1762 }
1763
1764 if (cf->args->nelts > 2) {
1765 if (ngx_strcmp(value[2].data, "transparent") == 0) {
1766 #if (NGX_HAVE_TRANSPARENT_PROXY)
1767 local->transparent = 1;
1768
1769 #else
1770 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1771 "transparent proxying is not supported "
1772 "on this platform, ignored");
1773 #endif
1774 } else {
1775 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1776 "invalid parameter \"%V\"", &value[2]);
1777 return NGX_CONF_ERROR;
1778 }
1710 } 1779 }
1711 1780
1712 return NGX_CONF_OK; 1781 return NGX_CONF_OK;
1713 } 1782 }