This is the second post in a series that highlights interesting new features of the PowerDNS 4.x.x and dnsdist 1.x.x releases.
As noted previously, in some organizations it is desirable to filter access to some domains (malware, advertising, ‘adult’ etc) for some users or subscribers. In our previous post we showed how to use common DNS blocking lists to offer adblocking for users of your resolver.
A problem however for other kinds of filtering is that subscribers typically share a single IP address among all their devices. This makes it hard to provide ‘parental control’ to the kids’ tablets, but not to other computers in the household. (Note: we realize not everyone likes parental controls or other forms of DNS filtering. In the real world however, it is something people want, and PowerDNS is technology to make such things possible!)
Now, it would be easy if we could do selective filtering based on the device’s MAC address, but this MAC address is not visible from the nameserver. All we see is the MAC address of our router, not that of your devices.
It turns out however that various home routers and cable modems (‘CPEs’) have the option to embed requestor MAC addresses into DNS queries themselves. This allows a service provider to conditionally filter DNS based on this MAC address.
A quick survey discovered that different vendors embed the MAC address or other ‘user identifiers’ differently, and for this reason PowerDNS support for this feature is dynamic.
First, we’ll use dnsdist to embed the MAC address in queries. The natural and universally chosen mechanism for this is an EDNS option, and we can configure dnsdist to add the MAC address like this:
This makes dnsdist listen on port 53 and forward all queries to 192.168.5.123:5300. With the last line, we add the MAC address of the requestor to all queries using EDNS option code point 65001 (5 is also used sometimes). We could restrict this to certain IP addresses if we wanted, or hash or truncate the MAC address for increased privacy. In a typical setup, this configuration is how dnsdist would run on a subscriber’s CPE.
Next up we need to configure the PowerDNS Recursor with our filtering instructions:
These lines implement a set of bad domains, in this case everything within the TLD “xxx”. Secondly, for two IP addresses we list some MAC addresses that desire filtering. 192.168.5.24 is in this case for the dnsdist configuration listed above.
Now to make use of these filters:
This first defines macPrint() to pretty print the binary encoded MAC address. Secondly, we use the PowerDNS Recursor Lua hook ‘preresolve’ to intercept incoming queries. Then we check if there is an embedded MAC address in EDNS option 65001, and if there is, we look up if for that IP address, we have that MAC address listed.
If so, and the query is part of our ‘baddomains’ list, we return a CNAME to a server which would then inform the user their request got blocked:
The last two lines are from a host with a different MAC address which is not filtered.
Takeaway
With the configuration outlined above, it is easily possible to provide per-device DNS filtering instructions for each subscriber. As shown, this configuration is not very dynamic. PowerDNS however has multiple ways to retrieve such filtering instructions, either from remote servers or from local indexed files.
Please do not hesitate to contact us if you need help integrating PowerDNS with your existing domain categorization lists, customer database or CPE deployed base! We have solutions that make this work out of the box.
Enjoy!
