Securing inbound and outbound ports for Azure IoT

The Azure IoT Hub is able to support a high number of IoT devices, all communicating with their own personal secure connection.

The Azure IoT Hub supports both MQTTs, AMQPs and HTTPs as transport protocols. It’s even possible to communication MQTTs and AMQPs over websockets for Azure IoT Edge.

No, it’s not possible to transfer IoT telemetry and commands without TLS supported communication.

But what if a hacker tries to spoof a device, or our IoT Hub?

How can we be sure that received telemetry is coming from genuine devices? And can we limit the device communication to our own Azure resources?

Do you know who you are talking against?

Let’s see how we can make Azure IoT yet a little bit more secure.

This blog is all about firewall settings.

Limiting IoT Hub inbound communication

The Azure IoT Hub supports IP filtering. This makes it possible to limit communication to trusted devices on trusted IP ranges only. See how easy this is to configure:

Here is an example after adding two rules:

I have added one rule which blocks an IP range. And I added one IP address which is trusted.

Regarding the trusted IP address: it’s for demonstation purposes only, in this case it has no real added value. By default, all addresses, not touched by any blocked range are allowed to communication, including this trusted IP address. The ‘allow’ functionality is for more exotic purposes.

Note: the number of configuration lines is limited. It’s a soft limit. You can ask Microsoft to open more rules if needed for your own IoT Hub.

Note: Do not block IP ranges for your own logic running on actual Azure services. You could potentially block a service like Azure Stream Analytics.

It’s also possible to test your IP filter rules quickly:

As you can see, the rule causing the blocked IP address is using the CIDR format. So a complete range of IP addresses is blocked with a single rule.

Now you are able to block malicious devices sending data from non supported locations.

How about limitting communication from a device point of view?

Limiting local firewall outbound communication

Limitting access to the cloud for local devices is normally done by a firewall.

Each internet connected device should have at least a local firewall in place.

For example, check your own internet router, there should be a firewall active on that one too.

Normally, limiting inbound communcation is active by default. You do not want to have ports opened so an external party can access something on your local internet. Exceptions could be eg. running a website (port 80/port 443) or (if you know what you are doing) SSH access (port 22).

In our case, the attack vector is that malicious code or misconfiguration on our IoT device is leaking information to non-azure internet addresses. So this is limiting outbound communcation!

Note: inbound or outbound does not say anything about simplex or full duplex communcation. It only means which side is listening.

In short:

  • the side which is listening, is vulnerable to attacks (eg. DDOS)
  • the side which is sending is vulnerable to leaking information

So we want to add IP filters to our local firewall too.

Note: setting outbound IP filters on a local device is not as powerful as setting them on the corporate firewall. A hacker with access to your device should be smart enough to change the local firewall rules too.

Outbound firewall rules

But how do we get the IP address of our Azure resources?

The short answer is just to ping a resource such as your IoT Hub. If ‘ping’ is able to resolve the IP address, you see the IP address appearing:

ping edgedemo-ih.azure-devices.net

Pinging ihsu-prod-am-002.cloudapp.net [13.95.15.251] with 32 bytes of data:
Request timed out.
Ping statistics for 13.95.15.251:
Packets: Sent = 1, Received = 0, Lost = 1 (100% loss),
Control-C

All you have to do is adding this IP address to the firewall?

Yes and no.

Yes, you can add the IP address and be safe for now…

Azure resources do not have fixed IP addresses by default. So setting the current IP address will only works as long as Microsoft does not rearrange IP addresses on Azure.

Would it not be nice if Microsoft warns us if the addresses change?

Azure firewall service tags

Microsoft already has this in place. They publish a list of all known IP addresses used by the Azure platform. This is called Azure Service tags:

A service tag represents a group of IP address prefixes from a given Azure service. Microsoft manages the address prefixes encompassed by the service tag and automatically updates the service tag as addresses change, minimizing the complexity of frequent updates to network security rules.

There is also a tag called ‘AzureIoTHub’ so the IoT Hub addresses are available too.

Note: The Device Provisioning Service is not supported yet.

How can you get this list of possible IP addresses? These are two ways:

  1. You can download a file with all tags (deprecated by June 30, 2020)
  2. A more automated usage: Rest, CLI, Power shell (currenly in preview)

Let’s look at downloading the file first. Just download it. This will return a JSON file. Open it in Visual Studio Code and search for IoTHub nodes:

This is the overall section for IoTHub IP address ranges, all over the world.

There are also separate sub sections for specific regions. I normally host my resources in West Europe:

If you compare these ranges with the IP address return by the ping to my own IoTHub, you will see the address is listed here.

These are the ranges I have to add firewall rules for. But is this enough?

No, you have to take the geo-paired Azure into consideration too.

The West Europe Azure region is paired with North Europe. If a resource in West Europe becomes unavailable, a North Europe equivalent will pick up the load from there.

So you need to check out your geo-pair region too:

Note: the change number is your trigger to update your firewall rules.

Still, there are a number of challenges with this approach:

  • It’s hard to automate firewall updates with this file
  • It seems the file support will depricate half 2020 (see the note)

So the API (which is still in preview) is a better approach.

API Support

To demonstrate the API support, I tested both the CLI and the Powershell support:

// CLI
az login // only needed if you are not logged into Azure from your prompt
az network list-service-tags --location westeurope
az network list-service-tags --location westeurope --subscription [subscription guid] // needed if you have multiple subscriptions under the same account

It’s interesting to see that a different Azure subscription could possible lead to different service tags.

For Powershell you need to install azure support for Powershell, if not already done yet:

Install-Module -Name Az -AllowClobber -Scope CurrentUser

After this, you can run the powershell command:

Connect-AzAccount // only needed if you are not logged into Azure from Powershell
$serviceTags = Get-AzNetworkServiceTag -Location westeurope

This will fill a variable ‘$servicetags’ containing the tags. Now you can filter this variable:

$serviceTags.Values | Where-Object { $_.Name -eq "iot" }

Unfortunately, at this moment the IoTHub is not supported in the API yet. So this will result in an empy set.

Conclusion

Adding firewall rules for IoT devices is an essential part of IoT security and faily simple to execute.

The service tags are a good improvement in supporting a flexible but still limited (and trusted) set of IP address ranges.

The current file solution is cumbersome but still the way to go. As soon as the API supports the IoT Hub and Device Provisioning Service, we can fully automate this security solution