mDNS, or multicast DNS, is a way to discover devices on your network at
.local domain without any central DNS configuration (also known as ZeroConf and Bonjour, etc). Fedora Magazine has a good article on setting it up in Fedora, which I won’t repeat here.
If you’re like me, you’re using OpenWRT with multiple VLANs to separate networks. In my case this includes my home automation (HA) network (VLAN 2) from my regular trusted LAN (VLAN 1). Various untrusted home automation products, as well as my own devices, go into the HA network (more on that in a later post).
In my setup, my OpenWRT router acts as my central router, connecting each of my networks and controlling access. My LAN can access everything in my HA network, but generally only establish related TCP traffic is allowed back from HA to LAN. There are some exceptions though, for example my Pi-hole DNS servers which are accessible from all networks, but otherwise that’s the general setup.
With IPv4, mDNS communicates by sending IP multicast
UDP packets to
18.104.22.168 with source and destination ports both using
5353. In order to receive requests and responses, your devices need to be running an mDNS service and also allow incoming UDP traffic on port
As multicast is local only, mDNS doesn’t work natively across routed networks. Therefore, this prevents me from easily talking to my various HA devices from my LAN. In order to support mDNS across routed networks, you need a proxy in the middle to transparently send requests and responses back and forward. There are a few different options for a proxy, such as
igmpproxy, but i prefer to use the standard Avahi server on my OpenWRT router.
Keep in mind that doing this will also mean that any device in your untrusted networks will be able to send mDNS requests into your trusted networks. We could stop the mDNS requests with an application layer firewall (which iptables is not), or perhaps with connection tracking, but we’ll leave that for another day. Even if untrusted devices discover addresses in LAN, the firewall is stopping the from actually communicating (at least on my setup).
Set up Avahi
Log onto your OpenWRT router and install Avahi.
opkg update opkg install avahi-daemon
There is really only one thing that must be set in the config, and that is to enable
reflector (proxy) support. This goes under the
[reflector] section and looks like this.
While technically not required, you can also set which interfaces to listen on. By default it will listen on all networks, which includes WAN and other VLANs, so I prefer to limit this just to the two networks I need.
On my router, my LAN is the
br-lan device and my home automation network on VLAN 2 is the
eth1.2 device. Your LAN is probably the same, but your other networks will most likely be different. You can find these in your router’s Luci web interface under
Interfaces. The interfaces option goes under the
[server] section and looks like this.
Now we can start and enable dbus and the Avahi service!
/etc/init.d/dbus start /etc/init.d/dbus enable /etc/init.d/avahi-daemon start /etc/init.d/avahi-daemon enable
OK that’s all we need to do for Avahi. It is now configured to listen on both LAN and HA interfaces and act as a proxy back and forth.
As mentioned above, devices need to have incoming
5353 open. In order for our router to act as a proxy, we must enable this on both LAN and HA network interfaces (we’ll just configure for all interfaces). As mDNS multicasts to a specific address with source and destination ports both using 5353, we can lock this rule down a bit more.
Log onto your firewall Luci web interface and go to
Traffic Rules tab. Under
Open ports on router add a new rule for mDNS. This will be for
UDP on port
Find the new rule in the list and edit it so we can customise it further. We can set the source to be any zone, source port to be
5353, where destination zone is the
Device (input) and the destination address and port are
5353. Finally, set action should be
accept. If you prefer to not allow all interfaces, then create two rules instead and restrict source zone for one to LAN and to your untrusted network for the other. Hit
Save & Apply to make the rule!
We should now be able to resolve mDNS from LAN into the untrusted network.
To test it, ensure your Fedora computer is configured for mDNS and can resolve yourself. Now, try and ping a device in your untrusted network. For me, this will be
study.local which is one of my home automation devices in my study (funnily enough).
When my computer in LAN tries to discover the device running in the study, the communication flow looks like this.
- My computer (
192.168.0.125) on LAN tries to ping
study.localbut needs to resolve it.
- My computer sends out the mDNS UDP multicast to
22.214.171.124:5353on the LAN, requesting address of
- My router (
192.168.0.1) picks up the request on LAN and sends same multicast request out on HA network (
- The study device on HA network picks up the request and multicasts the reply of
126.96.36.199:5353on the HA network.
- My router picks up the reply on HA network and re-casts it on LAN.
- My computer picks up the reply on LAN and thus learns the address of the study device on HA network.
- My computer successfully pings
10.0.0.202from LAN by routing through my router to HA network.
This is what a packet capture looks like.
16:38:12.489582 IP 192.168.0.125.5353 > 188.8.131.52.5353: 0 A (QM)? study.local. (35) 16:38:12.489820 IP 10.0.0.1.5353 > 184.108.40.206.5353: 0 A (QM)? study.local. (35) 16:38:12.696894 IP 10.0.0.202.5353 > 220.127.116.11.5353: 0*- [0q] 1/0/0 (Cache flush) A 10.0.0.202 (45) 16:38:12.697037 IP 192.168.0.1.5353 > 18.104.22.168.5353: 0*- [0q] 1/0/0 (Cache flush) A 10.0.0.202 (45)
And that’s it! Now we can use mDNS to resolve devices in an untrusted network from a trusted network with zeroconf.