Two-way TLS/SSL with EMQX Cloud, MQTT X, and Let's Encrypt

Overview

EMQX Cloud is the first fully hosted MQTT 5.0 cloud messaging service in the world. With the support of EMQX Cloud, you can create an MQTT cluster on the cloud and use the features of EMQX Enterprise Edition. This allows you to spend more time on business connections and less time for EMQX operation, maintenance, and management.

In this article, we will set up a two-way TLS/SSL authentication for an EMQX Cloud deployment with a third-party certification.

  • Let's Encrypt, a free third-party Certificate Authority, will be used to certify a custom domain purchased from AWS Route 53, which will point to the EMQX Cloud deployment.
  • OpenSSL will be used for client-side TLS/SSL.
  • MQTT X will be used to validate the encrypted connection.

Prerequisites

Create client-side self-signed certificate

Alternatively to the step by step below, instructions can be followed from the EMQX Cloud TLS/SSL documentation.

# Create CA certificate
openssl req -new -newkey rsa:2048 \
    -days 365 -nodes -x509 \
    -subj "/C=US/O=Test Org/CN=Test CA" \
    -keyout client-ca.key -out client-ca.crt

# Create private key
openssl genrsa -out client.key 2048

# Create certificate request file
openssl req -new -key client.key -out client.csr -subj "/CN=Client"

# Create client certifite by feeding the certificate request file to the newly created CA
openssl x509 -req -days 365 -sha256 -in client.csr -CA client-ca.crt -CAkey client-ca.key -CAcreateserial -out client.crt

# View and verify the client certificate
openssl x509 -noout -text -in client.crt
openssl verify -CAfile client-ca.crt client.crt

Point a subdomain to the EMQX Cloud deployment cluster

  1. Copy the EMQX Cloud deployment URL from the EMQX Cloud console.

    Copy the EMQX Cloud deployment URL

  2. Create a CNAME record in AWS Route 53 hosted zone pointing to the EMQX Cloud deployment.

    Create a CNAME record

    Create a CNAME record

Get a certificate for the subdomain

Alternatively to the step by step below, instructions are available from Let's Encrypt/Certbot for certbot and Route 53 plugin. Be sure to select "Other" for the "Software" dropdown, and the "Wildcard" tab.

  1. Install package manager, Certbot, and DNS plugin using the CLI:

    • macOS:

      # Install Homebrew if needed
      /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
      
      # Install certbot with brew
      brew install certbot
      
      # Install DNS plugin (discussion on why Homebrew doesn't work: https://github.com/certbot/certbot/issues/5680)
      $( brew --prefix certbot )/libexec/bin/pip install certbot-dns-route53
      
    • Ubuntu:

      # Install snap if needed
      sudo snap install core; sudo snap refresh core
      
      # Install certbot with snap and configure it
      sudo snap install --classic certbot
      sudo ln -s /snap/bin/certbot /usr/bin/certbot
      sudo snap set certbot trust-plugin-with-root=ok
      
      # Install DNS plugin
      sudo snap install certbot-dns-route53
      
  2. Give AWS permissions to the plugin:

    • Create IAM policy with the following statement, changing YOURHOSTEDZONEID:

      Create IAM policy

      {
          "Version": "2012-10-17",
          "Id": "certbot-dns-route53 policy",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "route53:ListHostedZones",
                      "route53:GetChange"
                  ],
                  "Resource": [
                      "*"
                  ]
              },
              {
                  "Effect" : "Allow",
                  "Action" : [
                      "route53:ChangeResourceRecordSets"
                  ],
                  "Resource" : [
                      "arn:aws:route53:::hostedzone/YOURHOSTEDZONEID"
                  ]
              }
          ]
      }
      
    • Create a new IAM user, attach the new policy to its permissions, and save the Access key ID and Secret access key.

      Create a new IAM user

    • Set credentials for the new IAM user in the CLI as environment variables and acquire a certificate:

      export AWS_ACCESS_KEY_ID=AKIA---------EXAMPLE
      export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI-----------------EXAMPLEKEY
      
      certbot certonly --dns-route53 -d mqtt.YOURDOMAIN.COM
      

Understanding the Certbot certificates

  • fullchain.pem: The full chain of certificates involving the certification of the domain. Usually includes three certificates that can be broken down in the following manner:
    • Certificate body (first): the certificate for the registered domain.
    • Intermediate certificate (second): the certificate for Let's Encrypt.
    • Root certificate (third): the certificate from a trusted certificate authority, which belongs to a select few set of CA's shipped by default in most OS and web browsers.
  • cert.pem: The first certificate from the full chain.
  • chain.pem: All the certificates from the full chain, except the first.
  • privkey.pem: Used to encrypt/decrypt data.

More information from Let's Encrypt on their certificate chain can be found here.

Set up two-way TLS/SSL in EMQX Cloud deployment

  1. Click on + TLS/SSL in EMQX Cloud console.

    Click on "+ TLS/SSL"

  2. Select "two-way" for "Type", add the certificates from previous steps to the EMQX Cloud deployment, and click "Confirm".

    • Certificate body: cert.pem from Let's Encrypt. The certificate created by Let's Encrypt for the subdomain.

    • Certificate chain: The intermediate (second) certificate in fullchain.pem from Let's Encrypt. The chain should include all certificates between the certified (sub)domain and the root certificate, which in this case should be just one.

    • Certificate private key: privkey.pem from Let's Encrypt.

    • Client CA certificate: client-ca.crt locally created previously with openssl. Since the client connecting to the deployment also needs to be verified, the deployment needs to know the trusted CA to check client certificates with.

      Client CA certificate

Test two-way TLS/SSL with MQTT X

  1. Ensure the existence of a username and password to connect to the deployment. Help creating users can be found here.

  2. In the Let's Encrypt certificate directory, create a new root.pem file and add the root (last) certificate from fullchain.pem.

  3. Open MQTT X and create a new connection.

    Open MQTT X

  4. Fill out the new connection prompt with the proper information and click "Connect".

    • Host and Port: since TLS is being used, choose mqtts:// as well as port 8883. The port number can be confirmed in the EMQX Cloud console. Do not forget to add the certified subdomain in the address field.
    • Username and Password: fill out with an existing EMQX Cloud deployment user (see step 1).
    • Enable both SSL options.
    • Certificate: Choose self signed.
    • Certificates:
    • CA File: root.pem manually created from the Let's Encrypt certificates.
    • Certificate Client File: client.crt locally created previously with openssl.
    • Client key file: client.key locally created previously with openssl.

    Fill out the new connection prompt

  5. Once the connection is successful, a green "SSL" sign should appear and the two-way TLS/SSL is fully configured and ready to be used. It can be further tested by subscribing to a topic then sending a message to the same topic.

    the connection is successful

If you get a "Error: unable to get issuer certificate" message, download the ISRG Root X1 Self-signed certificate and use it in the MQTT X "CA file" field. The error occurs because Let's Encrypt's default root certificate is itself certified with an older CA that recently expired, causing some devices to no longer trust it. More information here.

Next steps

Now we have finished setting up a two-way TLS authentication for an EMQX Cloud with a custom domain from Route 53 certified by Let’s Encrypt, tested with MQTT X. Two-way TLS/SSL can provide an important layer of security for communication over the internet, helping to protect sensitive information and prevent attacks.

Continue exploring what EMQX Cloud has to offer:

For more about EMQX Cloud, please check our documentation, GitHub, Slack channel, and forum! For questions, comments, or suggestions, please contact us at cloud-support@emqx.io.

Try EMQX Cloud for Free
No credit card required
Get Started →

Related Posts

Connect to MQTT broker with Websocket

This article will demonstrate how to use WebSocket to connect to MQTT broker and introduce technical points of interest to developers and solutions to common errors.

Shifan Yu 2020-11-05
Enable two-way SSL/TLS for EMQX

This article will introduce how to enable SSL/TLS two-way security connection for MQTT in EMQX.

Shifan Yu 2020-07-22
Enable SSL/TLS for EMQX MQTT broker

EMQX MQTT broker supports multiple security authentications, this article will introduce how to enable SSL/TLS for MQTT in EMQX.

Shifan Yu 2020-07-13