# HG changeset patch # User Dmitry Volyntsev # Date 1472730333 -10800 # Node ID 9cac11efb205595ee82a413ee4513cae92d617ce # Parent b802b7e1d9bc03048ef1530273920e0bd5d679cb Stream: realip module. diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -1007,6 +1007,16 @@ if [ $STREAM != NO ]; then . auto/module fi + if [ $STREAM_REALIP = YES ]; then + ngx_module_name=ngx_stream_realip_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_realip_module.c + ngx_module_libs= + ngx_module_link=$STREAM_REALIP + + . auto/module + fi + if [ $STREAM_LIMIT_CONN = YES ]; then ngx_module_name=ngx_stream_limit_conn_module ngx_module_deps= diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -115,6 +115,7 @@ MAIL_SMTP=YES STREAM=NO STREAM_SSL=NO +STREAM_REALIP=NO STREAM_LIMIT_CONN=YES STREAM_ACCESS=YES STREAM_GEO=YES @@ -296,6 +297,7 @@ use the \"--with-mail_ssl_module\" optio --with-stream) STREAM=YES ;; --with-stream=dynamic) STREAM=DYNAMIC ;; --with-stream_ssl_module) STREAM_SSL=YES ;; + --with-stream_realip_module) STREAM_REALIP=YES ;; --with-stream_geoip_module) STREAM_GEOIP=YES ;; --with-stream_geoip_module=dynamic) STREAM_GEOIP=DYNAMIC ;; @@ -503,6 +505,7 @@ cat << END --with-stream enable TCP/UDP proxy module --with-stream=dynamic enable dynamic TCP/UDP proxy module --with-stream_ssl_module enable ngx_stream_ssl_module + --with-stream_realip_module enable ngx_stream_realip_module --with-stream_geoip_module enable ngx_stream_geoip_module --with-stream_geoip_module=dynamic enable dynamic ngx_stream_geoip_module --without-stream_limit_conn_module disable ngx_stream_limit_conn_module diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -122,6 +122,7 @@ typedef struct { ngx_array_t servers; /* ngx_stream_core_srv_conf_t */ ngx_array_t listen; /* ngx_stream_listen_t */ + ngx_stream_access_pt realip_handler; ngx_stream_access_pt limit_conn_handler; ngx_stream_access_pt access_handler; ngx_stream_access_pt access_log_handler; diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c --- a/src/stream/ngx_stream_handler.c +++ b/src/stream/ngx_stream_handler.c @@ -296,6 +296,15 @@ ngx_stream_init_session_handler(ngx_even cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); + if (cmcf->realip_handler) { + rc = cmcf->realip_handler(s); + + if (rc == NGX_ERROR) { + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; + } + } + if (cmcf->limit_conn_handler) { rc = cmcf->limit_conn_handler(s); diff --git a/src/http/modules/ngx_http_realip_module.c b/src/stream/ngx_stream_realip_module.c copy from src/http/modules/ngx_http_realip_module.c copy to src/stream/ngx_stream_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/stream/ngx_stream_realip_module.c @@ -7,102 +7,69 @@ #include #include -#include - - -#define NGX_HTTP_REALIP_XREALIP 0 -#define NGX_HTTP_REALIP_XFWD 1 -#define NGX_HTTP_REALIP_HEADER 2 -#define NGX_HTTP_REALIP_PROXY 3 +#include typedef struct { ngx_array_t *from; /* array of ngx_cidr_t */ - ngx_uint_t type; - ngx_uint_t hash; - ngx_str_t header; - ngx_flag_t recursive; -} ngx_http_realip_loc_conf_t; +} ngx_stream_realip_srv_conf_t; typedef struct { - ngx_connection_t *connection; struct sockaddr *sockaddr; socklen_t socklen; ngx_str_t addr_text; -} ngx_http_realip_ctx_t; - - -static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r); -static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r, - ngx_addr_t *addr); -static void ngx_http_realip_cleanup(void *data); -static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf); -static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_http_realip_add_variables(ngx_conf_t *cf); -static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf); -static ngx_http_realip_ctx_t *ngx_http_realip_get_module_ctx( - ngx_http_request_t *r); +} ngx_stream_realip_ctx_t; -static ngx_int_t ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_realip_remote_port_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_realip_handler(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_realip_set_addr(ngx_stream_session_t *s, + ngx_addr_t *addr); +static char *ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static void *ngx_stream_realip_create_srv_conf(ngx_conf_t *cf); +static char *ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); +static ngx_int_t ngx_stream_realip_add_variables(ngx_conf_t *cf); +static ngx_int_t ngx_stream_realip_init(ngx_conf_t *cf); -static ngx_command_t ngx_http_realip_commands[] = { +static ngx_int_t ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); + + +static ngx_command_t ngx_stream_realip_commands[] = { { ngx_string("set_real_ip_from"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_http_realip_from, - NGX_HTTP_LOC_CONF_OFFSET, + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_stream_realip_from, + NGX_STREAM_SRV_CONF_OFFSET, 0, NULL }, - { ngx_string("real_ip_header"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_http_realip, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("real_ip_recursive"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_realip_loc_conf_t, recursive), - NULL }, - ngx_null_command }; - -static ngx_http_module_t ngx_http_realip_module_ctx = { - ngx_http_realip_add_variables, /* preconfiguration */ - ngx_http_realip_init, /* postconfiguration */ +static ngx_stream_module_t ngx_stream_realip_module_ctx = { + ngx_stream_realip_add_variables, /* preconfiguration */ + ngx_stream_realip_init, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_http_realip_create_loc_conf, /* create location configuration */ - ngx_http_realip_merge_loc_conf /* merge location configuration */ + ngx_stream_realip_create_srv_conf, /* create server configuration */ + ngx_stream_realip_merge_srv_conf /* merge server configuration */ }; -ngx_module_t ngx_http_realip_module = { +ngx_module_t ngx_stream_realip_module = { NGX_MODULE_V1, - &ngx_http_realip_module_ctx, /* module context */ - ngx_http_realip_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ + &ngx_stream_realip_module_ctx, /* module context */ + ngx_stream_realip_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ @@ -114,176 +81,85 @@ ngx_module_t ngx_http_realip_module = { }; -static ngx_http_variable_t ngx_http_realip_vars[] = { +static ngx_stream_variable_t ngx_stream_realip_vars[] = { { ngx_string("realip_remote_addr"), NULL, - ngx_http_realip_remote_addr_variable, 0, 0, 0 }, + ngx_stream_realip_remote_addr_variable, 0, 0, 0 }, { ngx_string("realip_remote_port"), NULL, - ngx_http_realip_remote_port_variable, 0, 0, 0 }, + ngx_stream_realip_remote_port_variable, 0, 0, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 } }; static ngx_int_t -ngx_http_realip_handler(ngx_http_request_t *r) +ngx_stream_realip_handler(ngx_stream_session_t *s) { - u_char *p; - size_t len; - ngx_str_t *value; - ngx_uint_t i, hash; - ngx_addr_t addr; - ngx_array_t *xfwd; - ngx_list_part_t *part; - ngx_table_elt_t *header; - ngx_connection_t *c; - ngx_http_realip_ctx_t *ctx; - ngx_http_realip_loc_conf_t *rlcf; + ngx_addr_t addr; + ngx_connection_t *c; + ngx_stream_realip_srv_conf_t *rscf; - ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module); + rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_realip_module); - if (ctx) { - return NGX_DECLINED; - } - - rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module); - - if (rlcf->from == NULL) { + if (rscf->from == NULL) { return NGX_DECLINED; } - switch (rlcf->type) { - - case NGX_HTTP_REALIP_XREALIP: - - if (r->headers_in.x_real_ip == NULL) { - return NGX_DECLINED; - } - - value = &r->headers_in.x_real_ip->value; - xfwd = NULL; - - break; - - case NGX_HTTP_REALIP_XFWD: - - xfwd = &r->headers_in.x_forwarded_for; - - if (xfwd->elts == NULL) { - return NGX_DECLINED; - } - - value = NULL; - - break; - - case NGX_HTTP_REALIP_PROXY: - - value = &r->connection->proxy_protocol_addr; - - if (value->len == 0) { - return NGX_DECLINED; - } - - xfwd = NULL; + c = s->connection; - break; - - default: /* NGX_HTTP_REALIP_HEADER */ - - part = &r->headers_in.headers.part; - header = part->elts; - - hash = rlcf->hash; - len = rlcf->header.len; - p = rlcf->header.data; - - for (i = 0; /* void */ ; i++) { + if (c->proxy_protocol_addr.len == 0) { + return NGX_DECLINED; + } - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - header = part->elts; - i = 0; - } - - if (hash == header[i].hash - && len == header[i].key.len - && ngx_strncmp(p, header[i].lowcase_key, len) == 0) - { - value = &header[i].value; - xfwd = NULL; - - goto found; - } - } - + if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) { return NGX_DECLINED; } -found: - - c = r->connection; - - addr.sockaddr = c->sockaddr; - addr.socklen = c->socklen; - /* addr.name = c->addr_text; */ - - if (ngx_http_get_forwarded_addr(r, &addr, xfwd, value, rlcf->from, - rlcf->recursive) - != NGX_DECLINED) + if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol_addr.data, + c->proxy_protocol_addr.len) + != NGX_OK) { - if (rlcf->type == NGX_HTTP_REALIP_PROXY) { - ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); - } - - return ngx_http_realip_set_addr(r, &addr); + return NGX_DECLINED; } - return NGX_DECLINED; + ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); + + return ngx_stream_realip_set_addr(s, &addr); } static ngx_int_t -ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr) +ngx_stream_realip_set_addr(ngx_stream_session_t *s, ngx_addr_t *addr) { - size_t len; - u_char *p; - u_char text[NGX_SOCKADDR_STRLEN]; - ngx_connection_t *c; - ngx_pool_cleanup_t *cln; - ngx_http_realip_ctx_t *ctx; + size_t len; + u_char *p; + u_char text[NGX_SOCKADDR_STRLEN]; + ngx_connection_t *c; + ngx_stream_realip_ctx_t *ctx; - cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t)); - if (cln == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + c = s->connection; + + ctx = ngx_palloc(c->pool, sizeof(ngx_stream_realip_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; } - ctx = cln->data; - - c = r->connection; - len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text, NGX_SOCKADDR_STRLEN, 0); if (len == 0) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } p = ngx_pnalloc(c->pool, len); if (p == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } ngx_memcpy(p, text, len); - cln->handler = ngx_http_realip_cleanup; - ngx_http_set_ctx(r, ctx, ngx_http_realip_module); + ngx_stream_set_ctx(s, ctx, ngx_stream_realip_module); - ctx->connection = c; ctx->sockaddr = c->sockaddr; ctx->socklen = c->socklen; ctx->addr_text = c->addr_text; @@ -297,25 +173,10 @@ ngx_http_realip_set_addr(ngx_http_reques } -static void -ngx_http_realip_cleanup(void *data) +static char * +ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_realip_ctx_t *ctx = data; - - ngx_connection_t *c; - - c = ctx->connection; - - c->sockaddr = ctx->sockaddr; - c->socklen = ctx->socklen; - c->addr_text = ctx->addr_text; -} - - -static char * -ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_realip_loc_conf_t *rlcf = conf; + ngx_stream_realip_srv_conf_t *rscf = conf; ngx_int_t rc; ngx_str_t *value; @@ -323,15 +184,15 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx value = cf->args->elts; - if (rlcf->from == NULL) { - rlcf->from = ngx_array_create(cf->pool, 2, + if (rscf->from == NULL) { + rscf->from = ngx_array_create(cf->pool, 2, sizeof(ngx_cidr_t)); - if (rlcf->from == NULL) { + if (rscf->from == NULL) { return NGX_CONF_ERROR; } } - cidr = ngx_array_push(rlcf->from); + cidr = ngx_array_push(rscf->from); if (cidr == NULL) { return NGX_CONF_ERROR; } @@ -362,48 +223,12 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx } -static char * -ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +static void * +ngx_stream_realip_create_srv_conf(ngx_conf_t *cf) { - ngx_http_realip_loc_conf_t *rlcf = conf; - - ngx_str_t *value; - - if (rlcf->type != NGX_CONF_UNSET_UINT) { - return "is duplicate"; - } - - value = cf->args->elts; - - if (ngx_strcmp(value[1].data, "X-Real-IP") == 0) { - rlcf->type = NGX_HTTP_REALIP_XREALIP; - return NGX_CONF_OK; - } + ngx_stream_realip_srv_conf_t *conf; - if (ngx_strcmp(value[1].data, "X-Forwarded-For") == 0) { - rlcf->type = NGX_HTTP_REALIP_XFWD; - return NGX_CONF_OK; - } - - if (ngx_strcmp(value[1].data, "proxy_protocol") == 0) { - rlcf->type = NGX_HTTP_REALIP_PROXY; - return NGX_CONF_OK; - } - - rlcf->type = NGX_HTTP_REALIP_HEADER; - rlcf->hash = ngx_hash_strlow(value[1].data, value[1].data, value[1].len); - rlcf->header = value[1]; - - return NGX_CONF_OK; -} - - -static void * -ngx_http_realip_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_realip_loc_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_realip_loc_conf_t)); + conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_realip_srv_conf_t)); if (conf == NULL) { return NULL; } @@ -412,46 +237,33 @@ ngx_http_realip_create_loc_conf(ngx_conf * set by ngx_pcalloc(): * * conf->from = NULL; - * conf->hash = 0; - * conf->header = { 0, NULL }; */ - conf->type = NGX_CONF_UNSET_UINT; - conf->recursive = NGX_CONF_UNSET; - return conf; } static char * -ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { - ngx_http_realip_loc_conf_t *prev = parent; - ngx_http_realip_loc_conf_t *conf = child; + ngx_stream_realip_srv_conf_t *prev = parent; + ngx_stream_realip_srv_conf_t *conf = child; if (conf->from == NULL) { conf->from = prev->from; } - ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP); - ngx_conf_merge_value(conf->recursive, prev->recursive, 0); - - if (conf->header.len == 0) { - conf->hash = prev->hash; - conf->header = prev->header; - } - return NGX_CONF_OK; } static ngx_int_t -ngx_http_realip_add_variables(ngx_conf_t *cf) +ngx_stream_realip_add_variables(ngx_conf_t *cf) { - ngx_http_variable_t *var, *v; + ngx_stream_variable_t *var, *v; - for (v = ngx_http_realip_vars; v->name.len; v++) { - var = ngx_http_add_variable(cf, &v->name, v->flags); + for (v = ngx_stream_realip_vars; v->name.len; v++) { + var = ngx_stream_add_variable(cf, &v->name, v->flags); if (var == NULL) { return NGX_ERROR; } @@ -465,68 +277,28 @@ ngx_http_realip_add_variables(ngx_conf_t static ngx_int_t -ngx_http_realip_init(ngx_conf_t *cf) +ngx_stream_realip_init(ngx_conf_t *cf) { - ngx_http_handler_pt *h; - ngx_http_core_main_conf_t *cmcf; - - cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + ngx_stream_core_main_conf_t *cmcf; - h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers); - if (h == NULL) { - return NGX_ERROR; - } - - *h = ngx_http_realip_handler; + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); - h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); - if (h == NULL) { - return NGX_ERROR; - } - - *h = ngx_http_realip_handler; + cmcf->realip_handler = ngx_stream_realip_handler; return NGX_OK; } -static ngx_http_realip_ctx_t * -ngx_http_realip_get_module_ctx(ngx_http_request_t *r) +static ngx_int_t +ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) { - ngx_pool_cleanup_t *cln; - ngx_http_realip_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module); - - if (ctx == NULL && (r->internal || r->filter_finalize)) { - - /* - * if module context was reset, the original address - * can still be found in the cleanup handler - */ + ngx_str_t *addr_text; + ngx_stream_realip_ctx_t *ctx; - for (cln = r->pool->cleanup; cln; cln = cln->next) { - if (cln->handler == ngx_http_realip_cleanup) { - ctx = cln->data; - break; - } - } - } - - return ctx; -} + ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); - -static ngx_int_t -ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_str_t *addr_text; - ngx_http_realip_ctx_t *ctx; - - ctx = ngx_http_realip_get_module_ctx(r); - - addr_text = ctx ? &ctx->addr_text : &r->connection->addr_text; + addr_text = ctx ? &ctx->addr_text : &s->connection->addr_text; v->len = addr_text->len; v->valid = 1; @@ -539,23 +311,23 @@ ngx_http_realip_remote_addr_variable(ngx static ngx_int_t -ngx_http_realip_remote_port_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) +ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) { - ngx_uint_t port; - struct sockaddr *sa; - ngx_http_realip_ctx_t *ctx; + ngx_uint_t port; + struct sockaddr *sa; + ngx_stream_realip_ctx_t *ctx; - ctx = ngx_http_realip_get_module_ctx(r); + ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); - sa = ctx ? ctx->sockaddr : r->connection->sockaddr; + sa = ctx ? ctx->sockaddr : s->connection->sockaddr; v->len = 0; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); + v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1); if (v->data == NULL) { return NGX_ERROR; }