How to Connect to AWS IoT Core using MQTT & ALPN

This example shows how to connect to AWS IoT Core using MQTT on the secure HTTPS port 443. Many firewalls and home routers limit inbound and outbound traffic to a small range of TCP ports. This is done as a security measure to limit the attack surface for possible cyber attacks. Standard ports for things like HTTPS traffic (port 443) are usually left open but others that are used for less common protocols, such as MQTT (port 8883) may be intentionally blocked.

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.

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 Lua code we have prepared.

We have prepared two AWS IoT Core MQTT examples. One can be downloaded from GitHub and the other is integrated in our Lua tutorials. The example on GitHub requires some configuration and the example that is integrated in our Lua tutorials is configuration-less. The Lua tutorials version just needs the zip file you get when following the AWS video tutorial. You can also safely run the AWS IoT Core MQTT example using our online tutorial server.

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 Authentication (mTLS) SharkSSL Object

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.

Discover More:

Whether you are a maker, a startup, or a large business, we've got you covered. Please send us an email if you have any questions or if you are unsure on what product to select. We are here to help you find the best solution, and we'd really like to help you with your hardware/software project challenges.


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