F5 BIG-IP MQTT protocol support and use cases in an IoT environment

The Internet-of-Things is a system of physical devices, vehicles, buildings, and any other items each provided with a unique identifier allowing them to communicate with one another without any human intervention. MQTT is a widely-used machine-to-machine connectivity protocol that helps these devices communicate and exchange messages. The wide adoption and popularity of the MQTT protocol led to its support in the BIG-IP version 13.0.

MQTT is a publish/subscribe messaging protocol. A device such as a camera, heat sensor, lP-enabled light bulb, etc. can publish data to an intermediary module using the MQTT protocol. An application can then subscribe to this intermediary module and retrieve the published data. Intermediary modules are also known as message brokers. The BIG-IP with MQTT awareness can sit in front of the MQTT message brokers to provide scalability, security, visibility, and availability.

Fig. 1 – Basic architecture of using the BIG-IP platform in an IoT environment.

In an MQTT configuration, clients publish messages and the BIG-IP system parses those MQTT messages based on which it invokes MQTT specific iRule events if defined and performs connection based load balancing on the MQTT messages to a pool of message brokers. The message brokers then transport and route the messages to subscribing servers

A typical BIG-IP MQTT configuration includes:

  • MQTT pool of message brokers
    • Are grouped together to receive and process traffic. After the pool is created, associate the pool with a virtual server. Some common open source message brokers examples are Mosquitto and VerneMQ
  • iRules for MQTT
  • Client SSL profile
    • Use a Client SSL profile when you want the BIG-IP® system to authenticate and decrypt/encrypt client-side application traffic
  • Virtual server configured to use MQTT functionality

For more details please refer to: https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/ltm-iot-administration-13-0-0/1.html

BIG-IP natively supports the MQTT protocol. BIG-IP has a full proxy architecture which makes BIG-IP itself an endpoint and an originator of the MQTT protocol. iRules take advantage of the deep understanding of the protocol and can be used at different events (specific moments within the session flow of a network connection, such as MQTT_CLIENT_INGRESS, MQTT_SERVER_INGRESS) to intelligently parse the MQTT protocol and make traffic decisions.

Let’s explore some of the use cases using iRules such as load balancing and steering traffic based on a unique identified present within the MQTT protocol, preventing attacks based on TOPICS/LENGTH of a PUBLISH message, client authentication based on CN name present in the client certificate.

Use Case: prevent MQTT DDoS attacks based on the below parameters

Topic validation

Validate the ‘TOPIC’ of a PUBLISH message and if it does not fit the validation criteria then drop the connection. This will prevent messages with bogus TOPICS from reaching the message brokers. And help in preventing MQTT DDoS attacks based on TOPIC.

when MQTT_CLIENT_INGRESS {
log local0. "CLIENT [MQTT::type]"
    if {[MQTT::type] eq "PUBLISH" } {
        # Check against a allowed topic.
        if { [MQTT::topic] eq "bogus/bogus" } {
            # Invalid topic
            log local0. "   Topic is Invalid. Potential DDoS Attack -> Dropping Topic: [MQTT::topic]"
            drop
        }
    }         
}

The above iRule can be enhanced to use data groups where the data groups will have the entire list of TOPICS and the [MQTT::TOPIC] can be checked against the data group

MQTT PUBLISH message length validation  

An application will typically have knowledge about the size of the data that is being transmitted. Taking advantage of that knowledge the length of a PUBLISH message can be validated and if it does not satisfy the expected length then drop the connection. This will prevent large messages from reaching the message brokers and not overload the broker.

when MQTT_CLIENT_INGRESS {
log local0. "CLIENT [MQTT::type]"
    if {[MQTT::type] eq "PUBLISH" } {
        # Check length of message.
        if { [MQTT::length] > 100 } {
            # Invalid length
            log local0. "   Length is Invalid. Potential DDoS Attack -> Dropping message: [MQTT::topic] : [MQTT::length]"
            drop
        }
    }         
}

Use Case: pool selection/load balancing based on username as a unique identifier

Use the username as a unique identifier to steer traffic to a message broker. This enables stickiness between an end user and a message broker by mapping a device/end user to a pool in the load balancer.  The mapping helps in conditions where in a device needs to reconnect to the message broker on which the active client session lives and can use the state information present on the message broker to make decisions.

when MQTT_CLIENT_INGRESS {
log local0. "CLIENT [MQTT::type]"
    if {[MQTT::type] eq "CONNECT" } {
        # Select pool based on username, example license ID
        if { [MQTT::username] eq "D1111111" } {
            log local0. "Load balancing to pool MQTT-BrokerPool1"
            pool MQTT-BrokerPool1
        }
        if { [MQTT::username] eq "D1111112" } {
            log local0. "Load balancing to pool MQTT-BrokerPool2"
            pool MQTT-BrokerPool2
        }
    }         
}

The above iRule can be enhanced to use data groups where the data groups will have the list of unique usernames. Multiple data groups can be defined, each one representing users for multiple Pools. The [MQTT::username] can be checked against the data group and based on that the pool selection can be made.

Use Case: client certificate authentication over TLS

BIG-IP can terminate MQTT encrypted SSL/TLS messages and then send the un-encrypted traffic to the backend Broker. This allows the Broker to scale as it can offload all SSL/TLS functions and configuration to the BIG-IP. In addition to terminating SSL/TLS the BIG-IP can use iRules to perform Client Certificate Authentication. The BIG-IP can embed the client CN name from the client certificate into the backend connection along with the username for authentication by the back-end Broker.

when CLIENT_ACCEPTED {
    set cn ""
}

when CLIENTSSL_CLIENTCERT {
   log local0. " Parsing X509 Info for SSL Client Cert CN Name"
   set cn [findstr [X509::subject [SSL::cert 0]] "CN=" 3 ","]
   log local0. "Found Client Cert Common Name (CN) : $cn"
}

when MQTT_CLIENT_INGRESS {
    log local0. "MQTT Client MmessageTtype [MQTT::type]"
    if {[MQTT::type] == "CONNECT"} {
        log local0. "Connecting to Broker"
        if {$cn == ""} {
            # if we didn't see a client cert, return an authentication error         
            MQTT::drop                  
            MQTT::respond type CONNACK return_code 5
            MQTT::disconnect  
          } else {
            log local0. "Passing Username and CN to Backend for Authentication"
            log local0. "MQTT Username: [MQTT::username]"
            log local0. "Username: [MQTT::username] CN: $cn"
            set mqttuser [MQTT::username]
            MQTT::username "$mqttuser $cn"             
        }
    }
 }

Conclusion

Bookmark this page if you are interested in learning more. We will be update this blog with new compelling IoT features developed by F5 for the upcoming BIG-IP releases.

Do you have a suggestion for an IoT related topic that you would like for us to cover? Please leave a comment on this post if you do.

References

Published May 09, 2017
Version 1.0
  • Joffo's avatar
    Joffo
    Icon for Nimbostratus rankNimbostratus

    Hello,

     

    MQTT_CLIENT_INGRESS event is not even triggered in 14.1.0.6. Why could that be?