Use mDNS & certificates to create your IoT network

We are all familiar by now with the basics of how networks operate. IoT networks have special requirements and here we explore these needs and how to meet them.

The IoT network

We are all familiar by now with the basics of how networks operate and how our computers connect to information sources on the internet. A combination of protocols give our devices an IP address (DHCP), provide a way for other devices to find us (DNS), and protocols built on underlying packet transportation protocols such as UDP & TCP allow us to communicate across the internet. We layer protocols such as HTTP over these to transfer information and typically secure our communications with certificates that enable us to authenticate and encrypt conversations between end-points.

IoT networks, particularly those that run on the factory floor or in a small or medium business enterprise stretch the capabilites of the normal internet architecture because of some unique characteristics. First of all, important chunks of the infrastructure may not be present. Typically, while there is usally a DHCP server on the factory floor network segment, DNS serices are not always present. Secondly, it is not always possible to automatically register a new device with DNS, something which is very much part of the normal IoT workflow.

mDNS

In order to enable IoT devices to be installed in these scenarios, to enable them to receive IP addresses, and then to make themselves known to other IoT devices on the network requires some different protocols. Factory floor discovery uses two new protocols mDNS (multicast DNS) and DNS-SD (DNS service discovery) to enable nodes to participate fully in the network.

mDNS, as you might guess, is a multicast version of DNS. Normally, DNS services are hosted on a server and a node wanting to communicate with another, issues a query for the IP address of a target node to the DNS server which (possibly recursively) maps the name to an IP address and returns it to the requesting node.

mDNS uses the same format as DNS, but instead of directing a query to the DNS server, broadcasts the request on the network. The device with the node name in the DNS request responds with its IP address. Devices which support the mDNS protocol hear this message and cache the address information so that they learn about the names and addresses of other nodes on the network.A unique characterstic of mDNS services is the handling of domains. All mDNS nodes are automatically assigned to the “local” domain, thus distinguishing them from the global DNS namespace.

An interesting use case for factory floor networks, is the need to locate certain services such as a historian or a configuration service on the network. It’s hard to do this when you don’t know the name of the server and hence can’t try and find its IP address. DNS-SD is similiar in function to mDNS, but instead of helping resolve node names to IP addresses, it resolves services to IP addresses. You have probably seen this in action when, for example, you ask your computer to find a printer for you to use, and a list of printers shows up for you to select from. Here your computer issues a DNS-SD request for any device that provides the “printer” services, all devices (printers) respond to the query.

Service discovery is actually a very interesting capability for IoT nodes, since it allows devices to build self-organizing networks on top of the basic network infrastructure. It also enables devices to find useful services such as a mqtt-broker etc without knowing, a priori where the broker is located on the network. Service discovery provides an element of redundancy since, if one provider of the service is no longer available, DNS-SD can be used to find a replacement.

Here is a simple code snippet for ESP32 that initializes the mDNS subsystem and publishes a hostname “dev01” for the device. It also advertises a http service running over tcp-ip in port 443. This service is a simple https server on the node. By executing this code, the device registers the name “dev01.local” on the network and the availability of its web interface.

static void initialise_mdns(void)
{
    char* hostname = "dev01";
    //initialize mDNS
    ESP_ERROR_CHECK( mdns_init() );
    //set mDNS hostname (required if you want to advertise services)
    ESP_ERROR_CHECK( mdns_hostname_set(hostname) );
    ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname);
    //set default mDNS instance name
    ESP_ERROR_CHECK( mdns_instance_name_set(hostname) );
    mdns_service_add(NULL, "_http", "_tcp", 443, NULL, 0);
}

Certificates

Now that we understand how to get our nodes on the network and how to find and address them, lets look at what is needed to ensure that we can communicate securely to them. We will look at protecting HTTP services using certificates (ie HTTPS), and will look at what steps are necessary in this local network kind of environment.

Over the last few years the process of generating certificates for secure communications has undergone a dramatic change. Previously it was common for an entity to approach a certificate service such as namecheap or others and pay for a multi-year certificate that could be used to validate a network server or other device. With the rapid surge in growth of automated circuit generating and updating capabilities such as LetsEncrypt, it is now possible to obtain free certificates and renew them automatically by using such a service. The existance of automation and security concerns has also been driving to shorten the lifetime of valid publically trusted certificates, with the current lifespan being set at 398 days.

These automated services often require the certifying authority and the node to have access to domain records or to specific files that are hosted on a http server on the node. In addition, since the “.local” domain is literally a local one, there is a possibility of name overlap between various “.local” networks and hence no real unique owner of the name that can be identified by these certification authorities. In fact, Lets Encrypt for example, will not issue certificates for anything in the “.local” domain.

A possible solution is to add local trust settings to your network. Typically this would involve creating your own root Certificate Authority (CA) and using it to generate trusted certificates for the devices in your network. In order to work with major browsers such as Firefox, Chrome or Safari, you will need to add your local CA certificate as a trusted certificate to the browsers in your network. Once you have done this however, you have the last pieces you need to build your IoT solution.

Here, you can see an example of the server certificate for “dev01.local”. This, and the corresponding key-pair were created using openssl. The certificate was then signed by the IoTReady Certificate Authority.

Certificate for "dev01.local"

Since the certificate authority was imported into Firefox (using the menu Settings/Privacy & Security), the browser was able to verify the server certificate and accept it. The figure below shows the IoTReady Certificate in the Firefox store.

IoTReady Cert Auth installed in Firefox
Scroll to Top