Scaling And Securing IoT Data Streams
The Internet of Things (IoT) is big and upcoming; we see more connected devices around us each day. When typical devices are “connected,” there’s an opportunity to make them smart and
Designing and building a new IoT solution is an exciting project that has many facets, ranging from a product design, to an end-user experience test, to building and managing a solution. With hundreds of IoT platforms available — many as a cloud service eg. AWS, Azure, etc. — deciding where and how messages (data) are processed is a key component. Part of the challenge is knowing what data is collected and how sensitive that data is for the customer or the organisation. Are we willing (or allowed) to process and store the captured data in a cloud service?
Organisations who host their own IoT service are confronted with a typical question; how do I scale and secure my service? Not an uncommon question when we build a typical application like webservers, but is it really that different?
Yes and no. Yes, because a connected device has one (or a few) connections where are long lived (and consists of events) whereas a web client has many connections which are short lived. No, because — just like with any applications — you need to balance the data streams between the servers, secure the connection with SSL/TLS and in some cases, authenticate the device before a connection is setup. This a typical workload for the Citrix NetScaler is also a Secure Event Delivery Controller (S-EDC).
A common protocol used in IoT is Message Queueing Telemetry Transport (MQTT), a machine-to-machine (M2M) data transfer protocol. MQTT clients can publish messages and (other) clients can subscribe to receiving messages, clients connect with MQTT brokers which – as the name implies – brokers all traffic between the clients. MQTT brokers (like HiveMQ) are available in clusters, so they scale and are resilient. However, they require a load balancer to spread to load from the clients. Just like you don’t want to expose your application/webserver directly to the internet, but have a reverse-proxy instead; the same goes for your MQTT broker. Especially when SMQTT (MQTT over TLS) is used to securing the IoT data stream the en-/decryption of the TLS connection is resource intensive not to mention the first layer of defense. A second layer of defense is typically an authentication layer, so the server can verify the identity of the client during the TLS handshake, for which X509 client certificates can be used.
What’s interesting with NetScaler 12 is that we didn’t just release support for MQTT, we’ve introduced the Protocol Extensionsframework. Meaning it’s now possible to introduce new protocols by writing extension code! Quite awesome if you ask me!
When you’re looking to scale and secure your IoT service, look no further! But do read on as I’ll share with you how I configured my NetScaler to secure the connection with my connected devices.
In my lab, I’ve got a NetScaler exposed to the internet and two MQTT brokers. I’ve got no intention to provide access to my network for my IoT sensors (no strangers in my network) as that reduces my risk significantly. So, these sensors are using SMQTT to connect to my NetScaler which is configured with a SSL certificate from an authorized certificate authority (CA). The NetScaler in its turn connect via MQTT to the MQTT brokers, as that’s my trusted network.
- NetScaler release 12;
- SSL certificate from an authorized certificate authority (CA); Ensure you include the certificate chain when intermediate certificates are used!
- lua file (see docs.citrix.com) to /var/download/extensions on your NetScaler (I’m using FileZilla on my Mac)
- MQTT broker(s).
import ns extension local:mqtt.lua mqtt_codeadd service lb_service_mqtt1 <MQTT_BROKER_1> USER_TCP 1883add service lb_service_mqtt2 <MQTT_BROKER_2> USER_TCP 1883 add lb vs lb_vserver_MQTT USER_TCPbind lb vs lb_vserver_MQTT lb_service_mqtt1bind lb vs lb_vserver_MQTT lb_service_mqtt2add user protocol MQTT -transport TCP -extension mqtt_codeadd user vs u_vserver_mqtt MQTT <MQTT_VIP> 80 -defaultlb lb_vserver_MQTTadd user protocol MQTT_SSL -transport SSL -extension mqtt_code add user vs u_vserver_mqtt_ssl MQTT_SSL <MQTT_VIP> 443 -defaultlb lb_vserver_MQTTbind ssl vserver u_vserver_mqtt_ssl -certkeyName <CERT_KEYNAME>
Let’s take a look at the steps
import ns extension local:mqtt.lua mqtt_code
This create a protocol extension with the name mqtt_code with the file mqtt.lua which is found in /var/download/extensions. When you try to load this policy extension in the GUI (via AppExpert > Policy Extensions > Policy Extensions) you’ll get an error “Extension loading error. [Extension mqtt, line 12: attempt to index global ‘client’ (a userdata value)]”. Don’t worry, a bug (BUG0699181) is filed and will be fixed!
add service lb_service_mqtt1 <MQTT_BROKER_1> USER_TCP 1883add service lb_service_mqtt2 <MQTT_BROKER_2> USER_TCP 1883
Here we create two services pointing to the MQTT Brokers on port 1883 (default port). <MQTT_BROKER_1> refers to the IP address of the first MQTT broker, <MQTT_BROKER_2> to the IP address of the second MQTT broker.
add lb vs lb_vserver_MQTT USER_TCPbind lb vs lb_vserver_MQTT lb_service_mqtt1bind lb vs lb_vserver_MQTT lb_service_mqtt2
Next we create a Load Balancing Virtual Server with the name lb_vserver_MQTT with the protocol USER_TCP. We binded the two servers (the MQTT brokers) to this Virtual Server.
add user protocol MQTT -transport TCP -extension mqtt_codeadd user vs u_vserver_mqtt MQTT <MQTT_VIP> 80 -defaultlb lb_vserver_MQTT
We then added a user protocol with the name MQTT using the TCP transport with the protocol extension we just added (mqtt_code). After that we create a User Virtual Server using the MQTT user protocol on port 80 which points to the Load Balancing Virtual Server we created in the step before: lb_vserver_MQTT. <MQTT_VIP> refers to the IP address where the IoT clients will connect to. This is not the SMQTT, so just for reference!
add user protocol MQTT_SSL -transport SSL -extension mqtt_code add user vs u_vserver_mqtt_ssl MQTT_SSL <MQTT_VIP> 443 -defaultlb lb_vserver_MQTTbind ssl vserver u_vserver_mqtt_ssl -certkeyName <CERT_KEYNAME>
Next we create another user protocol but this time with the name MQTT_SSL which is using the SSL transport. Another User Virtual Server is created with port 443 that points to the same Load Balancing Virtual Server as before.
Last we bind the SSL certificate to the User Virtual Server using the SSL transport u_vserver_mqtt_ssl where <CERT_KEYNAME> refers to the name of the Server certificate.
After this my sensors should be able to connect to <MQTT_VIP> via port 443 and setup a SMQTT session. We can verify this quite easily by using a MQTT application, I’m using MQTT-fx on my Mac.
First, configure a connection profile where you point the broker address to the <MQTT_VIP> you specified. The broker port is the port specified in u_vserver_mqtt_ssl (443). Select the tab SSL/TLS and check Enable SSL/TLS. Since we’ve used a SSL certificate from an authorized CA we can keep the CA signed server certificate selected.
You can now Connect and the light on the right should turn green with the lock locked (meaning you’re using SMQTT). In the Subscribe tab you can subscribe to messages (plural) or scan for topics collected. In the Publish tab you can “post” messages to a certain topic, which should be visible in the subscribe tab.
- Tutorial – Adding MQTT Protocol to the NetScaler appliance by using Protocol Extensions
- Some useful commands for troubleshooting:
sh ns extensionsh user protocolsh connectiontablesh persistentSessionssh lb vs lb_vserver_MQTTsh user vs u_vserver_mqtt
Citrix TechBytes – Created by Citrix Experts, made for Citrix Technologists! Learn from passionate Citrix Experts and gain technical insights into the latest Citrix Technologies.