How to capture samples in haproxy for logging

haproxy

I would like to add additional logging with samples from the TLS connection details in particular. I'm running haproxy v2.0 and for the life of me cannot figure out how to capture anything except some request headers. Based on the docs for http-request capture (emphasis mine):

http-request capture [ len | id ]
[ { if | unless } ]

This captures sample expression from the request buffer, and
converts it to a string of at most characters. The resulting
string is stored into the next request "capture" slot, so it will
possibly appear next to some captured HTTP headers. It will then
automatically appear in the logs, and it will be possible to extract
it using sample fetch rules to feed it into headers or anything. The
length should be limited given that this size will be allocated for
each capture during the whole session life. Please check section 7.3
(Fetching samples) and "capture request header" for more information.

One will note, the entire 7.3 section lists many, many kinds of samples/fetches that are available. So I would expect something like the following using some random layer 5 fetch to work:

frontend https
   bind :443 accept-proxy alpn h2,http/1.1 ssl crt-list /usr/local/etc/haproxy/https.cfg
   log-format "... %hr %hs ..."

   # Inform our downstreams of the client connection deets
   http-request set-header X-SSL-Version %{+Q}[sslv]

   # Add some additional logging infromation 
   # errors: unknown fetch method 'sslv'
   http-request capture sslc len 64  # ECDHE-ECDSA-AES256-GCM-SHA384
   # errors: unknown fetch method '%[sslv]'
   http-request capture %[sslc] len 64  # ECDHE-ECDSA-AES256-GCM-SHA384
   # works
   http-request capture req.hdr(Host) len 253 # foo.example.com

What I expect to happen is to get log line something like:

... {ECDHE-ECDSA-AES256-GCM-SHA384|foo.example.com} ...

If anyone can point out to me what I'm doing wrong, I'd appreciate it. It feels like I'm "holding it wrong", but I'm simply not seeing it.

Thank you

P.S. I would also love to also know if it's possible to add L5 samples in the case of failed connections such as rejected TLS client connections. An opaque error message like https/1: SSL handshake failure is so terribly difficult to diagnose.

Best Answer

Neither sslc nor sslv seem to be listed as fetches in section 7.3. They're probably log formatting macros or something. You have to use a fetch with http-request capture, rather than a log variable.

The SSL/TLS cipher used is ssl_fc_cipher (assuming you want the client's cipher). The version is ssl_fc_protocol... but the docs are horrible and the only way I confirmed this was a blog post by HAProxy Technologies about how you can check if you're vulnerable to POODLE.

In other words, you need to do this:

http-request capture ssl_fc_protocol len 8
http-request capture ssl_fc_cipher len 64

I don't think it's possible to get a better error message than what it's giving you though, because that's just OpenSSL being as unhelpful as usual.