Repository: go
Issue: crypto/tls: TLS handshake issue with Eclipse Paho MQTT client and RabbitMQ
Labels: NeedsInvestigation

Hi All,

I'm trying to connect to my RabbitMQ broker using the Eclipse Paho MQTT client (go lang version).

I'm using go1.14.6 linux/arm.

My goal is to establish a secure connection with mutual authentication between my Go client and RabbitMQ broker.

I got the following TLS error from the Go client:

panic: Network Error : remote error: tls: handshake failure

I cannot see any relevant logs on my RabitMQ broker:

2020-07-17 16:43:42.936 [debug] <0.17255.19> Supervisor {<0.17255.19>,rabbit_mqtt_connection_sup} started rabbit_mqtt_connection_sup:start_keepalive_link() at pid <0.17256.19>
2020-07-17 16:43:42.936 [debug] <0.17255.19> Supervisor {<0.17255.19>,rabbit_mqtt_connection_sup} started rabbit_mqtt_reader:start_link(<0.17256.19>, {acceptor,{0,0,0,0,0,0,0,0},8883}) at pid <0.17257.19>

Please note that if i use openssl CLI it works fine with the same broker and certificates:

openssl s_client -connect <server-host>:8883 -debug -CAfile /tmp/ca.crt -key /tmp/private-key.crt  -cert /tmp/client-cert.crt

Could you help me to solve this issue? I can share privately rootCA + client cert + private key + server host.

Below the code that i'm using:
#############
# GO CLIENT #
#############

```go
package main

import (
    MQTT "github.com/eclipse/paho.mqtt.golang"
    "fmt"
    "time"
    "io/ioutil"
    "crypto/tls"
    "crypto/x509"
)

var (
    brokerUrl = "ssl://<server-host>:8883"
)

func main() {
    opts := MQTT.NewClientOptions()
    opts.SetClientID("MY-CLIENT-ID")
    opts.AddBroker(brokerUrl)   
    opts.SetPingTimeout(1 * time.Second)
    opts.SetAutoReconnect(true)
    opts.SetCleanSession(true)
    opts.SetKeepAlive(10 * time.Second)
    opts.SetConnectTimeout(10 * time.Second)
    opts.SetTLSConfig(NewTLSConfig())

    client := MQTT.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }

    fmt.Println("Client Connected")
}

func NewTLSConfig() *tls.Config {
    certpool, err := x509.SystemCertPool()
    if err != nil {
        return nil
    }

    pemCert, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        return nil   
    }
   
    certpool.AppendCertsFromPEM(pemCert)
   
    // Import client certificate/key pair
    cert, err := tls.LoadX509KeyPair("client-cert.crt", "private-key.crt.key")
    if err != nil {
        return nil
    }

    // Just to print out the client certificate...
    cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
    if err != nil {
        return nil
    }
   
    // Create tls.Config with desired tls properties
    return &tls.Config{
       
        // RootCAs = certs used to verify server cert.
        RootCAs: certpool,

        // Certificates = list of certs client sends to server.
        Certificates: []tls.Certificate{cert},
       
        PreferServerCipherSuites: true,
       
        CipherSuites: []uint16{
            tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
            tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
            tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
        },
    }
}
```

```python
######################
# RabbitMQ configuration #
######################

{versions, ['tlsv1.2']},
{ciphers,  [
           {ecdhe_ecdsa,aes_256_gcm,aead,sha384}, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ECDHE-RSA-AES256-GCM-SHA384
           {ecdhe_rsa,aes_256_gcm,aead,sha384}, TLS_RSA_WITH_AES_256_GCM_SHA384
           {ecdh_ecdsa,aes_256_gcm,aead,sha384},
           {ecdh_rsa,aes_256_gcm,aead,sha384},
           {dhe_rsa,aes_256_gcm,aead,sha384},
           {dhe_dss,aes_256_gcm,aead,sha384},
           {ecdhe_ecdsa,aes_128_gcm,aead,sha256}, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
           {ecdhe_rsa,aes_128_gcm,aead,sha256}, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
           {ecdh_ecdsa,aes_128_gcm,aead,sha256},
           {ecdh_rsa,aes_128_gcm,aead,sha256},
           {dhe_rsa,aes_128_gcm,aead,sha256},
           {dhe_dss,aes_128_gcm,aead,sha256}
         ]},
{honor_cipher_order,   true},
{honor_ecc_order,      true},
{client_renegotiation, false},
{secure_renegotiate,   true},
{verify,               verify_peer},
{fail_if_no_peer_cert, true}]
```

Thanks in advance,
Dario