How to Connect to AWS IoT Core using MQTT & ALPN

This example demonstrates how to connect to AWS IoT Core using MQTT over a secure HTTPS connection on port 443. Many firewalls and home routers restrict inbound and outbound traffic to a small range of TCP ports as a security measure, and while standard ports like HTTPS (port 443) are typically left open, others that are used for less common protocols like MQTT (port 8883) may be blocked. By using TLS ALPN, this example shows you how to connect the MQTT client to AWS IoT Core using the HTTPS port 443, allowing you to bypass any potential barriers and establish a secure connection. This is an important consideration for anyone looking to implement MQTT in their IoT projects, and our ready-to-run examples make it easy to get started with this powerful communication setup.

This tutorial also shows you how to set up mutual TLS authentication. Mutual Transport Layer Security (mTLS) is a secure communication protocol that establishes an encrypted connection between two parties using X.509 digital certificates to authenticate each other. This ensures that the parties on either end of a network connection can be confident in the identity of the other party, as both must possess the correct private key in order to successfully establish the connection. This tutorial serves as a solid foundation for both the mTLS Lua example and the mTLS C example included in the SharkSSL IDE, and will help you get started with implementing secure communication in your own IoT projects.

This example is designed for the YouTube video tutorial How to Get Started with AWS IoT Core Quick Connect. You must follow the instructions in this video "as is", except for running the Python code. Instead of running the Python code, you will be running the code we have prepared.

We have created two AWS IoT Core MQTT examples for Lua - one can be downloaded from GitHub and the other is integrated into our Lua tutorials. The GitHub example requires some configuration, while the version in our Lua tutorials is ready to use out of the box - all you need is the zip file produced by following the AWS video tutorial. The configuration-less example is also available to run on our online tutorial server, so you can try it out without having to set anything up on your own computer. Additionally, we have included a C code version of the AWS IoT Core MQTT example in the SharkSSL IDE, providing even more options for those looking to get started with AWS IoT Core.

Options:

The GitHub code example has a smaller code base since it does not need the supporting code for the configuration-less example.

How the AWS IoT Core Example Works

The following code snippet shows how to connect to AWS IoT Core using the port number 443 (the secure HTTPS port).

local mqtt = require"mqttc".connect(
   awsBroker, -- broker name
   onpub, -- Our MQTT callback function
   { -- The option (op) table
      shark = shark,
      id = "basicPubSub",
      port = 443,
      alpn = "x-amzn-mqtt-ca"
   })

We load the Lua MQTT client module "mqttc" by calling the require function. This function returns the MQTT module as a Lua table. Using this table, we call the MQTT connect() function that is part of this table. We pass in three arguments to the connect() function, the AWS IoT Core's MQTT broker name, a callback function, and a configuration table. The callback function will be called when the broker publishes messages we have subscribed to. In the configuration table, we set the MQTT client's ID, the connection port to 443, and the alpn extension to a specialized extension defined by AWS. See the Amazon AWS tutorial MQTT with TLS client authentication on port 443 for more information on how this works. We also set the 'shark' attribute in the configuration table. The Mako Server uses the Barracuda App Server library, which in turn is bundled with a TLS stack called SharkSSL. Since we are connecting using a secure connection, a SharkSSL object is required.

How to Create a Mutual Transport Layer Security (mTLS) SharkSSL Object

Check out the tutorial Certificate Management and Chain of Trust if you are new to certificate management and/or mTLS.

As we mentioned above, a SharkSSL object is required when using a secure connection. This object not only enables setting up a secure connection, but also makes sure we trust the broker and that the broker can authenticate our MQTT client using the SSL certificate created by the online AWS portal. This is known as Mutual TLS (mTLS) authentication. The client authenticates the broker and the broker authenticates the client. See the tutorial Certificate Management for Embedded Systems if you are new to PKI (Public Key Infrastructure).

When using mTLS, both the client and server have a certificate, and both sides authenticate using their public/private key pair. The mTLS handshake works as follows:
  1. Client connects to server
  2. Server presents its TLS certificate
  3. Client verifies the server's certificate
  4. Client presents its TLS certificate
  5. Server verifies the client's certificate
  6. Server grants access
  7. Client and server exchange information over encrypted TLS connection

Before creating a SharkSSL object, we need to create a Truststore aka certificate store. The certificate store will enable the client to authenticate the broker's X.509 certificate; more specifically, the certificate store will enable the client to validate the broker's complete certificate chain.

local certstore = ba.create.certstore()
certstore:addcert(io,"AmazonRootCA1.pem")
local shark = ba.create.sharkssl(certstore)

In the above Lua code snippet, we create a certificate store and add the Amazon root certificate aka certificate authority (CA) certificate to the store. This will enable the client to authenticate the AWS MQTT broker. The last line above creates a SharkSSL object and binds this object to the certificate store.

We also need to make sure the client sends its client certificate to the MQTT broker. You get the client certificate and its associated private key by following the instructions in the AWS IoT Core Quick Connect video tutorial.

local sharkcert = ba.create.sharkcert(io, "Demo_Thing.cert.pem","Demo_Thing.private.key")
shark:addcert(sharkcert)

In the above code snippet, we create a SharkSSL binary (optimized) certificate by using the client's certificate and private key. We then add this certificate to the SharkSSL object. That is all it takes to complete the mutual authentication configuration. We can now use the SharkSSL object in the configuration table when we call the mqtt.connect() function (see the first code snippet above).

See the MQTT example's full source code for details.

Note: This example does not work if your Intranet requires Internet access via a proxy such as a SOCKS proxy. See the code snippet Example 4: Connecting via a SOCKS5 proxy included in the MQTT documentation if you are behind a HTTPS or SOCKS proxy.

Discover More:

No matter what your background or project goals, we're here to help you find the perfect solution! Are you a maker looking for the right tools? A startup trying to get off the ground? A large business seeking new software solutions? We've got you covered.

If you have any questions or just aren't sure which product is right for you, don't hesitate to reach out. Our team is dedicated to helping you overcome your hardware/software challenges and find the best solution for your needs. Let us know how we can help - we'd love to lend a hand!


OPC-UA

OPC-UA Client & Server

An easy to use OPC UA stack that enables bridging of OPC-UA enabled industrial products with cloud services, IT, and HTML5 user interfaces.

Edge Controller

Edge Controller

Use our user programmable Edge-Controller as a tool to accelerate development of the next generation industrial edge products and to facilitate rapid IoT and IIoT development.

On-Premises IoT

On-Premises IoT Platform

Learn how to use the Barracuda App Server as your On-Premises IoT Foundation.

Embedded Web Server

Barracuda Embedded Web Server

The compact Web Server C library is included in the Barracuda App Server protocol suite but can also be used standalone.

WebSocket Server

Microcontroller Friendly

The tiny Minnow Server enables modern web server user interfaces to be used as the graphical front end for tiny microcontrollers. Make sure to check out the reference design and the Minnow Server design guide.

WebDAV Server

Network File System

Why use FTP when you can use your device as a secure network drive.

HTTP Client

Secure HTTP Client Library

PikeHTTP is a compact and secure HTTP client C library that greatly simplifies the design of HTTP/REST style apps in C or C++.

WebSocket Client

Microcontroller Friendly

The embedded WebSocket C library lets developers design tiny and secure IoT applications based on the WebSocket protocol.

SMTP Client

Secure Embedded SMTP Library

Send alarms and other notifications from any microcontroller powered product.

Crypto Library

RayCrypto C Library

The RayCrypto engine is an extremely small and fast embedded crypto library designed specifically for embedded resource-constrained devices.

Embedded PKI Service

Automatic SSL Certificate Management for Devices

Real Time Logic's SharkTrust™ service is an automatic Public Key Infrastructure (PKI) solution for products containing an Embedded Web Server.

Modbus

Modbus TCP client

The Modbus client enables bridging of Modbus enabled industrial products with modern IoT devices and HTML5 powered HMIs.

Posted in Tutorials