Hi

When I run httpd(8) behind relayd(8) the access log of httpd contains
the IP address of relayd, but not the IP address of the client. I've
tried to match the logs of relayd(8) and httpd(8) using some scripting
and failed.

So I've written a patch for httpd(8). It stores the content of the
X-Forwarded-For header in the third field of the log entry:

www.example.com 192.0.2.99 192.0.2.134 - [11/Nov/2018:09:28:48 ...

Cheers,
Bruno

Index: usr.sbin/httpd/server_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.127
diff -u -p -r1.127 server_http.c
--- usr.sbin/httpd/server_http.c        4 Nov 2018 05:56:45 -0000       1.127
+++ usr.sbin/httpd/server_http.c        11 Nov 2018 08:41:18 -0000
@@ -1632,7 +1632,7 @@ server_log_http(struct client *clt, unsi
        static char              tstamp[64];
        static char              ip[INET6_ADDRSTRLEN];
        time_t                   t;
-       struct kv                key, *agent, *referrer;
+       struct kv                key, *agent, *referrer, *xff;
        struct tm               *tm;
        struct server_config    *srv_conf;
        struct http_descriptor  *desc;
@@ -1642,6 +1642,7 @@ server_log_http(struct client *clt, unsi
        char                    *version = NULL;
        char                    *referrer_v = NULL;
        char                    *agent_v = NULL;
+       char                    *xff_v = NULL;
 
        if ((srv_conf = clt->clt_srv_conf) == NULL)
                return (-1);
@@ -1666,7 +1667,7 @@ server_log_http(struct client *clt, unsi
         *
         * httpd's format is similar to these Apache LogFormats:
         * "%v %h %l %u %t \"%r\" %>s %B"
-        * "%v %h %l %u %t \"%r\" %>s %B \"%{Referer}i\" \"%{User-agent}i\""
+        * "%v %h %a %u %t \"%r\" %>s %B \"%{Referer}i\" \"%{User-agent}i\""
         */
        switch (srv_conf->logformat) {
        case LOG_FORMAT_COMMON:
@@ -1708,6 +1709,11 @@ server_log_http(struct client *clt, unsi
                    agent->kv_value == NULL)
                        agent = NULL;
 
+               key.kv_key = "X-Forwarded-For";
+               if ((xff = kv_find(&desc->http_headers, &key)) != NULL &&
+                   xff->kv_value == NULL)
+                       xff = NULL;
+
                /* Use vis to encode input values from the header */
                if (clt->clt_remote_user &&
                    stravis(&user, clt->clt_remote_user, HTTPD_LOGVIS) == -1)
@@ -1718,6 +1724,9 @@ server_log_http(struct client *clt, unsi
                if (agent &&
                    stravis(&agent_v, agent->kv_value, HTTPD_LOGVIS) == -1)
                        goto done;
+               if (xff &&
+                   stravis(&xff_v, xff->kv_value, HTTPD_LOGVIS) == -1)
+                       goto done;
 
                /* The following should be URL-encoded */
                if (desc->http_path &&
@@ -1728,10 +1737,10 @@ server_log_http(struct client *clt, unsi
                        goto done;
 
                ret = evbuffer_add_printf(clt->clt_log,
-                   "%s %s - %s [%s] \"%s %s%s%s%s%s\""
+                   "%s %s %s %s [%s] \"%s %s%s%s%s%s\""
                    " %03d %zu \"%s\" \"%s\"\n",
-                   srv_conf->name, ip, clt->clt_remote_user == NULL ? "-" :
-                   user, tstamp,
+                   srv_conf->name, ip, xff == NULL ? "-" : xff_v,
+                   clt->clt_remote_user == NULL ? "-" : user, tstamp,
                    server_httpmethod_byid(desc->http_method),
                    desc->http_path == NULL ? "" : path,
                    desc->http_query == NULL ? "" : "?",
@@ -1762,6 +1771,7 @@ done:
        free(version);
        free(referrer_v);
        free(agent_v);
+       free(xff_v);
 
        return (ret);
 }

Reply via email to