How to get common name from client cert in TLS connection instead of HTTPS


#1

how to get common name from client cert in TLS connection instead of HTTPS. I am using TLS not https and want to get common name from client cert using haproxy 1.6.9 also tried 1.7-dev4 on aws, I am using aws elb+haproxy client certificate ssl and I know use ssl_c_i_dn but how to get/compare the value here is my config: global log 127.0.0.1 local0 maxconn 100000 lua-load /home/ubuntu/a.lua defaults log global mode tcp option tcplog option dontlognull retries 3000 option redispatch timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 100s timeout check 10s maxconn 100000

        frontend fort
        mode tcp
        log 127.0.0.1 local0 debug
        bind *:4443 ssl crt /home/ubuntu/host.pem ca-file /home/ubuntu/ca.crt verify required

        bind *:4443
        use_backend ssl-error unless { ssl_c_verify 0 }
        use_backend mos if { ssl_fc_has_crt }
        default_backend %[lua.c]
        backend mos
        balance leastconn
        mode tcp
        server ip-10-252-1-100 10.252.1.131:2983 check inter 5s fall 3 rise 99999999
        server ip-10-252-1-131 10.252.1.131:1983 check backup

        a.lua
        function c(txn)
        local arg2 = txn.sf:ssl_c_i_dn("dn")
        local arg3 = txn.sf:ssl_f_i_dn("dn")
        core.log(core.info, arg3)
        core.log(core.info, arg2)
            return "mos"
        end
        core.register_fetches("c", c)

#2

HTTPS is TLS, what you mean is TCP mode instead of HTTP.

What do you want to do exactly with the common name of the client certificate?


#3

Hi Lukastribus,

I want to extract the common name of a client certificate in TLS connection and use the extracted ones to match into some tables predefined on server side of our MQTT brokers. The TLS is NOT https since we are only using SSL over TCP instead of HTTP, from mqtt client to communicate 2 way authentication with mqtt brokers.
We have to use something like ELB or Haproxy to avoid the single node failure of the MQTT brokers but it seems Haproxy or ELB does NOT have the ability to forward client certificate from our MQTT client to backend MQTT brokers. I also tried the accept-proxy mode in Haproxy with ELB Proxy pass-through but not work since Haproxy keep complaining something like “Received something which does not look like a PROXY protocol header”, I knew the reason for this but tried both ssl/tcp on ELB side (Elastic Load Balancer on AWS) but still no luck to fix this.

Best regards
Albert


#4

How do your MQTT brokers expect this client certificate to be send? Because if there is no protocol for it, it won’t work anyway, and you can have all the ELB, nginx or haproxy features in the world, but if your MQTT broker isn’t able to read it, it won’t work anyway.

Get clarification on the MQTT side, first of all.

And if mutual TLS authentication is required, why not transparently pass TLS to the backend, instead of terminating it on the haproxy box? Wouldn’t that be easier and still resolve your single node failure problem?


#5

Hi L,

  1. the requirement is extract the common name from the client certificate and check if the common name in some db or backend files to do authenticate, to my best knowledge neither nginx or haproxy could do this (extract the common name from the client cert in TLS), I think they could only do client cert verification but not getting data from the cert.
  2. As I mentioned before why I got “Received something which does not look like a PROXY protocol header” when I do client—(SSL)—> ELB—(SSL)—>HAPROXY (I got this error).

Best regards
Albert
p.s I did make haproxy TLS termination successfully.


#6

You can extract the common name, use ssl_c_i_dn(CN) for that.

So what you want is haproxy to lookup the CN in a database, is that what you are saying? I don’t think that is possible and neither do I think thats a good idea. You would probably stall the whole instance, even if this would be possible with LUA.

Just stop terminating TLS on ELB on Haproxy and pass it transparently to the backend.


#7

Dear Sir/Madam,

  1. Actually I tried something like this in lua but arg2 return empty string (not nil) and is there anything wrong?
    2.what do you mean transparently using about haproxy between elf and backend? client—(TLS)—>ELB—(TLS)—>HAPROXY—(TCP)—>BACKEND?

function check(txn)
local arg2 = txn.sf:ssl_c_i_dn(“dn”)
local arg3 = txn.sf:ssl_f_i_dn(“dn”)
core.log(core.info, arg3)
core.log(core.info, arg2)

    return “mqtt"

end

core.register_fetches("check”, check)

Best regards
Albert


#8

The common name is CN, not dn (common name vs distinguished name). Unless you access the correct parameter, you will never get what you need.

What I mean is: don’t terminate TLS on ELB/haproxy, but use plain TCP mode. You can terminate TLS on your MQTT broker which can do its mutual TLS authentication with the client and the haproxy instance will transparently pass everything back and forth without intercepting TLS, therefor the authentication only has to happen on the MQTT box.


#9

Dear Sir,

Thanks for your update and the CN could return the common name now!
I also read something like using haproxy lua script to call http request then match the common name like the following:
local result, respcode, respheaders, respstatus = http.request {
method = “POST”,
url = “http://example.com/notifyhttp://example.com/notify";,
source = ltn12.source.string(reqbody),
headers = {
[“content-type”] = “text/plain”,
[“content-length”] = tostring(#reqbody)
},
sink = ltn12.sink.table(respbody)
}

  1. How do you think this would work? Need I install some particular plugin for haproxy 1.6.9 (haproxy 1.7 dev4 not working with lua)
  2. same question how to solve this error as I mentioned before, why I got “Received something which does not look like a PROXY protocol header” when I do client—(SSL)—> ELB—(SSL)—>HAPROXY (I got this error). How to solve this?
    My requirement is we have to secure the content from client to haproxy or to elb (but in this case need to also send client cert to haproxy to verify common name)

Best regards
Albert


#10

Don’t know about LUA.
The proxy error happens because you need to enable the proxy protocol on both ends of the connection.

And I would still strongly suggest that you abandon this approach and use a transparent setup instead, which you should be able to setup in a few minutes, other than spending days trying to solve a problem at proxy layer that belongs to the application.


#11

Hi L,

Again the requirement is secure the content from the client to the haproxy or elb at least , if I use haproxy do transparently pass through, then I think the connection from client to elb/haproxy is TCP instead of TLS (SSL)?

Best regards
Albert


#12

No, not at all. It would be end-to-end TLS, where as in this configuration you would terminate TLS on every single layer.


#13

but actually I tried the tcp dump to get the packet and found tcp
am using ssl://haproxy-server:port ssl://haproxy-server:port to init the connection from the client side and I grabbed the packed then got only tcp in plain text WITHOUT any tbs connection.


#14

I don’t know what to tell you, troubleshoot it then. If both your client and your server use TLS, and all the proxies in the middle only forward the TCP payload (no “ssl” keyword in any of the haproxy configurations), then you will see encrypted traffic all the way to the backend.


#15

Hi L,

Also I did the packet capture on haproxy server but only found from client (10.2.1.123) to haproxy is NOT secured but from haproxy to backend (10.252.0.82) is secured, the client is calling ssl://haproxy-server:port ssl://haproxy-server:port

Best regards
Albert


#16

Albert, there is nothing for me to do here. Whether the client is sending encrypted traffic or not, is up to the client, not haproxy.

If you see unencrypted traffic between the client and haproxy, and encrypted traffic between haproxy and the backend, then you also did not configure haproxy as per my instructions (read above: no ssl keywords in the haproxy configuration).


#17

Hi L,

Thanks for your update and I am using client init url as ssl:// haproxy-server:port so client intended to use ssl, also I am a little confused that do you want me to use ssl or not?
Also it seems haproxy only support limit Lua language lib e.g if you use luasocket like socket.http package in lua, it just complains error like could not found the lib but if you use standard lua5.3 or lua5.1 it both work with the same piece of lua code.
what version lua does haproxy 1.6.9 support, need I recompile the haproxy to enable some package support on lua?

Best regards
Albert


#18

I want you to remove all the SSL configuration from haproxy. That way, haproxy will transparently pass SSL from the client to the backend, and you get end-to-end SSL with mutual certificate authentication on your MQTT broker.

If you have any “ssl” keywords in your haproxy configuration, you did it wrong.

You cannot use TCP sockets in LUA afaik.


#19

Hi L,

I mean using socket.http this package (third party lua lib) in haproxy, how could I use that since haproxy seems only support limited lua functions and how to add new lib?

best regards
Albert


#20

You cannot, just like I said.