Skip to main content
Version: Next

MQTT TLS Configuration

thin-edge.io supports certificate-based authentication when communicating with an MQTT broker. Three levels of security are supported:

  1. No authentication (default)
  2. Server authentication
  3. Server + client authentication

MQTT Configuration​

The tedge config command provides MQTT specific settings to open to the child devices the MQTT broker running on the gateway device.

PropertyDescription
mqtt.external.bind.portMqtt broker port, which is used by the external mqtt clients to publish or subscribe. Example: 8883
mqtt.external.bind.addressIP address / hostname, which the mqtt broker limits incoming connections on. Example: 0.0.0.0
mqtt.external.bind.interfaceName of network interface, which the mqtt broker limits incoming connections on. Example: wlan0
mqtt.external.ca_pathPath to a file containing the PEM encoded CA certificates that are trusted when checking incoming client certificates. Example: /etc/ssl/certs
mqtt.external.cert_filePath to the certificate file, which is used by external MQTT listener. Example: /etc/tedge/server-certs/tedge-certificate.pem
mqtt.external.key_filePath to the private key file, which is used by external MQTT listener. Example: /etc/tedge/server-certs/tedge-private-key.pem
note

If none of these options is set, then no external listener is set. If one of these options is set, then default values are inferred by the MQTT server (Mosquitto). For instance, the port defaults to 1883 for a non-TLS listener, and to 8883 for a TLS listener.

These settings can be considered in 2 groups, listener configuration and TLS configuration.

Configure basic listener​

To configure basic listener you should provide port and/or bind address which will use default interface. To change the default interface you can use mqtt.external.bind.interface configuration option.

To set them you can use tedge config as follows:

sudo tedge config set mqtt.external.bind.port 8883

To allow connections from all IP addresses on the interface:

sudo tedge config set mqtt.external.bind.address "0.0.0.0"

Configure TLS on the listener​

To configure the external listener with TLS additional settings are available:

  • mqtt.external.ca_path
  • mqtt.external.cert_file
  • mqtt.external.key_file

To enable MQTT over TLS, a server side certificate must be configured using the 2 following settings:

sudo tedge config set mqtt.external.cert_file /etc/tedge/server-certs/tedge-certificate.pem
sudo tedge config set mqtt.external.key_file /etc/tedge/server-certs/tedge-private-key.pem

To fully enable TLS authentication clients, client side certificate validation can be enabled:

sudo tedge config set mqtt.external.ca_path /etc/ssl/certs

Server authentication​

Enabling server authentication causes thin-edge.io MQTT clients to require a valid certificate from a broker when connecting. The broker certificate is valid when it is signed by a CA that the clients trust.

To enable server authentication, perform the following:

Step 1: Configure server authenticated listener in Mosquitto broker​

Create a file in /etc/mosquitto/conf.d/ with the following content and restart mosquitto service:

listener 8883
certfile PATH_TO_SERVER_CERTIFICATE
keyfile PATH_TO_SERVER_PRIVATE_KEY
  • listener 8883: defines a new listener on port 8883
  • certfile: points to a certificate that will be used by the broker to authenticate itself to connecting clients
  • keyfile: points to a private key of the specified certificate, necessary for encrypted communication

Be sure that mosquitto can read both files, especially the private key, which can only be read by the owner. Set mosquitto:mosquitto as an owner of these files. If you're unsure where to place them, /etc/mosquitto/ca_certificates is the directory intended for them, although you can use other paths if necessary.

The certificates used need to be X.509 v3 certificates with a subjectAltName section containing the hostname that the broker is running on.

Step 2: Configure thin-edge.io to connect to the new listener​

Execute the following commands:

sudo tedge config set mqtt.client.port 8883
sudo tedge config set mqtt.client.auth.ca_file PATH_TO_CA_CERTIFICATE

# optional
sudo tedge config set mqtt.client.auth.ca_dir PATH_TO_CA_CERTIFICATE_DIRECTORY

mqtt.client.auth.ca_file and mqtt.client.auth.ca_dir options point to trusted CA certificate(s) used by the clients to verify the broker. If either is used, server authentication is enabled.

Step 3: Restart services​

Now you will need to manually restart all the affected services so that they can pick up the configuration change.

Server + client authentication​

Additionally, the server can require connecting clients to present a valid certificate. These client certificates need to be signed by a CA that the server trusts. CA used to sign a server certificate and CA signing client certificates do not have to be the same.

Step 1: Configure server + client authenticated listener in Mosquitto broker​

Change the content of the conf file defined previously to the following and restart mosquitto service:

listener 8883
allow_anonymous false
require_certificate true
cafile PATH_TO_CLIENT_CA_CERTIFICATE
certfile PATH_TO_SERVER_CERTIFICATE
keyfile PATH_TO_SERVER_PRIVATE_KEY
  • allow_anonymous disables anonymous access to the listener; connecting clients will need to authenticate themselves
  • require_certificate requires clients to provide a certificate as a means of authentication

Step 2: Configure thin-edge.io to use a client certificate and private key​

sudo tedge config set mqtt.client.auth.cert_file PATH_TO_CLIENT_CERTIFICATE
sudo tedge config set mqtt.client.auth.key_file PATH_TO_CLIENT_PRIVATE_KEY

Both certfile and keyfile are required to enable client authentication. Setting only one of them will result in an error about the second one not being set.

As with the server private key, set tedge:tedge as the owner of the certificate and the private key, so that the private key can be read by thin-edge.io components.

Step 3: Restart services​

Now you will need to manually restart all the affected services so that they can pick up the configuration change.

Generating certificates​

You can use the following script to generate all required certificates:

openssl req \
-new \
-x509 \
-days 365 \
-extensions v3_ca \
-nodes \
-subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=ca" \
-keyout ca.key \
-out ca.crt

openssl genrsa -out server.key 2048

openssl req -out server.csr -key server.key -new \
-subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=$(hostname)"

cat > v3.ext << EOF
authorityKeyIdentifier=keyid
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyAgreement
subjectAltName=DNS:$(hostname), DNS:localhost
EOF

openssl x509 -req \
-in server.csr \
-CA ca.crt \
-CAkey ca.key \
-extfile v3.ext \
-CAcreateserial \
-out server.crt \
-days 365

openssl genrsa -out client.key 2048

openssl req -out client.csr \
-key client.key \
-subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=client1" \
-new

openssl x509 -req \
-in client.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-out client.crt \
-days 365

Next steps​