diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index f6731e780..ad68720dd 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -10,18 +10,20 @@ #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 +#define NGX_HTTP_REALIP_XREALIP 0 +#define NGX_HTTP_REALIP_XFWD 1 +#define NGX_HTTP_REALIP_HEADER 2 +#define NGX_HTTP_REALIP_PROXY 3 +#define NGX_HTTP_REALIP_EXPRESSION 4 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_array_t *from; /* array of ngx_cidr_t */ + ngx_uint_t type; + ngx_uint_t hash; + ngx_str_t header; + ngx_http_complex_value_t *addresses; + ngx_flag_t recursive; } ngx_http_realip_loc_conf_t; @@ -131,7 +133,7 @@ ngx_http_realip_handler(ngx_http_request_t *r) { u_char *p; size_t len; - ngx_str_t *value; + ngx_str_t *value, addrs_value; ngx_uint_t i, hash; ngx_addr_t addr; ngx_list_part_t *part; @@ -188,6 +190,23 @@ ngx_http_realip_handler(ngx_http_request_t *r) break; + case NGX_HTTP_REALIP_EXPRESSION: + + if (ngx_http_complex_value(r, rlcf->addresses, &addrs_value) + != NGX_OK) + { + return NGX_DECLINED; + } + + if (addrs_value.len == 0) { + return NGX_DECLINED; + } + + value = &addrs_value; + xfwd = NULL; + + break; + default: /* NGX_HTTP_REALIP_HEADER */ part = &r->headers_in.headers.part; @@ -418,7 +437,9 @@ ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_realip_loc_conf_t *rlcf = conf; - ngx_str_t *value; + ngx_str_t *value; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; if (rlcf->type != NGX_CONF_UNSET_UINT) { return "is duplicate"; @@ -441,6 +462,29 @@ ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + rlcf->addresses = ngx_palloc(cf->pool, + sizeof(ngx_http_complex_value_t)); + if (rlcf->addresses == NULL) { + return NGX_CONF_ERROR; + } + + *rlcf->addresses = cv; + rlcf->type = NGX_HTTP_REALIP_EXPRESSION; + + 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]; @@ -465,6 +509,7 @@ ngx_http_realip_create_loc_conf(ngx_conf_t *cf) * conf->from = NULL; * conf->hash = 0; * conf->header = { 0, NULL }; + * conf->addresses = NULL; */ conf->type = NGX_CONF_UNSET_UINT; @@ -492,6 +537,10 @@ ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) conf->header = prev->header; } + if (conf->addresses == NULL) { + conf->addresses = prev->addresses; + } + return NGX_CONF_OK; }