If apache is running behind a device which masks the client's IP address with its own, mod_usertrack will use this IP address as part of its cookie_id. Since this is NOT the actual IP address of the client (and may in fact be information best kept private), this behavior could be less than ideal.

Some devices (including a reverse-proxying Apache instance) set HTTP headers which contain the "real" IP address of the request, which might be more appropriate for mod_usertrack.

The attached patch adds the "CookieIPHeader" directive which takes as its only argument the name of the header containing the IP address to use. For example, mod_usertrack could use the IP address passed on my another Apache instance's "ProxyPass" with the following directive:

CookieIPHeader X-Forwarded-For

If the specified header doesn't exist or inet_aton() fails to parse it, the default value (from r->connection) is used instead. Without the directive, apache's behavior is unchanged.

This patch is against the mod_usertrack.c found in 1.3.28.

--
Mike Cramer
http://www.webkist.com/
--- mod_usertrack-orig.c        2003-08-12 14:49:48.000000000 -0400
+++ mod_usertrack.c     2003-08-12 15:51:54.000000000 -0400
@@ -126,6 +126,7 @@
     char *cookie_name;
     char *cookie_domain;
     char *prefix_string;
+    char *cookie_ip_header;
 } cookie_dir_rec;
 
 /* Define this to allow post-2000 cookies. Cookies use two-digit dates,
@@ -161,12 +162,26 @@
 
     long reqtime = (long) r->request_time;
     long clocktime;
+    unsigned long ipaddr = 0;
+    const char *rname = NULL;
 
-    unsigned long ipaddr = ntohl(r->connection->remote_addr.sin_addr.s_addr);
-    const char *rname = ap_get_remote_host(r->connection, r->per_dir_config,
-                                          REMOTE_NAME);
     dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module);
 
+    if (dcfg->cookie_ip_header != NULL) {
+       if (rname = ap_table_get(r->headers_in, dcfg->cookie_ip_header)) {
+            struct in_addr remote_ip_addr;
+            if (inet_aton(rname, &remote_ip_addr))
+               ipaddr = ntohl(remote_ip_addr.s_addr);
+       }
+    }
+
+    if (ipaddr == 0)
+       ipaddr = ntohl(r->connection->remote_addr.sin_addr.s_addr);
+
+    if (rname == NULL)
+       rname = ap_get_remote_host(r->connection, r->per_dir_config,
+                                  REMOTE_NAME);
+
 #if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
 /* We lack gettimeofday(), so we must use time() to obtain the epoch
    seconds, and then times() to obtain CPU clock ticks (milliseconds).
@@ -338,6 +353,7 @@
     dcfg->style = CT_UNSET;
     dcfg->format = CF_NORMAL;
     dcfg->enabled = 0;
+    dcfg->cookie_ip_header = NULL;
     return dcfg;
 }
 
@@ -418,6 +434,14 @@
     return NULL;
 }
 
+static const char *set_cookie_ip(cmd_parms *cmd, void *mconfig, char *name)
+{
+    cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig;
+
+    dcfg->cookie_ip_header = ap_pstrdup(cmd->pool, name);
+    return NULL;
+}
+
 static const char *set_cookie_name(cmd_parms *cmd, void *mconfig, char *name)
 {
     cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig;
@@ -528,6 +552,8 @@
      "'Normal' or 'Compact'"},
     {"CookiePrefix", set_cookie_prefix, NULL, OR_FILEINFO, TAKE1,
      "String prepended to cookie"},
+    {"CookieIPHeader", set_cookie_ip, NULL, OR_FILEINFO, TAKE1,
+     "name of the header to use for client IP"},
     {NULL}
 };
 

Reply via email to