Enhancement request for realip module...

Igor Sysoev is at rambler-co.ru
Thu Sep 25 18:58:42 MSD 2008


On Wed, Sep 24, 2008 at 09:36:15PM -0700, mike wrote:

> Is there any way to make the "real_ip_header" accept -any- header,
> instead of only X-Forwarded-For and X-Real-IP?
> 
> I have a site on nginx behind Akamai, and they transmit a
> "True-Client_IP" header with the actual client IP.
> 
> They send X-Forwarded-For as well, but it appears it might not be legitimate.
> 
> I'm thinking this is pretty simple... I assume it's only a couple
> lines of code to change...

The attached patch allows any header in "real_ip_header":

     real_ip_header  True-Client_IP;


-- 
Igor Sysoev
http://sysoev.ru/en/
-------------- next part --------------
Index: src/http/modules/ngx_http_realip_module.c
===================================================================
--- src/http/modules/ngx_http_realip_module.c	(revision 1576)
+++ src/http/modules/ngx_http_realip_module.c	(working copy)
@@ -9,6 +9,10 @@
 #include <ngx_http.h>
 
 
+#define NGX_HTTP_REALIP_XREAL   0
+#define NGX_HTTP_REALIP_XFWD    1
+#define NGX_HTTP_REALIP_HEADER  2
+
 /* AF_INET only */
 
 typedef struct {
@@ -19,7 +23,9 @@
 
 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 +40,13 @@
 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 +58,10 @@
 
     { 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
 };
@@ -106,6 +106,8 @@
     size_t                       len;
     in_addr_t                    addr;
     ngx_uint_t                   i;
+    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 +132,10 @@
         return NGX_DECLINED;
     }
 
-    if (rlcf->xfwd == 0) {
+    switch (rlcf->type) {
+
+    case NGX_HTTP_REALIP_XREAL:
+
         if (r->headers_in.x_real_ip == NULL) {
             return NGX_DECLINED;
         }
@@ -138,7 +143,10 @@
         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 +162,44 @@
                 break;
             }
         }
+
+        break;
+
+    default: /* NGX_HTTP_REALIP_HEADER */
+
+        part = &r->headers_in.headers.part;
+        header = part->elts;
+        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 (rlcf->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 +275,10 @@
 {
     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 +315,33 @@
 }
 
 
+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_XREAL;
+        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 +356,11 @@
      * 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,8 +376,13 @@
         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_XREAL);
 
+    if (conf->header.len == 0) {
+        conf->hash = prev->hash;
+        conf->header = prev->header;
+    }
+
     return NGX_CONF_OK;
 }
 


More information about the nginx mailing list