I’ve recently been playing with the popular open source home automation software Home Assistant. One of the nice features of this platform is that it can export most of the devices it manages as HomeKit devices for easy use from iOS devices.
HomeKit isn’t perfect, it’s a generic management platform so it’ll never be as good at doing thing X compared to a native app from vendor X – it just can’t have all the same parameters and configurability.
Despite this, there’s some compelling features for a household that’s fully on the Apple ecosystem:
- It puts all the assorted IoT “stuff” that we have into a single interface. This interface is available on my iPhone, iPad and Watch.
- It makes it easy to share to others who probably aren’t so technical they’re running a VPN to your house thanks to the built in tunnelling via Apple TV or Apple HomePod.
- The protocol has been opened up by Apple, so that you can now write and use uncertified devices using libraries such as HAP-Python or HAP-NodeJs. This is how it’s now possible for Home Assistant to expose various devices connected via other means to the HomeKit network.
The only thing that’s a bit annoying, is that if you get your firewall rulesets wrong it can be tricky to debug.
I had opened up TCP port 51827 (used by HomeKit) and was able to pair my device successfully, but then had weird issues where the accessories would go into “No Response” state for prolonged periods and only occasionally update with the latest information.
The trick to finding this was to do some packet dumping. I ran a packet dump for all traffic from my phone to the server running the Home Assistant app to see what was coming across the wire and could see a pile of mDNS requests that weren’t being answered.
mDNS is a tricky protocol – essentially it’s DNS, but instead of going to a name server for resolution, devices using mDNS send out a multicast packet to the network and wait to see who replies with the answer. Devices implementing mDNS need to listen to these packets and respond where appropriate. It’s most commonly implemented as Bonjour (Apple) and Avahi (Linux).
This means that we need to setup a firewall rule for UDP port 5353 to allow HomeKit clients to find the HomeKit accessory (in this case, Home Assistant). Without it, you get the “No Response” problem when lookups fail.
Why did it work at all without it? Not 100% sure, but I think HAP-Python might occasionally send out it’s own multicast messages advertising itself to iOS devices which allows them to find it for a period of time, but when the TTL expires and they try to re-resolve for connected accessories it’s nowhere to be found.
So the complete set of iptables rules you probably want (or something like them) is:
# mDNS iptables -A INPUT -p udp -m multiport --dports 5353 -j ACCEPT # Homekit Protocol iptables -A INPUT -p tcp -m multiport --dports 51827 -j ACCEPT # Home Assistant interface iptables -A INPUT -p tcp -m multiport --dports 8123 -j ACCEPT