How to force DNS for specific clients?

7,113

For what it's worth, here's how I got this working (mostly). First, I made sure all the devices that I didn't want to use OpenDNS had hostnames. Next I added "home" as the Domain Name in Router Identification (it won't work without this). I then added the following firewall script:

# For certain devices, use default LAN DNS
# #############################################################
iptables -t nat -A PREROUTING -i br0 -s xxxx_Family_PC.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxx_Family_PC.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-Laptop.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-Laptop.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s Chromecast.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s Chromecast.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-Galaxy-Note.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-Galaxy-Note.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-HTC-One-M8.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-HTC-One-M8.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr) 
iptables -t nat -A PREROUTING -i br0 -s Roku.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s Roku.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s Sharp-Aquos-HDTV.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s Sharp-Aquos-HDTV.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxxsiPhone2.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxxsiPhone2.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-MacBook.home -p tcp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)
iptables -t nat -A PREROUTING -i br0 -s xxxxxx-MacBook.home -p udp --dport 53 -j DNAT --to $(nvram get lan_ipaddr)

# For every other client, use OpenDNS (including guest network - br1).
# #############################################################
iptables -t nat -A PREROUTING -i br0 -p udp --dport 53 -j DNAT --to 208.67.220.220
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 53 -j DNAT --to 208.67.220.220
iptables -t nat -A PREROUTING -i br1 -p udp --dport 53 -j DNAT --to 208.67.220.220
iptables -t nat -A PREROUTING -i br1 -p tcp --dport 53 -j DNAT --to 208.67.220.220

This gets me pretty much what I wanted. The only thing lacking is that clients that don't match the first section (and so get the OpenDNS ip) don't have a secondary dns in case the first one is down. There's just no way to specify that using this method. Still, it works 99.99% of the time which is going to have to be good enough. Those last two lines for br1 ensure that anyone connecting to my guest network are forced to use OpenDNS as well.

Share:
7,113
Jaroslav
Author by

Jaroslav

Updated on September 18, 2022

Comments

  • Jaroslav
    Jaroslav over 1 year

    I'm running Shibby's Tomato firmware on my ASUS RT-N66U. What I'm trying to do is force OpenDNS IP's for certain clients (i.e. my kids) based on MAC address, while other clients get the router's default values. So far, so good (mostly). Here is the Dnsmasq script I'm using to do this:

    # Assign alternate DNS for select hosts
    # Set Specific Clients to be affected
    dhcp-mac=set:altdns,XX:XX:XX:XX:XX:XX # kids laptop
    dhcp-mac=set:altdns,XX:XX:XX:XX:XX:XX # kids ipod
    
    # Set Alternate DNS
    dhcp-option=tag:altdns,option:dns-server,208.67.220.220,208.67.222.222
    

    This works great... on the 2.4Ghz band. If they connect to the 5Ghz band they get the router's default DNS entries.

    Question #1: Is there a way to make this script apply to both 2.4Ghz (eth1) and 5Ghz (eth2)? Failing that, does Tomato allow me to whitelist devices for the 5Ghz band? I can whitelist/blacklist for wireless in general, but I don't see how to do this for one or the other.

    I can always just use a different key for 5Ghz, so that's not a huge deal. The bigger loophole is that this only works with DHCP. Changing the DNS settings on the laptop completely bypasses this. My 12yo son is getting to the point that he could figure this out without much trouble.

    Question #2: How can I force DNS for a particular client if they're not using DHCP? I was thinking some sort of Firewall rule only allowing DNS traffic to specific IP's for specific MAC addresses or something, but I have no idea how to go about that. Alternatively, is there any way to force DHCP (or block certain clients if they aren't using DHCP)?

    • Jaroslav
      Jaroslav over 9 years
      Just wanted to add that "Intercept DNS" works, but there's no way to limit it to certain clients. Is there a way to accomplish the same thing for only select clients using iptables?
  • DavidPostill
    DavidPostill over 9 years
    This is not an answer to the original question. It should be a comment to the original question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient reputation you will be able to comment on any post.
  • Dan H
    Dan H almost 8 years
    Thanks for sharing this. An alternative to setting up hostnames and the domain name is to reference static IPs. That's the method I'm using and it's working great.