Hi,

I've completely reworked my patch for httpd(8). The last patch broke the
log format combined. And the config option was ugly. This time I've
added another log format called forwarded. It appends two fields to the
log format combined: The first field contains the value of the header
X-Forwarded-For and the second one the value of X-Forwarded-Port. If
either of the headers is empty or missing a dash (-) is written.

The new log format is compatible with log analyzing tools like Webalizer
or GoAccess. If you run httpd(8) behind a proxy like relayd(8) the new
log format finally gives you a way to track the origin of the requests.

Cheers,
Bruno

Index: usr.sbin/httpd/httpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.conf.5,v
retrieving revision 1.103
diff -u -p -r1.103 httpd.conf.5
--- usr.sbin/httpd/httpd.conf.5 19 Feb 2019 11:37:26 -0000      1.103
+++ usr.sbin/httpd/httpd.conf.5 27 Feb 2019 15:26:48 -0000
@@ -450,7 +450,8 @@ The
 .Ar style
 can be
 .Cm common ,
-.Cm combined
+.Cm combined ,
+.Cm forwarded
 or
 .Cm connection .
 The styles
@@ -459,6 +460,14 @@ and
 .Cm combined
 write a log entry after each request similar to the standard Apache
 and nginx access log formats.
+The style
+.Cm forwarded
+extends the style
+.Cm combined
+by appending two fields containing the values of the headers
+.Ar X-Forwarded-For
+and
+.Ar X-Forwarded-Port .
 The style
 .Cm connection
 writes a summarized log entry after each connection,
Index: usr.sbin/httpd/httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.143
diff -u -p -r1.143 httpd.h
--- usr.sbin/httpd/httpd.h      19 Feb 2019 11:37:26 -0000      1.143
+++ usr.sbin/httpd/httpd.h      27 Feb 2019 15:26:48 -0000
@@ -437,7 +437,8 @@ SPLAY_HEAD(client_tree, client);
 enum log_format {
        LOG_FORMAT_COMMON,
        LOG_FORMAT_COMBINED,
-       LOG_FORMAT_CONNECTION
+       LOG_FORMAT_CONNECTION,
+       LOG_FORMAT_FORWARDED
 };
 
 struct log_file {
Index: usr.sbin/httpd/parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/parse.y,v
retrieving revision 1.110
diff -u -p -r1.110 parse.y
--- usr.sbin/httpd/parse.y      19 Feb 2019 11:37:26 -0000      1.110
+++ usr.sbin/httpd/parse.y      27 Feb 2019 15:26:48 -0000
@@ -140,7 +140,7 @@ typedef struct {
 %token PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TICKET
 %token TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST
 %token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE
-%token CA CLIENT CRL OPTIONAL PARAM
+%token CA CLIENT CRL OPTIONAL PARAM FORWARDED
 %token <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.port>        port
@@ -1024,6 +1024,11 @@ logstyle : COMMON                {
                        srv_conf->flags |= SRVFLAG_LOG;
                        srv_conf->logformat = LOG_FORMAT_CONNECTION;
                }
+               | FORWARDED             {
+                       srv_conf->flags &= ~SRVFLAG_NO_LOG;
+                       srv_conf->flags |= SRVFLAG_LOG;
+                       srv_conf->logformat = LOG_FORMAT_FORWARDED;
+               }
                ;
 
 filter         : block RETURN NUMBER optstring {
@@ -1295,6 +1300,7 @@ lookup(char *s)
                { "ecdhe",              ECDHE },
                { "error",              ERR },
                { "fastcgi",            FCGI },
+               { "forwarded",          FORWARDED },
                { "hsts",               HSTS },
                { "include",            INCLUDE },
                { "index",              INDEX },
Index: usr.sbin/httpd/server_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.129
diff -u -p -r1.129 server_http.c
--- usr.sbin/httpd/server_http.c        10 Feb 2019 13:41:27 -0000      1.129
+++ usr.sbin/httpd/server_http.c        27 Feb 2019 15:26:49 -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, *xfp;
        struct tm               *tm;
        struct server_config    *srv_conf;
        struct http_descriptor  *desc;
@@ -1642,6 +1642,8 @@ server_log_http(struct client *clt, unsi
        char                    *version = NULL;
        char                    *referrer_v = NULL;
        char                    *agent_v = NULL;
+       char                    *xff_v = NULL;
+       char                    *xfp_v = NULL;
 
        if ((srv_conf = clt->clt_srv_conf) == NULL)
                return (-1);
@@ -1698,6 +1700,7 @@ server_log_http(struct client *clt, unsi
                break;
 
        case LOG_FORMAT_COMBINED:
+       case LOG_FORMAT_FORWARDED:
                key.kv_key = "Referer"; /* sic */
                if ((referrer = kv_find(&desc->http_headers, &key)) != NULL &&
                    referrer->kv_value == NULL)
@@ -1734,9 +1737,9 @@ server_log_http(struct client *clt, unsi
                    (referrer_v = url_encode(referrer->kv_value)) == NULL)
                        goto done;
 
-               ret = evbuffer_add_printf(clt->clt_log,
+               if ((ret = evbuffer_add_printf(clt->clt_log,
                    "%s %s - %s [%s] \"%s %s%s%s%s%s\""
-                   " %03d %zu \"%s\" \"%s\"\n",
+                   " %03d %zu \"%s\" \"%s\"",
                    srv_conf->name, ip, user == NULL ? "-" :
                    user, tstamp,
                    server_httpmethod_byid(desc->http_method),
@@ -1747,7 +1750,38 @@ server_log_http(struct client *clt, unsi
                    desc->http_version == NULL ? "" : version,
                    code, len,
                    referrer == NULL ? "" : referrer_v,
-                   agent == NULL ? "" : agent_v);
+                   agent == NULL ? "" : agent_v)) == -1)
+                       break;
+
+               if (srv_conf->logformat == LOG_FORMAT_COMBINED)
+                       goto finish;
+
+               xff = xfp = NULL;
+
+               key.kv_key = "X-Forwarded-For";
+               if ((xff = kv_find(&desc->http_headers, &key)) != NULL
+                   && xff->kv_value == NULL)
+                       xff = NULL;
+
+               if (xff &&
+                   stravis(&xff_v, xff->kv_value, HTTPD_LOGVIS) == -1)
+                       goto finish;
+
+               key.kv_key = "X-Forwarded-Port";
+               if ((xfp = kv_find(&desc->http_headers, &key)) != NULL
+                  && xfp->kv_value == NULL)
+                       xfp = NULL;
+
+               if (xfp &&
+                   stravis(&xfp_v, xfp->kv_value, HTTPD_LOGVIS) == -1)
+                       goto finish;
+
+               if ((ret = evbuffer_add_printf(clt->clt_log, " %s %s",
+                   xff == NULL ? "-" : xff_v,
+                   xfp == NULL ? "-" : xfp_v)) == -1)
+                       break;
+finish:
+               ret = evbuffer_add_printf(clt->clt_log, "\n");
 
                break;
 
@@ -1769,6 +1803,8 @@ done:
        free(version);
        free(referrer_v);
        free(agent_v);
+       free(xff_v);
+       free(xfp_v);
 
        return (ret);
 }

Reply via email to