Broadcast mDNS across multiple network

My HA setup involves multiple networks.

  1. Network with internet where all the home devices connect to.
  2. Network without internet where all the IOT devices connect to.
  3. Virtual Network that bridges host machine with HAOS running in a hyper-v

Some of the devices I own like (ecobee, abode, etc) will connect only through Apple Homekit. However, mDNS doesnt discover devices outside its network and HA doesnt have the ability to integrate devices from multiple network.

So with absolutely no knowledge on Python, I leveraged zeroconf and wrote this tiny program that could help broadcast mDNS over all the networks and thereby allowing you to discover devices from all the networks.

Jebarson/MdnsBroadcaster: MdnsBroadcaster is a lightweight Python program that forwards mDNS traffic between multiple network interfaces.

I use Avahi (https://avahi.org/) to bridge mDNS across my vlans. There are some threads in this forum discussing it’s use (search for Avahi).

I believe avahi as a tool works only in linux though? My set up runs on windows and hyper-v. I believe I looked at both avahi and zeroconf before deciding to use zeroconf to write the script.

I think your tool is a great contribution. I was just pointing out (to others who might search for a solution) that there are other options.

Nah, I wasn’t questioning your intention. I am genuinely interested in knowing how avahi works and its limitations just in case I overlooked something obvious

You are correct that Avahi is targeted at Linux / BSD-like systems. I do not know enough about Avahi to speak to its limitations.

It was easy for me to install and configure Avahi on my pfSense firewall to allow control of my Chromecast devices (on my IoT network) from my secure network. I do not do mDNS bridging for Home Assistant to discover devices. I keep HA and all my IoT devices on the same IoT VLAN and I believe this is the best practice for managing HA and its associated devices (along with device and protocol specific firewall rules).

Interesting. How do you expose HA without connecting to your main network (the one with internet) and connect to things such as remote browsing, home device control / access?

The IoT network firewall rules restrict IoT device access to the IoT VLAN - IoT devices, including Home Assistant, can’t “see” my other VLANs. My “main” network has access the IoT network (but not the other way around); therefore, anything on my “main” network can establish a connection to stuff on the IoT network.

I don’t think of it as “exposing” HA to my other networks, I think of it as controlling the flow of connections (who can initiate a connection to where).

Got it. That’s indeed very cool.

I did initially think about it but then the amount of devices that I will need to manage just scared me enough to create separate networks. But I know that there is a huge amount of people who would rather use firewall to control access to devices instead of complicating the network like I did.

Thanks for sharing your setup.

Have a look at this…
No need Avahi

https://www.reddit.com/r/PFSENSE/comments/nhhhfu/mdns_not_working_across_subnets/

New to HA and also had this problem. Initially I resorted to GitHub - dennypage/mdns-bridge: mDNS Bridge · GitHub, but then I came across The kernel itself can do this · Issue #12 · udp-redux/udp-broadcast-relay-redux · GitHub and realised that I could just use nftables too. Here are the details and it should work on any Linux-based routers running a recent enough kernel.

My setup / what I need:

  • Two VLANs: lan and iot
  • IPv6 ULA-prefix fd00:abcd:abcd::/48
  • HA running in lan (192.168.10.1/24, fd00:abcd:abcd:10::1/60)
  • Devices running in iot (192.168.20.1/24, fd00:abcd:abcd:20::1/60)
  • HA should see iot devices
  • Devices in iot should not see any lan devices

So basically I want to clone mDNS queries from lan to iot, and then clone responses from iot back to lan.

To achieve this, add this to your rule set:

destroy table ip mdns
table ip mdns {
	counter lan_query {
	}
	counter lan_response {
	}

	counter iot_query {
	}
	counter iot_response {
	}

	chain prerouting {
		type filter hook prerouting priority mangle; policy accept;
		udp dport 5353 iif "br-lan" 	@ih,16,1 { 0 }	ip saddr set 192.168.20.1 dup to 224.0.0.251 device "br-iot"	counter name "lan_query" 	comment "mDNS query from br-lan"
		udp dport 5353 iif "br-lan" 	@ih,16,1 { 1 } 																	counter name "lan_response" comment "mDNS response from br-lan"
		udp dport 5353 iif "br-iot" 	@ih,16,1 { 0 }	 																counter name "iot_query" 	comment "mDNS query from br-iot"
		udp dport 5353 iif "br-iot" 	@ih,16,1 { 1 } 	ip saddr set 192.168.10.1 dup to 224.0.0.251 device "br-lan" 	counter name "iot_response" comment "mDNS response from br-iot"
	}
}

destroy table ip6 mdns
table ip6 mdns {
	counter lan_query {
	}
	counter lan_response {
	}

	counter iot_query {
	}
	counter iot_response {
	}

	chain prerouting {
		type filter hook prerouting priority mangle; policy accept;
		udp dport 5353 iif "br-lan" 	@ih,16,1 { 0 }	ip6 saddr set fd00:abcd:abcd:20::1 dup to ff02::fb device "br-iot"	counter name "lan_query" 	comment "mDNS query from br-lan"
		udp dport 5353 iif "br-lan" 	@ih,16,1 { 1 } 																		counter name "lan_response"	comment "mDNS response from br-lan"
		udp dport 5353 iif "br-iot" 	@ih,16,1 { 0 }	 																	counter name "iot_query" 	comment "mDNS query from br-iot"
		udp dport 5353 iif "br-iot" 	@ih,16,1 { 1 } 	ip6 saddr set fd00:abcd:abcd:10::1 dup to ff02::fb device "br-lan"	counter name "iot_response" comment "mDNS response from br-iot"
	}
}

@ih,16,1 matches the message type bit in mDNS. 0 = query, 1 = response.

You can save this file as mdns.nft then load it with nft -f mdns.nft. Of course there are usually more idiomatic ways to do this in your router's distro.


more idiomatic ways

I use OpenWRT and this is how I make this persistent:

  1. Back up your current config first of all
  2. Predictable IPv6
    a. uci set network.lan.ip6hint='10'
    b. uci set network.iot.ip6hint='20'
    c. uci commit
    d. Restart the interfaces / Reboot the router
    e. Confirm the results with ip addr show br-lan # or br-iot
  3. Save the nftables to /etc/nftables.inc/mdns.nft
  4. Edit /etc/config/firewall, and add this to the end:
    config include
    	option type 'nftables'
    	option path '/etc/nftables.inc/mdns.nft'
    	option position 'ruleset-post'
    
  5. Run fw4 check to make sure there are no issues
  6. Run fw4 reload and confirm the results with nft list table ip mdns / nft list table ip6 mdns
  7. Finally add /etc/nftables.inc/ to /etc/sysupgrade.conf

Bonus: I saw a lot of people struggle with Tuya broadcast across VLANs. This too can be solved by nftables:

destroy table ip tuya
table ip tuya {
	chain prerouting {
		type filter hook prerouting priority mangle; policy accept;
		udp dport 6666 iif "br-iot" ip saddr != 192.168.10.1 ip saddr != 192.168.20.1 dup to 192.168.10.1 device "br-lan" counter comment "Tuya 3.1 UDP"
		udp dport 6667 iif "br-iot" ip saddr != 192.168.10.1 ip saddr != 192.168.20.1 dup to 192.168.10.1 device "br-lan" counter comment "Tuya 3.3 UDP Encrypted"
	}
}