MQTTs - TLS verification issues

Hi everyone.
Here some context:

  • HaProxy in front of a MQTT Broker
  • Would like to use HaProxy to verify the TLS
  • We are using self-signed root-certificates with ECDSA

My understanding is that both { ssl_c_used } and { ssl_c_verify 0 } are needed (from this topic), but with ssl_c_used any connection fails. HaProxy keeps failing no matter the certificate in use.

I’m feeling that I’m missing something obvious, here the full configuration:

global
    log stdout format raw local0 debug

defaults
    log global
    mode tcp
    option tcplog
    maxconn 1024000
    timeout connect 30000
    timeout client 600s
    timeout server 600s

frontend vernemq_tcp
    tcp-request inspect-delay 5s
    bind *:8883 ssl crt /certs/ca.pem ssl-min-ver TLSv1.2

    use_backend vernemq_tcp_back if { ssl_c_used } { ssl_c_verify 0 }

    default_backend rejected_connections

backend vernemq_tcp_back
    # Create a stick table for session persistence
    stick-table type string len 32 size 100k expire 30m

    # Use ClientID / client_identifier as persistence key
    stick on req.payload(0,0),mqtt_field_value(connect,client_identifier)

    server vernemq vernemq:1883 check

backend rejected_connections
    tcp-request content reject

Let me know if the details are clear.
Any help or hint is appreciated!

Do you mean mutual TLS authentication and Haproxy should verify the certificate provided by the client against your root CA certificate?

That’s as simple as adding to the bind line:

ca-file /path/to/root-ca-file verify required

No ACLs or different backends are needed.

Many thanks lukastribus, I did alter the cfg as follows:

global
    log stdout format raw local0 debug

defaults
    log global
    mode tcp
    option tcplog
    maxconn 1024000
    timeout connect 30000
    timeout client 600s
    timeout server 600s

frontend vernemq_tcp
    bind *:8883 ssl crt /certs ca-file /certs verify required
    use_backend vernemq_tcp_back

    default_backend rejected_connections

backend vernemq_tcp_back
    # Create a stick table for session persistence
    stick-table type string len 32 size 100k expire 30m

    # Use ClientID / client_identifier as persistence key
    stick on req.payload(0,0),mqtt_field_value(connect,client_identifier)

    server vernemq vernemq:1883 check

backend rejected_connections
    tcp-request content reject

If my understanding is correct, having the ca-file on the bind directive will verify the client-certificates while establishing the connection.

If the client certificates are not valid / verified the connection will fail: I would prefer to have more granular control using the ACL, for example to redirect the clients with expired certificates elsewhere.

Would this frontend definition be equivalent with fragment above?

frontend vernemq_tcp
    bind *:8883 ssl crt /certs ca-file /certs verify optional
    use_backend vernemq_tcp_back if { ssl_c_verify 0 }

    default_backend rejected_connections

Yes, ok, you can do that, but I would strongly suggest to do this step by step.

First, make sure you actually get SSL verification working, in the most basic setup possible, which is ca-file /path/to/root-ca-file verify required.

Only when this is working correctly, you downgrade SSL verification to verify optional and then add your custom rules.

No, this is not correct, you need to use ssl_c_used instead.