HAProxy has many nice features when speaking about SSL, despite SSL has been introduced in it lately.
One of those features is the client side certificate management, which has already been discussed on the blog.
One thing was missing in the article since HAProxy did not have the feature when I first write the article. It is the capability of inserting client certificate information in HTTP headers and reporting them as well in the log line.
Fortunately, the devs at HAProxy Technologies keep on improving HAProxy, and it is now available (well, for some time now, but I did not have any time to write the article yet).
OpenSSL Commands to Generate SSL Certificates
Well, just take the script from HAProxy Technologies github, follow the instruction, and you’ll have an environment setup in a very few seconds.
Here is the script: https://github.com/exceliance/haproxy/tree/master/blog/ssl_client_certificate_management_at_application_level
Configuration
The configuration below shows a frontend and a backend with SSL offloading and with the insertion of client certificate information into HTTP headers. As you can see, this is pretty straight forward.
frontend ft_www
bind 127.0.0.1:8080 name http
bind 127.0.0.1:8081 name https ssl crt ./server.pem ca-file ./ca.crt verify required
log-format %ci:%cp [%t] %ft %b/%s %Tq/%Tw/%Tc/%Tr/%Tt %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs {%[ssl_c_verify],%{+Q}[ssl_c_s_dn],%{+Q}[ssl_c_i_dn]} %{+Q}r
http-request set-header X-SSL %[ssl_fc]
http-request set-header X-SSL-Client-Verify %[ssl_c_verify]
http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn]
http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Issuer %{+Q}[ssl_c_i_dn]
http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore]
http-request set-header X-SSL-Client-NotAfter %{+Q}[ssl_c_notafter]
default_backend bk_www
backend bk_www
cookie SRVID insert nocache
server server1 127.0.0.1:8088 maxconn 1
To observe the result, I just fake a server using netcat and observe the headers sent by HAProxy:
X-SSL: 1
X-SSL-Client-Verify: 0
X-SSL-Client-DN: "/C=FR/ST=Ile de France/L=Jouy en Josas/O=haproxy.com/CN=client1/emailAddress=ba@haproxy.com"
X-SSL-Client-CN: "client1"
X-SSL-Issuer: "/C=FR/ST=Ile de France/L=Jouy en Josas/O=haproxy.com/CN=haproxy.com/emailAddress=ba@haproxy.com"
X-SSL-Client-NotBefore: "130613144555Z"
X-SSL-Client-NotAfter: "140613144555Z"
And the associated log line which has been generated:
Jun 13 18:09:49 localhost haproxy[32385]: 127.0.0.1:38849 [13/Jun/2013:18:09:45.277] ft_www~ bk_www/server1
1643/0/1/-1/4645 504 194 - - sHNN 0/0/0/0/0 0/0
{0,"/C=FR/ST=Ile de France/L=Jouy en Josas/O=haproxy.com/CN=client1/emailAddress=ba@haproxy.com",
"/C=FR/ST=Ile de France/L=Jouy en Josas/O=haproxy.com/CN=haproxy.com/emailAddress=ba@haproxy.com"} "GET /"
I have inserted a few CRLF to make it easily readable.
Now, my HAProxy can deliver the following information to my web server:
ssl_fc: did the client used a secured connection (1) or not (0)
ssl_c_verify: the status code of the TLS/SSL client connection
ssl_c_s_dn: returns the full Distinguished Name of the certificate presented by the client
ssl_c_s_dn(cn): same as above, but extracts only the Common Name
ssl_c_i_dn: full distinguished name of the issuer of the certificate presented by the client
ssl_c_notbefore: start date presented by the client as a formatted string YYMMDDhhmmss
ssl_c_notafter: end date presented by the client as a formatted string YYMMDDhhmmss
Related Articles:
Mitigating the SSL Beast attack using the ALOHA Load-Balancer / HAProxy
How to get SSL with HAProxy getting rid of stunnel, stud, nginx or pound