Jump to content
Welcome to our new Citrix community!
  • Azure IoT and Citrix NetScaler


    cugcblogs

    verheij.rnd_.png.d0f1362e6265137a5f5ed265aea64fac.png by Ingmar Verheij, Citrix, CTP

    Earlier I wrote an article on Citrix Blogs on how a NetScaler can help scale and secure an IoT data stream. For organisations who host their IoT service, this is key for their success. After all, you don’t want your solution to get compromised! 

    But what if you want to use Azure IoT instead of building your own IoT service? That makes perfect sense to me; it’s a mature IoT stack which not only features the IoT Hub but also brings machine learning and other capabilities to create a complete solution. Another great capability of Azure IoT is the Azure IoT Edge (v2 in tech preview at the time of writing), which enables organisations to connect devices at the Edge instead of the Cloud. And–this is the best part in my humble opinion–you can process data at the edge before you forward it to the Cloud (if ever).

    Azure IoT is capable of communicating via a number of protocols, including HTSSP, AMQP and SMQTT. What’s interesting is that the Azure IoT has implemented a subset of the MQTT stack; it supports Device-to-Cloud (D2C) and Cloud-to-Device (C2D) but not Device-to-Device (D2D). Meaning; a device can only subscribe to messages published by the IoT Hub, not from other devices as you would with a “normal” MQTT broker. But what’s more interesting for this article, they only support the secure implementation of MQTT. A good decision if you ask me, you shouldn’t communicate anything over a non-secure connection to a Cloud service.

    verheij121217-01.png?w=764

    If we introduce the Azure IoT Edge component–which will probably end up somewhere in a datacenter or (factory building)–does this still apply? I think there are numerous devices which only talk the non-secure version of MQTT. Though you can resolve this with a custom module, I doubt you should (for such a simple reason).  

    As mentioned before, I feel the IoT Edge component is essential if your devices should process data at the edge, before reaching the Cloud. This could be due to performance reasons (eg. shutdown a valve when an anomaly is detected in the sensor readings) but also due to compliancy reasons (eg. personally identifiable information [PII]). Using modules in the IoT Edge runtime, this can be handled.

    verheij121217-02.png.cfb51d4bdd9fc3aa97b6641378ad97b2.png

    Now what if we bring the Azure IoT Edge to a production site, how do we handle resiliency? There’s little information known about the scalability of the Azure IoT Edge, but what’s clear is that one equals none. Meaning; we need at least two to provide a high available set. So, we need a Load Balancer capable of handling (S)MQTT.

    Just like the IoT Hub the IoT Edge only accepts SMQTT, which requires a TLS between the Device and the Edge. This requires quite some compute power–not to mention the administrative efforts–for which a CPU isn’t optimized. A Reverse Proxy capable of offloading the SSL handshake does improve scalability.

    Lastly, some (proprietary) devices aren’t able to communicate the secure version of MQTT. If the devices are in a controlled network segment (yes, you should really segment all your IoT devices) this might be acceptable. A Reverse Proxy capable of translating MQTT into SMQTT would be a great solution.

    verheij121217-03.png.ea197855ef73965161a801c53350bd6d.png

    What you see here is an example configuration where all IoT Devices communicate using the same connection string (single point of access); a Citrix NetScaler. The NetScaler has two endpoints: MQTT and SMQTT (with a CA signed certificate). The NetScaler in its turn communicates with the Azure IoT Edges (plural) over SMQTT. In my example, they’ve got the default self-signed certificates on them, this reduces the administrative overhead. 

    Three obvious benefits of a Citrix NetScaler with Azure IoT:

    • Create a resilient pool of Azure IoT Edge servers;
    • Offload SSL transactions;
    • Enable non-secure MQTT.

    And I can probably sum a whole lot more, but I won’t. What I will do is share with you how to you can set this up yourselves.

    Requirements

    Before we get to the dirty details, we need to ensure we have the tools at hand to test our setup. To test the publish and subscribe actions, I’ll be using the client tools provided by mosquitto on my Ubuntu 16.04 server.

    We’ll also need some information about your Azure IoT environment. What we need is:

    • [ioTHub] – The name of your Azure IoT Hub (this makes up [ioTHub].azure-devices.net). You can find this in the Overview section of your IoT Hub in Azure Portal;
    • [DeviceID] – The ID of a device we’ll be testing with. Create a new device in the IoT Devices section of your IoT Hub and give it an ID (I named mine MosquittoDevice). You can create the Device Explorer for this too (see next line);
    • [sharedAccessSignature] – The SharedAccessSignature (SAS) of the device (!) you just created. This isn’t available through the Azure Portal, you’ll need the Device Explorer to create a SAS for the device. TIP: Set the TTL longer than 0;
    • ExampleSharedAccessSignature sr=.azure-devices.net%2Fdevices%2F&sig=xxxxxx&se=xxxxxx
    • [AzureEdgeFQDN1] – The FQDN to your first Azure Edge server;
    • [AzureEdgeFQDN2] – The FQDN to your second Azure Edge server;
    • [NetScalerFQDN] – The FQDN where your devices will connect to your NetScaler;
    • [NetScalerVIP] – The Virtual IP on the NetScaler where your devices connect to;
    • [NetScalerCertKeyName] - The name of your SSL server.

    You also need the mqtt.lua file (see docs.citrix.com) in /var/download/extensions on your NetScaler (I’m using FileZilla on my Mac).

    Setup

    With all the requirements in place we can start with configuring the Citrix NetScaler. Open up the CLI and issue the following commands; 

    import ns extension local:mqtt.lua mqtt_code

    add user protocol MQTT -transport TCP -extension mqtt_code

    add user protocol MQTT_SSL -transport SSL -extension mqtt_code

    add server AzureIOTEdge1 [AzureEdgeFQDN1]

    add server AzureIOTEdge2 [AzureEdgeFQDN2]

    add service lb_service_azureiot1 AzureIOTEdge1 USER_SSL_TCP 8883

    add service lb_service_azureiot2 AzureIOTEdge2 USER_SSL_TCP 8883

    add lb vs lb_vserver_azureiot USER_SSL_TCP

    bind lb vs lb_vserver_azureiot lb_service_azureiot1

    bind lb vs lb_vserver_azureiot lb_service_azureiot2

    bind ssl vserver lb_vserver_azureiot -certkeyName [NetScalerCertKeyName]

    set ssl vserver lb_vserver_azureiot -ssl3 DISABLED

    add user vs u_vserver_azureiot MQTT [NetScalerVIP] 1883 -defaultlb lb_vserver_azureiot

    add user vs u_vserver_azureiot_ssl MQTT_SSL [NetScalerVIP] 8883 -defaultlb lb_vserver_azureiot

    bind ssl vserver u_vserver_azureiot_ssl -certkeyName [NetScalerCertKeyName]

    set ssl vserver u_vserver_azureiot_ssl -ssl3 DISABLED

    Let’s take a look at the steps

    import ns extension local:mqtt.lua mqtt_code

    add user protocol MQTT -transport TCP -extension mqtt_code

    add user protocol MQTT_SSL -transport SSL -extension mqtt_code

    This creates a protocol extension with the name mqtt_code in your NetScaler, as described here.

    add server AzureIOTEdge1 [AzureEdgeFQDN1]

    add server AzureIOTEdge1 [AzureEdgeFQDN2] 

    add service lb_service_azureiot1 AzureIOTEdge1 USER_SSL_TCP 8883

    add service lb_service_azureiot2 AzureIOTEdge2 USER_SSL_TCP 8883

    We then add server objects pointing to the Azure IoT Edge servers and two service objects, referring to the Azure IoT Servers, on port 8883 (the port the Azure IoT Edge is listening SMQTT).

    add lb vs lb_vserver_azureiot USER_SSL_TCP

    bind lb vs lb_vserver_azureiot lb_service_azureiot1

    bind lb vs lb_vserver_azureiot lb_service_azureiot2

    bind ssl vserver lb_vserver_azureiot -certkeyName [NetScalerCertKeyName]

    set ssl vserver lb_vserver_azureiot -ssl3 DISABLED

    Next, we create a load balancing virtual server and add bind both Azure IoT Servers. We add the SSL certificate and disable SSLv3.

    add user vs u_vserver_azureiot MQTT [NetScalerVIP] 1883 -defaultlb lb_vserver_azureiot

    We then create a user virtual server for the non-secure MQTT, which listens on the specified Virtual IP and port 1883.

    add user vs u_vserver_azureiot_ssl MQTT_SSL [NetScalerVIP] 8883 -defaultlb lb_vserver_azureiot

    bind ssl vserver u_vserver_azureiot_ssl -certkeyName [NetScalerCertKeyName]

    set ssl vserver u_vserver_azureiot_ssl -ssl3 DISABLED

    Last, we create another user virtual server for the secure MQTT, which listens on the specified Virtual IP and port 8883.

    Don’t forget to save your config!

    Testing

    Now that everything is set up, we can start testing by subscribing and publishing messages to the Azure IoT hub, via the Azure IoT Hub. We skip the NetScaler portion for now, we need to make sure this part works first.

    I’ve been testing on the same host as where my Azure IoT Edge is installed, so the self-signed (CA) certificates are on the same machine. Before we can use them, we need to create symbolic links to them using c_rehash.

    Issue the following command

    c_rehash /var/lib/azure-iot-edge/certs/edge-chain-ca/cert

    We can now test publishing a message using the mosquitto client:

    mosquitto_pub -d -h 

    [AzureEdgeFQDN1]

     -i 

    [DeviceID]

     -u "

    [AzureEdgeFQDN1]

    .azure-devices.net/

    [DeviceID]

     /DeviceClientType=azure-iot-device%2F1.2.2&api-version=2017-06-30" -P "

    [sharedAccessSignature]

    " -t "devices/

    [DeviceID]

    /messages/devicebound/#" -m "Hello World!" -t "devices/

    [DeviceID]

    /messages/events/readpipe/" -p 8883 -V mqttv311 --capath /var/lib/azure-iot-edge/certs/edge-chain-ca/cert 

    What you should see is: 

    Client MosquittoDevice sending CONNECT

    Client MosquittoDevice received CONNACK

    Client MosquittoDevice sending PUBLISH (d0, q0, r0, m1, 'devices/MosquittoDevice/messages/events/readpipe/', ... (12 bytes))

    Client MosquittoDevice sending DISCONNECT

    If you want to test subscribing to a message:

    mosquitto_sub -d -h 

    [AzureEdgeFQDN1]

     -i 

    [DeviceID]

     -u "

    [AzureEdgeFQDN1]

    .azure-devices.net/

    [DeviceID]

     /DeviceClientType=azure-iot-device%2F1.2.2&api-version=2017-06-30" -P "

    [sharedAccessSignature]

    " -t "devices/

    [DeviceID]

    /messages/devicebound/#" -p 8883 -V mqttv311 --capath /var/lib/azure-iot-edge/certs/edge-chain-ca/cert

    You should see:

    Client MosquittoDevice sending CONNECT

    Client MosquittoDevice received CONNACK

    Client MosquittoDevice sending SUBSCRIBE (Mid: 1, Topic: devices/MosquittoDevice/messages/devicebound/#, QoS: 0)

    Client MosquittoDevice received SUBACK

    Subscribed (mid: 1): 0

    In the Device Explorer, you can go to the Message To Device tab and select your device. Type “Hello World!” at Message and press Send. You should see the message come in.

    .

    NetScaler

    Now, let start testing with the NetScaler! Since we use a CA signed certificate we can use the regular CA certificates on the device (in /etc/ssl/certs).

    We'll issue the same commands as before BUT we change the FQDN from the Azure IoT Hub to the NetScaler and, as mentioned, we change the certificate path:

    Publish

    mosquitto_pub -d -h 

    [NetScalerFQDN]

     -i 

    [DeviceID]

     -u "

    [AzureEdgeFQDN1]

    .azure-devices.net/

    [DeviceID]

     /DeviceClientType=azure-iot-device%2F1.2.2&api-version=2017-06-30" -P "

    [sharedAccessSignature]

    " -t "devices/

    [DeviceID]

    /messages/devicebound/#" -m "Hello World!" -t "devices/

    [DeviceID]

    /messages/events/readpipe/" -p 8883 -V mqttv311 --capath /etc/ssl/certs

    Subscribe

    mosquitto_sub -d -h 

    [NetScalerFQDN]

     -i 

    [DeviceID]

     -u "

    [AzureEdgeFQDN1]

    .azure-devices.net/

    [DeviceID]

     /DeviceClientType=azure-iot-device%2F1.2.2&api-version=2017-06-30" -P "

    [sharedAccessSignature]

    " -t "devices/

    [DeviceID]

    /messages/devicebound/#" -p 8883 -V mqttv311 --capath /etc/ssl/certs

    And that's it!

    Cheers,

    Ingmar


    User Feedback

    Recommended Comments

    There are no comments to display.



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

×
×
  • Create New...