Mercurial > hg > nginx-quic
diff src/event/ngx_event_connect.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 | 8f038068f4bc |
children | 2c7b488a61fb |
line wrap: on
line diff
--- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -11,6 +11,12 @@ #include <ngx_event_connect.h> +#if (NGX_HAVE_TRANSPARENT_PROXY) +static ngx_int_t ngx_event_connect_set_transparent(ngx_peer_connection_t *pc, + ngx_socket_t s); +#endif + + ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc) { @@ -72,6 +78,15 @@ ngx_event_connect_peer(ngx_peer_connecti } if (pc->local) { + +#if (NGX_HAVE_TRANSPARENT_PROXY) + if (pc->transparent) { + if (ngx_event_connect_set_transparent(pc, s) != NGX_OK) { + goto failed; + } + } +#endif + if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) { ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno, "bind(%V) failed", &pc->local->name); @@ -249,6 +264,94 @@ failed: } +#if (NGX_HAVE_TRANSPARENT_PROXY) + +static ngx_int_t +ngx_event_connect_set_transparent(ngx_peer_connection_t *pc, ngx_socket_t s) +{ + int value; + + value = 1; + +#if defined(SO_BINDANY) + + if (setsockopt(s, SOL_SOCKET, SO_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(SO_BINDANY) failed"); + return NGX_ERROR; + } + +#else + + switch (pc->local->sockaddr->sa_family) { + + case AF_INET: + +#if defined(IP_TRANSPARENT) + + if (setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IP_TRANSPARENT) failed"); + return NGX_ERROR; + } + +#elif defined(IP_BINDANY) + + if (setsockopt(s, IPPROTO_IP, IP_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IP_BINDANY) failed"); + return NGX_ERROR; + } + +#endif + + break; + +#if (NGX_HAVE_INET6) + + case AF_INET6: + +#if defined(IPV6_TRANSPARENT) + + if (setsockopt(s, IPPROTO_IPV6, IPV6_TRANSPARENT, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IPV6_TRANSPARENT) failed"); + return NGX_ERROR; + } + +#elif defined(IPV6_BINDANY) + + if (setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IPV6_BINDANY) failed"); + return NGX_ERROR; + } + +#endif + break; + +#endif /* NGX_HAVE_INET6 */ + + } + +#endif /* SO_BINDANY */ + + return NGX_OK; +} + +#endif + + ngx_int_t ngx_event_get_peer(ngx_peer_connection_t *pc, void *data) {