diff src/http/modules/ngx_http_realip_module.c @ 412:b246022ef454 NGINX_0_7_18

nginx 0.7.18 *) Change: the "underscores_in_headers" directive; now nginx does not allows underscores in a client request header line names. *) Feature: the ngx_http_secure_link_module. *) Feature: the "real_ip_header" directive supports any header. *) Feature: the "log_subrequest" directive. *) Feature: the $realpath_root variable. *) Feature: the "http_502" and "http_504" parameters of the "proxy_next_upstream" directive. *) Bugfix: the "http_503" parameter of the "proxy_next_upstream" or "fastcgi_next_upstream" directives did not work. *) Bugfix: nginx might send a "Transfer-Encoding: chunked" heaer line for HEAD requests. *) Bugfix: now accept threshold depends on worker_connections.
author Igor Sysoev <http://sysoev.ru>
date Mon, 13 Oct 2008 00:00:00 +0400
parents 6ebbca3d5ed7
children 76a79816b771
line wrap: on
line diff
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -9,6 +9,11 @@
 #include <ngx_http.h>
 
 
+#define NGX_HTTP_REALIP_XREALIP  0
+#define NGX_HTTP_REALIP_XFWD     1
+#define NGX_HTTP_REALIP_HEADER   2
+
+
 /* AF_INET only */
 
 typedef struct {
@@ -19,7 +24,9 @@ typedef struct {
 
 typedef struct {
     ngx_array_t       *from;     /* array of ngx_http_realip_from_t */
-    ngx_uint_t         xfwd;
+    ngx_uint_t         type;
+    ngx_uint_t         hash;
+    ngx_str_t          header;
 } ngx_http_realip_loc_conf_t;
 
 
@@ -34,19 +41,13 @@ static ngx_int_t ngx_http_realip_handler
 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_init(ngx_conf_t *cf);
 
 
-static ngx_conf_enum_t  ngx_http_realip_header[] = {
-    { ngx_string("X-Forwarded-For"), 1 },
-    { ngx_string("X-Real-IP"), 0 },
-    { ngx_null_string, 0 }
-};
-
-
 static ngx_command_t  ngx_http_realip_commands[] = {
 
     { ngx_string("set_real_ip_from"),
@@ -58,10 +59,10 @@ static ngx_command_t  ngx_http_realip_co
 
     { ngx_string("real_ip_header"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_enum_slot,
+      ngx_http_realip,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_realip_loc_conf_t, xfwd),
-      &ngx_http_realip_header },
+      0,
+      NULL },
 
       ngx_null_command
 };
@@ -105,7 +106,9 @@ ngx_http_realip_handler(ngx_http_request
     u_char                      *ip, *p;
     size_t                       len;
     in_addr_t                    addr;
-    ngx_uint_t                   i;
+    ngx_uint_t                   i, hash;
+    ngx_list_part_t             *part;
+    ngx_table_elt_t             *header;
     struct sockaddr_in          *sin;
     ngx_connection_t            *c;
     ngx_pool_cleanup_t          *cln;
@@ -130,7 +133,10 @@ ngx_http_realip_handler(ngx_http_request
         return NGX_DECLINED;
     }
 
-    if (rlcf->xfwd == 0) {
+    switch (rlcf->type) {
+
+    case NGX_HTTP_REALIP_XREALIP:
+
         if (r->headers_in.x_real_ip == NULL) {
             return NGX_DECLINED;
         }
@@ -138,7 +144,10 @@ ngx_http_realip_handler(ngx_http_request
         len = r->headers_in.x_real_ip->value.len;
         ip = r->headers_in.x_real_ip->value.data;
 
-    } else {
+        break;
+
+    case NGX_HTTP_REALIP_XFWD:
+
         if (r->headers_in.x_forwarded_for == NULL) {
             return NGX_DECLINED;
         }
@@ -154,8 +163,46 @@ ngx_http_realip_handler(ngx_http_request
                 break;
             }
         }
+
+        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 (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)
+            {
+                len = header[i].value.len;
+                ip = header[i].value.data;
+
+                goto found;
+            }
+        }
+
+        return NGX_DECLINED;
     }
 
+found:
+
     c = r->connection;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "realip: \"%s\"", ip);
@@ -231,10 +278,10 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
 {
     ngx_http_realip_loc_conf_t *rlcf = conf;
 
-    ngx_int_t                 rc;
-    ngx_str_t                *value;
-    ngx_inet_cidr_t           in_cidr;
-    ngx_http_realip_from_t   *from;
+    ngx_int_t                rc;
+    ngx_str_t               *value;
+    ngx_inet_cidr_t          in_cidr;
+    ngx_http_realip_from_t  *from;
 
     if (rlcf->from == NULL) {
         rlcf->from = ngx_array_create(cf->pool, 2,
@@ -271,6 +318,33 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
 }
 
 
+static char *
+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;
+
+    value = cf->args->elts;
+
+    if (ngx_strcmp(value[1].data, "X-Real-IP") == 0) {
+        rlcf->type = NGX_HTTP_REALIP_XREALIP;
+        return NGX_CONF_OK;
+    }
+
+    if (ngx_strcmp(value[1].data, "X-Forwarded-For") == 0) {
+        rlcf->type = NGX_HTTP_REALIP_XFWD;
+        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)
 {
@@ -285,9 +359,11 @@ ngx_http_realip_create_loc_conf(ngx_conf
      * set by ngx_pcalloc():
      *
      *     conf->from = NULL;
+     *     conf->hash = 0;
+     *     conf->header = { 0, NULL };
      */
 
-    conf->xfwd = NGX_CONF_UNSET_UINT;
+    conf->type = NGX_CONF_UNSET_UINT;
 
     return conf;
 }
@@ -303,7 +379,12 @@ ngx_http_realip_merge_loc_conf(ngx_conf_
         conf->from = prev->from;
     }
 
-    ngx_conf_merge_uint_value(conf->xfwd, prev->xfwd, 0);
+    ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
+
+    if (conf->header.len == 0) {
+        conf->hash = prev->hash;
+        conf->header = prev->header;
+    }
 
     return NGX_CONF_OK;
 }