Chromecast, Home Assistant & different subnets
I'm using Home Assistant a lot these days to automate things around the house. One of the things that is interesting to know is the current state of my Chromecast devices - so I can turn on or off the stereo amplifier (or lamps in the same room ) if something is playing, for example.
As I try to pretend to have a security posture, I've tried to move IoT devices from my main client subnet. Chromecast devices aren't designed for dorks like me, and they expect to be in the same broadcast domain as the client devices that will control them…so you have to be a bit creative to make it work.
TL;DR
- You have to allow 1900/udp with destination address 239.255.255.250 from both networks
- You have to reflect mDNS between the networks (which means more ports)
- Update: you need to enable 8008-8009/tcp as well
Ports
I'm using nftables but you should get the idea:
# This is obviously not a complete example...
define homeassistant_if = eth0
define chromecast_if = eth1
define homeassistant_host = 192.168.0.2
chain firewall_out {
type filter hook output priority 100; policy drop;
# ...
oifname $chromecast_if udp dport 5353 ip daddr 244.0.0.251 ct state new accept
oifname $homeassistant_if udp dport 5353 ip daddr 244.0.0.251 ct state new accept
}
chain firewall_in {
type filter hook input priority 0; policy drop;
# ...
iifname $chromecast_if udp dport 5353 ip daddr 244.0.0.251 ct state new accept
iifname $homeassistant_if udp dport 5353 ip daddr 244.0.0.251 ct state new accept
}
chain chromecast_forwarding {
type filter hook forward priority 0; policy drop;
tcp dport { 8008, 8009 } ip saddr $homeassistant_host ct state new accept
}
chain chromecast_out {
type filter hook forward priority 0; policy drop;
# mdns
udp dport 5353 ip daddr 224.0.0.251 ct state new accept
}
chain homeassistant_out {
type filter hook forward priority 0; policy drop;
# ssdp
udp dport 1900 ip daddr 239.255.255.250 ct state new accept
# mdns
udp dport 5353 ip daddr 224.0.0.251 ct state new accept
}
Update: The scary part here is that I have no idea why it's enough to just enable 8008-8009/tcp in the forwarding chain for the chromecast network..? I should really try to understand why that works…
mDNS
This is fairly simple as well, install and enable avahi on your machine, do some basic configuration:
# /etc/avahi/avahi-daemon.conf - but just the important changes
[server]
allow-interfaces=chromecast_if,homeassistant_if
[reflector]
enable-reflector=yes
Testing
I setup a FreeBSD jail1 in each subnet and installed avahi-app on both. You can either use the nss_mdns
adapter (and then host(1)
or ping(8)
) or avahi-browse
to test it. I've only had partial success with the nsswitch.conf
changes so I got lazy and just used avahi-app
(rather that reading the manual).
# pkg install nss_mdns
# /etc/nsswitch.conf
# Add mdns to the end of the hosts line, like this:
hosts: files dns mdns
# or, if that doesn't work:
# pkg install avahi-app
# service dbus enable
# service dbus start
# service avahi-daemon enable
# service avahi-daemon start
# avahi-browse -a --ignore-local --terminate
If you can use ping to resolve .local
addresses, you should be fine. If the system configuration doesn't like using mdns, try avahi-browse instead and see if you list non-local hosts with it. It should return a list that looks something like this:
# avahi-browse -a --ignore-local --terminate
+ epair0b IPv4 testwifi _ssh._tcp local
+ epair0b IPv4 testwifi _sftp-ssh._tcp local
+ epair0b IPv4 CCCC12312312@Audio+ _raop._tcp local
+ epair0b IPv4 CCCC23423423@SHIELD+ _raop._tcp local
+ epair0b IPv4 googlerpc _googlerpc._tcp local
+ epair0b IPv4 Chromecast-Audio-$uuid _googlecast._tcp local
+ epair0b IPv4 SHIELD-Android-TV-$uuid _googlecast._tcp local
+ epair0b IPv4 SHIELD _nv_shield_remote._tcp local
+ epair0b IPv4 SHIELD _androidtvremote2._tcp local
+ epair0b IPv4 $uuid _googlezone._tcp local
+ epair0b IPv4 Homeassistant-instance-name _home-assistant._tcp local
+ epair0b IPv4 HASS Bridge xyzyxzyxz _hap._tcp local
+ epair0b IPv4 homeassistant [longstring] _workstation._tcp local
+ epair0b IPv4 router [00:ma:ca:dd:r] _workstation._tcp local
Conclusions
This Works For Me™ and might help someone else. I can now poll and control my Chromecast devices from my Home Assistant installation.
Footnotes
as my FreeBSD machine handles DHCP for both subnets both vlans were easily accessible on that machine already. It was also the easiest way I could think off