Added optional source=<variable> setting to allow lookups on
IPs in custom variables. Defaults to client ip if not set.
This commit is contained in:
parent
2f9ee969c8
commit
9d11f35986
2 changed files with 85 additions and 29 deletions
|
@ -46,7 +46,7 @@ The free GeoLite2 databases are available from [Maxminds website](http://dev.max
|
||||||
http {
|
http {
|
||||||
...
|
...
|
||||||
geoip2 /etc/maxmind-country.mmdb {
|
geoip2 /etc/maxmind-country.mmdb {
|
||||||
$geoip2_data_country_code default=US country iso_code;
|
$geoip2_data_country_code default=US source=$variable_with_ip country iso_code;
|
||||||
$geoip2_data_country_name country names en;
|
$geoip2_data_country_name country names en;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,25 +13,26 @@
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MMDB_s mmdb;
|
MMDB_s mmdb;
|
||||||
MMDB_lookup_result_s result;
|
MMDB_lookup_result_s result;
|
||||||
#if (NGX_HAVE_INET6)
|
#if (NGX_HAVE_INET6)
|
||||||
uint8_t address[16];
|
uint8_t address[16];
|
||||||
#else
|
#else
|
||||||
unsigned long address;
|
unsigned long address;
|
||||||
#endif
|
#endif
|
||||||
} ngx_http_geoip2_db_t;
|
} ngx_http_geoip2_db_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_array_t *databases;
|
ngx_array_t *databases;
|
||||||
ngx_array_t *proxies;
|
ngx_array_t *proxies;
|
||||||
ngx_flag_t proxy_recursive;
|
ngx_flag_t proxy_recursive;
|
||||||
} ngx_http_geoip2_conf_t;
|
} ngx_http_geoip2_conf_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_http_geoip2_db_t *database;
|
ngx_http_geoip2_db_t *database;
|
||||||
const char **lookup;
|
const char **lookup;
|
||||||
ngx_str_t default_value;
|
ngx_str_t default_value;
|
||||||
|
ngx_http_complex_value_t source;
|
||||||
} ngx_http_geoip2_ctx_t;
|
} ngx_http_geoip2_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,6 +130,7 @@ ngx_http_geoip2_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||||
ngx_addr_t addr;
|
ngx_addr_t addr;
|
||||||
ngx_array_t *xfwd;
|
ngx_array_t *xfwd;
|
||||||
u_char *p;
|
u_char *p;
|
||||||
|
ngx_str_t val;
|
||||||
|
|
||||||
#if (NGX_HAVE_INET6)
|
#if (NGX_HAVE_INET6)
|
||||||
uint8_t address[16], *addressp = address;
|
uint8_t address[16], *addressp = address;
|
||||||
|
@ -136,15 +138,25 @@ ngx_http_geoip2_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||||
unsigned long address;
|
unsigned long address;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip2_module);
|
if (geoip2->source.value.len > 0) {
|
||||||
addr.sockaddr = r->connection->sockaddr;
|
if (ngx_http_complex_value(r, &geoip2->source, &val) != NGX_OK) {
|
||||||
addr.socklen = r->connection->socklen;
|
goto not_found;
|
||||||
|
}
|
||||||
|
|
||||||
xfwd = &r->headers_in.x_forwarded_for;
|
if (ngx_parse_addr(r->pool, &addr, val.data, val.len) != NGX_OK) {
|
||||||
|
goto not_found;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip2_module);
|
||||||
|
addr.sockaddr = r->connection->sockaddr;
|
||||||
|
addr.socklen = r->connection->socklen;
|
||||||
|
|
||||||
if (xfwd->nelts > 0 && gcf->proxies != NULL) {
|
xfwd = &r->headers_in.x_forwarded_for;
|
||||||
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
|
|
||||||
gcf->proxies, gcf->proxy_recursive);
|
if (xfwd->nelts > 0 && gcf->proxies != NULL) {
|
||||||
|
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
|
||||||
|
gcf->proxies, gcf->proxy_recursive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (addr.sockaddr->sa_family) {
|
switch (addr.sockaddr->sa_family) {
|
||||||
|
@ -352,12 +364,11 @@ ngx_http_geoip2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
static char *
|
static char *
|
||||||
ngx_http_geoip2_add_variable(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
ngx_http_geoip2_add_variable(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
||||||
{
|
{
|
||||||
ngx_str_t *value, name;
|
ngx_str_t *value, name, source;
|
||||||
ngx_http_geoip2_ctx_t *geoip2;
|
ngx_http_geoip2_ctx_t *geoip2;
|
||||||
ngx_http_variable_t *var;
|
ngx_http_variable_t *var;
|
||||||
int i, nelts, idx;
|
int i, nelts, idx;
|
||||||
char *prefix = "default=";
|
ngx_http_compile_complex_value_t ccv;
|
||||||
size_t prefix_len = sizeof("default=") - 1;
|
|
||||||
|
|
||||||
geoip2 = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip2_ctx_t));
|
geoip2 = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip2_ctx_t));
|
||||||
if (geoip2 == NULL) {
|
if (geoip2 == NULL) {
|
||||||
|
@ -378,12 +389,57 @@ ngx_http_geoip2_add_variable(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
||||||
nelts = (int) cf->args->nelts;
|
nelts = (int) cf->args->nelts;
|
||||||
idx = 1;
|
idx = 1;
|
||||||
geoip2->database = (ngx_http_geoip2_db_t *) conf;
|
geoip2->database = (ngx_http_geoip2_db_t *) conf;
|
||||||
|
ngx_str_null(&source);
|
||||||
|
|
||||||
if (nelts > idx && value[idx].len >= prefix_len &&
|
if (nelts > idx) {
|
||||||
ngx_strncmp(value[idx].data, prefix, prefix_len) == 0) {
|
for (i = idx; i < nelts; i++) {
|
||||||
geoip2->default_value.len = value[idx].len - prefix_len;
|
if (ngx_strnstr(value[idx].data, "=", value[idx].len) == NULL) {
|
||||||
geoip2->default_value.data = value[idx].data + prefix_len;
|
break;
|
||||||
idx++;
|
}
|
||||||
|
|
||||||
|
if (value[idx].len > 8 && ngx_strncmp(value[idx].data, "default=", 8) == 0) {
|
||||||
|
if (geoip2->default_value.len > 0) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"default has already been declared for \"$%V\"", &name);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
geoip2->default_value.len = value[idx].len - 8;
|
||||||
|
geoip2->default_value.data = value[idx].data + 8;
|
||||||
|
} else if (value[idx].len > 7 && ngx_strncmp(value[idx].data, "source=", 7) == 0) {
|
||||||
|
if (source.len > 0) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"source has already been declared for \"$%V\"", &name);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
source.len = value[idx].len - 7;
|
||||||
|
source.data = value[idx].data + 7;
|
||||||
|
|
||||||
|
if (source.data[0] != '$') {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"invalid source variable name \"%V\"", &source);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||||
|
ccv.cf = cf;
|
||||||
|
ccv.value = &source;
|
||||||
|
ccv.complex_value = &geoip2->source;
|
||||||
|
|
||||||
|
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"unable to compile \"%V\" for \"$%V\"", &source, &name);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"invalid setting \"%V\" for \"$%V\"", &value[idx], &name);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
|
var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
|
||||||
|
|
Loading…
Reference in a new issue