Mercurial > hg > nginx
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 } |