//home | my other blog | github | twitter | about

httpd/relayd behind a reverse proxy in OpenBSD

Tested on: OpenBSD 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