diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 75809d9ad..912a03aae 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -563,6 +563,22 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) } #endif +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + if (ls[i].transparent) { + int transparent = 1; + + if (setsockopt(s, SOL_IP, IP_TRANSPARENT, + (const void *) &transparent, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "setsockopt(IP_TRANSPARENT) for %V failed, " + "ignored", + &ls[i].addr_text); + } + } +#endif + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ls[i].sockaddr->sa_family == AF_INET6) { diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 84dd80442..de0748953 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -78,6 +78,11 @@ struct ngx_listening_s { unsigned deferred_accept:1; unsigned delete_deferred:1; unsigned add_deferred:1; +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + unsigned transparent:1; +#else + unsigned :1; +#endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) char *accept_filter; #endif diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 27038799d..2119524fc 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -215,8 +215,21 @@ ngx_event_accept(ngx_event_t *ev) c->socklen = socklen; c->listening = ls; +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + if(ls->transparent) { + c->local_sockaddr = NULL; + c->local_socklen = 0; + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { + ngx_close_accepted_connection(c); + return; + } + }else{ +#endif c->local_sockaddr = ls->sockaddr; c->local_socklen = ls->socklen; +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + } +#endif #if (NGX_HAVE_UNIX_DOMAIN) if (c->sockaddr->sa_family == AF_UNIX) { diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index d835f896e..b912434b1 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1850,6 +1850,11 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) ls->sndbuf = addr->opt.sndbuf; ls->keepalive = addr->opt.so_keepalive; + +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + ls->transparent = addr->opt.transparent; +#endif + #if (NGX_HAVE_KEEPALIVE_TUNABLE) ls->keepidle = addr->opt.tcp_keepidle; ls->keepintvl = addr->opt.tcp_keepintvl; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 033a3bf64..9175ecb13 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -4126,6 +4126,17 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } + if (ngx_strcmp(value[n].data, "transparent") == 0) { +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + lsopt.transparent = 1; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "transparent mode is not supported " + "on this platform, ignored"); +#endif + continue; + } + if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) if (ngx_strcmp(&value[n].data[10], "n") == 0) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 765e7ff60..424ee48c1 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -83,6 +83,11 @@ typedef struct { unsigned reuseport:1; unsigned so_keepalive:2; unsigned proxy_protocol:1; +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + unsigned transparent:1; +#else + unsigned :1; +#endif int backlog; int rcvbuf; diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c index b6eeb23af..512fbfa89 100644 --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -1045,6 +1045,10 @@ ngx_stream_add_listening(ngx_conf_t *cf, ngx_stream_conf_addr_t *addr) ls->reuseport = addr->opt.reuseport; #endif +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + ls->transparent = addr->opt.transparent; +#endif + ls->wildcard = addr->opt.wildcard; return ls; diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h index dc05dc5ba..ff0547198 100644 --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -57,6 +57,11 @@ typedef struct { unsigned reuseport:1; unsigned so_keepalive:2; unsigned proxy_protocol:1; +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + unsigned transparent:1; +#else + unsigned :1; +#endif int backlog; int rcvbuf; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index 40951c291..bb2e5c8e6 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -930,6 +930,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) lsopt.ipv6only = 1; #endif +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + lsopt.transparent = 0; +#endif + backlog = 0; for (i = 2; i < cf->args->nelts; i++) { @@ -1033,6 +1037,16 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } + if (ngx_strcmp(value[i].data, "transparent") == 0) { +#if (NGX_HAVE_TRANSPARENT_PROXY && defined IP_TRANSPARENT) + lsopt.transparent = 1; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "transparent mode is not supported " + "on this platform, ignored"); +#endif + continue; + } if (ngx_strncmp(value[i].data, "accept_filter=", 14) == 0) { #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)