mirror of
https://github.com/nginx/nginx.git
synced 2024-11-25 10:20:21 -06:00
IP_TRANSPARENT support for listening sockets
This patch adds support for IP_TRANSPARENT support for listening sockets in the http module and stream module. Adding `transparent` to ths options of a listen directive, IP_TRANSPARENT will be enabled on that listening socket, allowing it to accept traffic redirected using TPROXY. When this is enabled, the original destination IP address and port before the redirection can be fetched from the variables $server_addr and $server_port. The original version of this patch was proposed by Stijn Tintel in <https://trac.nginx.org/nginx/ticket/287>. Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
This commit is contained in:
parent
f45c2707ea
commit
9cdc0982a5
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user