Author: ru
Date: 2012-05-14 14:00:17 +0000 (Mon, 14 May 2012)
New Revision: 4628
URL: http://trac.nginx.org/nginx/changeset/4628/nginx
Log:
geoip: trusted proxies support and partial IPv6 support.
The module now supports recursive search of client address through the
chain of trusted proxies (closes #100), in the same scope as the geo
module. Proxies are listed by the "geoip_proxy" directive, recursive
search is enabled by the "geoip_proxy_recursive" directive. IPv6 is
partially supported: proxies may be specified with IPv6 addresses.
Example:
geoip_country .../GeoIP.dat;
geoip_proxy 127.0.0.1;
geoip_proxy ::1;
geoip_proxy 10.0.0.0/8;
geoip_proxy_recursive on;
Modified:
trunk/src/http/modules/ngx_http_geoip_module.c
Modified: trunk/src/http/modules/ngx_http_geoip_module.c
===================================================================
--- trunk/src/http/modules/ngx_http_geoip_module.c 2012-05-14 13:53:22 UTC (rev 4627)
+++ trunk/src/http/modules/ngx_http_geoip_module.c 2012-05-14 14:00:17 UTC (rev 4628)
@@ -14,20 +14,24 @@
typedef struct {
- GeoIP *country;
- GeoIP *org;
- GeoIP *city;
+ GeoIP *country;
+ GeoIP *org;
+ GeoIP *city;
+ ngx_array_t *proxies; /* array of ngx_cidr_t */
+ ngx_flag_t proxy_recursive;
} ngx_http_geoip_conf_t;
typedef struct {
- ngx_str_t *name;
- uintptr_t data;
+ ngx_str_t *name;
+ uintptr_t data;
} ngx_http_geoip_var_t;
typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
+static u_long ngx_http_geoip_addr(ngx_http_request_t *r,
+ ngx_http_geoip_conf_t *gcf);
static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
@@ -44,12 +48,17 @@
static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
+static char *ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf);
static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static ngx_int_t ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
+ ngx_cidr_t *cidr);
static void ngx_http_geoip_cleanup(void *data);
@@ -76,6 +85,20 @@
0,
NULL },
+ { ngx_string("geoip_proxy"),
+ NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
+ ngx_http_geoip_proxy,
+ NGX_HTTP_MAIN_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("geoip_proxy_recursive"),
+ NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_MAIN_CONF_OFFSET,
+ offsetof(ngx_http_geoip_conf_t, proxy_recursive),
+ NULL },
+
ngx_null_command
};
@@ -85,7 +108,7 @@
NULL, /* postconfiguration */
ngx_http_geoip_create_conf, /* create main configuration */
- NULL, /* init main configuration */
+ ngx_http_geoip_init_conf, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
@@ -182,40 +205,44 @@
static u_long
-ngx_http_geoip_addr(ngx_http_request_t *r)
+ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
{
- struct sockaddr_in *sin;
-#if (NGX_HAVE_INET6)
- u_char *p;
- u_long addr;
- struct sockaddr_in6 *sin6;
-#endif
+ ngx_addr_t addr;
+ ngx_table_elt_t *xfwd;
+ struct sockaddr_in *sin;
- switch (r->connection->sockaddr->sa_family) {
+ addr.sockaddr = r->connection->sockaddr;
+ addr.socklen = r->connection->socklen;
+ /* addr.name = r->connection->addr_text; */
- case AF_INET:
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- return ntohl(sin->sin_addr.s_addr);
+ xfwd = r->headers_in.x_forwarded_for;
+ if (xfwd != NULL && gcf->proxies != NULL) {
+ (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
+ xfwd->value.len, gcf->proxies,
+ gcf->proxy_recursive);
+ }
+
#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+ if (addr.sockaddr->sa_family == AF_INET6) {
+ struct in6_addr *inaddr6;
- if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
- p = sin6->sin6_addr.s6_addr;
- addr = p[12] << 24;
- addr += p[13] << 16;
- addr += p[14] << 8;
- addr += p[15];
+ inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
- return addr;
+ if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
+ return ntohl(*(in_addr_t *) &inaddr6->s6_addr[12]);
}
+ }
#endif
+
+ if (addr.sockaddr->sa_family != AF_INET) {
+ return INADDR_NONE;
}
- return INADDR_NONE;
+ sin = (struct sockaddr_in *) addr.sockaddr;
+ return ntohl(sin->sin_addr.s_addr);
}
@@ -235,7 +262,7 @@
goto not_found;
}
- val = handler(gcf->country, ngx_http_geoip_addr(r));
+ val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
if (val == NULL) {
goto not_found;
@@ -273,7 +300,7 @@
goto not_found;
}
- val = handler(gcf->org, ngx_http_geoip_addr(r));
+ val = handler(gcf->org, ngx_http_geoip_addr(r, gcf));
if (val == NULL) {
goto not_found;
@@ -453,7 +480,7 @@
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
if (gcf->city) {
- return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r));
+ return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
}
return NULL;
@@ -490,6 +517,8 @@
return NULL;
}
+ conf->proxy_recursive = NGX_CONF_UNSET;
+
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NULL;
@@ -503,6 +532,17 @@
static char *
+ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf)
+{
+ ngx_http_geoip_conf_t *gcf = conf;
+
+ ngx_conf_init_value(gcf->proxy_recursive, 0);
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_geoip_conf_t *gcf = conf;
@@ -652,6 +692,66 @@
}
+static char *
+ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_geoip_conf_t *gcf = conf;
+
+ ngx_str_t *value;
+ ngx_cidr_t cidr, *c;
+
+ value = cf->args->elts;
+
+ if (ngx_http_geoip_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (gcf->proxies == NULL) {
+ gcf->proxies = ngx_array_create(cf->pool, 4, sizeof(ngx_cidr_t));
+ if (gcf->proxies == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ c = ngx_array_push(gcf->proxies);
+ if (c == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *c = cidr;
+
+ return NGX_CONF_OK;
+}
+
+static ngx_int_t
+ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
+{
+ ngx_int_t rc;
+
+ if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
+ cidr->family = AF_INET;
+ cidr->u.in.addr = 0xffffffff;
+ cidr->u.in.mask = 0xffffffff;
+
+ return NGX_OK;
+ }
+
+ rc = ngx_ptocidr(net, cidr);
+
+ if (rc == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
+ return NGX_ERROR;
+ }
+
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless", net);
+ }
+
+ return NGX_OK;
+}
+
+
static void
ngx_http_geoip_cleanup(void *data)
{
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel