Tested on: OpenBSD 6.4 - 6.6
I'm moving some of my homelab infrastructure to OpenBSD,
and in the meantime I have to use httpd(8)
behind a reverse proxy.
Issue being: httpd
doesn't support extracting the real IP address from headers
like X-Forwarded-for
, and you can't really log the actual IP of the client.
Granted, I was in control of my reverse-proxy so I could log the info there, but
we can make a nice learning experience out of this 'issue'.
relayd(8) to the rescue!
Since the httpd
's log format cannot be changed, we can stick relayd
in front
of it and use it to log the data we need (see
relayd.conf(5) for more details).
The match ... log
directives can be used to add additional fields to the log.
In this case I wanted to log the Host, Referer, User agent, and reverse proxy
IP. And since relayd only logs connection details by default, I added th url as
well:
webhost="127.0.0.1"
web_port="80"
table <webhosts> {$webhost}
log state changes
log connection
http protocol "httpfilter" {
# Add custom fields to the log:
match header log "Host"
match header log "X-Forwarded-For"
match header log "User-Agent"
match url log
match header log "Referer"
match request header "Host" value "example.com" forward to <webhosts>
}
relay "http" {
listen on 0.0.0.0 port 80
protocol "httpfilter"
forward to <webhosts> port $web_port check tcp interval 60
}
httpd
will of course only see (and log) '127.0.0.1' as the remote host,
although relayd
will happily log everything:
Aug 2 06:01:48 puffy relayd[46936]: relay http, session 27 (1 active), 0, 10.10.4.200 -> 127.0.0.1:80, done, [Host: example.com] [X-Forwarded-For: 10.10.4.1] [User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36] [example.com/] GET;
Aug 2 09:33:11 puffy relayd[19347]: relay http, session 29 (1 active), 0, 10.10.4.200 -> 127.0.0.1:80, done, [Host: example.com] [X-Forwarded-For: 181.101.XXX.XXX] [User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36] [example.com/] GET;
In this case 10.10.4.200
is the reverse proxy, 10.10.4.1
is the local gateway doing hairpin nat for another local network (more about this - maybe later).
Update:
Since OpenBSD 6.6 httpd supports a new log format (forwarded
) so relayd is technically not required (if this is it's only purpose).
So, go to your httpd.conf(5) and replace:
log style common
with:
log style forwarded