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); }