How would one configure BIND on a Linux system to forward DNS queries to a different upstream forwarder, based upon the source IP and/or MAC of the requesting host?

For example, I might want to send DNS queries from certain hosts on my network to OpenDNS, others to Google, and all others to my ISP.

  • 1
    You wouldn't do it in bind - you'd do it with iptables. Assuming NAT, etc. is already set up and working, then it would be a series of new rules if the destination is port 53 and the source is ip-range/MAC then forward to ... – ivanivan Jan 26 '17 at 2:40
  • 1
    I would set up the dhcp server on the network to just give different dns servers to the different clients. If there are reasons why this doesn't work then you need to provide more information on how your systems are configured, in particular is the bind server authoritative, recursive, caching, ... ? – icarus Jan 26 '17 at 4:39
  • @ivanivan I could be wrong but I don't believe forwarding the original request using iptables would work. The DNS server needs to issue a new (recursive) query to its upstream resolver, then provide the answer back to the original requester. – Timbo Jan 26 '17 at 19:08
  • @icarus I thought of that however if I do that I can't change it on the fly. Once DNS is assigned by DHCP the clients will keep using it until their lease expires. The application is a home DNS server that provides filtered DNS queries via OpenDNS to children's devices (no porn, TV, social media, etc), and unfiltered DNS to parents. I want to be able to change it on the fly, for example cut off kids' access at bedtime. I posted this question on linuxquestions.org and was told to use "views" in BIND, however I have not researched that yet – Timbo Jan 26 '17 at 20:19
  • Sounds like you are mixing up several things. You can turn down the dhcp lease times as bedtime approaches, or just set 10 minutes anyhow. Many home routers have facilities to restrict internet access to particular mac addresses based on time of day. You don't tell us how tech savvy the children are, you might be in a war that you can't win. Good luck. – icarus Jan 27 '17 at 1:30

The solution is BIND "views". You can filter on source or destination IP and route the request to a view. You can provide completely different DNS zones, forwarders, and other handling options.



I had the same use case, I did it as follows (albeit a bit convoluted, it works pretty well).

  • Router runs DNS over TLS via a DoT client which forwards to nextdns.io. I block ads and stuff via this service.
  • 2 x dnsmasq containers on an inside linux box, bound to different internal IPs on that same box. They forward queries to the router, and out to the internet over TLS.
  • 1 dnsmasq does adult DNS + DHCP, the second only kids DNS. The first sets different DNS options on DHCP response based on the MAC address of the requesting client -- I configure my kids devices specifically to get the DNS of my second, restricted, dnsmasq container, adults get the other one.
  • The second dnsmasq container only serves a restricted set of kid-friendly domains and returns for the rest.

As an aside, I also set up some IP tables to force all requests accross my router to go over TLS to handle badly behaved clients that hardcode or similar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.