DNS Forwarder Domain Overrides - Scheduling?



  • What might be a reasonable way to use a different DNS server to forward to at different times in a day/week?

    We use OpenDNS (whose servers are configured under General Setup - DNS Server Settings) for web content filtering, and are fairly satisfied with it. Sometimes we may want to not do any filtering for certain domains – for example, if we leave google.com and apple.com to resolve from OpenDNS, the respective google play (android) and itunes (apple) app stores get blocked by our desire to block "movies" and "games" categories on OpenDNS. This is perfectly fine, but at certain times of the day we would like to allow everything through for google and apple, and we can do that manually by adding domain overrides in pfSense's DNS Forwarder for google.com and apple.com, and setting the "IP address of the authoritative DNS server for this domain" to our local ISP's DNS server, which doesn't filter anything.

    Now how can we automatically schedule the above?

    dnsmasq's host overrides are in the /etc/hosts file. Where are the domain overrides kept? I can't seem to be able to find them -- would have been willing to do some simple script / cron job to add in/remove the relevant entries into a configuration file, but... not sure where that is!

    Or any other ideas on how to achieve scheduling of the DNS server to use for resolving particular domains.

    IP address of the authoritative DNS server for this domain



  • It seems domain overrides are done by dnsmasq as indicated below (from http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html). Now how does pfsense convey this information to dnsmasq, simply passing parameters read from config.xml when starting the dnsmasq service?
    –-------------------------------------------

    -S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source-ip>|<interface>[#<port>]]

    Specify IP address of upstream servers directly. Setting this flag does not suppress reading of /etc/resolv.conf, use -R to do that. If one or more optional domains are given, that server is used only for those domains and they are queried only using the specified server. This is intended for private nameservers: if you have a nameserver on your network which deals with names of the form xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving the flag -S /internal.thekelleys.org.uk/192.168.1.1 will send all queries for internal machines to that nameserver, everything else will go to the servers in /etc/resolv.conf. DNSSEC validation is turned off for such private nameservers, UNLESS a –trust-anchor is specified for the domain in question. An empty domain specification, // has the special meaning of "unqualified names only" ie names without any dots in them. A non-standard port may be specified as part of the IP address using a # character. More than one -S flag is allowed, with repeated domain or ipaddr parts as required.
    More specific domains take precendence over less specific domains, so: --server=/google.com/1.2.3.4 --server=/www.google.com/2.3.4.5 will send queries for *.google.com to 1.2.3.4, except *www.google.com, which will go to 2.3.4.5

    The special server address '#' means, "use the standard servers", so --server=/google.com/1.2.3.4 --server=/www.google.com/# will send queries for *.google.com to 1.2.3.4, except *www.google.com which will be forwarded as usual.

    Also permitted is a -S flag which gives a domain but no IP address; this tells dnsmasq that a domain is local and it may answer queries from /etc/hosts or DHCP but should never forward queries on that domain to any upstream servers. local is a synonym for server to make configuration files clearer in this case.

    IPv6 addresses may include a %interface scope-id, eg fe80::202:a412:4512:7bbf%eth0.

    The optional string after the @ character tells dnsmasq how to set the source of the queries to this nameserver. It should be an ip-address, which should belong to the machine on which dnsmasq is running otherwise this server line will be logged and then ignored, or an interface name. If an interface name is given, then queries to the server will be forced via that interface; if an ip-address is given then the source address of the queries will be set to that address. The query-port flag is ignored for any servers which have a source address specified but the port may be specified directly as part of the source address. Forcing queries to an interface is not implemented on all platforms supported by dnsmasq.</port></interface></source-ip></port></ipaddr></domain>



  • This thread seems to suggest there is no way to do except directly editing the config.xml file and reloading the service:

    https://forum.pfsense.org/index.php?topic=71861.0

    Are there any options to pass additional/new parameters to dnsmasq while it's running with the parameters already passed to it when pfsense starts it? Or replicate the command that pfsense uses to start dnsmasq, and add in the customizations on top of that, perhaps in a separate cronjob?


  • Banned

    This is not the way to do it. You can use scheduled firewall rules with NAT to redirect DNS queries on local interfaces to different DNS servers depending on time. See https://doc.pfsense.org/index.php/Redirecting_all_DNS_Requests_to_pfSense for basic concept. (Obviously needs the schedules added.)



  • @doktornotor:

    This is not the way to do it. You can use scheduled firewall rules with NAT to redirect DNS queries on local interfaces to different DNS servers depending on time. See https://doc.pfsense.org/index.php/Redirecting_all_DNS_Requests_to_pfSense for basic concept. (Obviously needs the schedules added.)

    This would seem to redirect every DNS query to a different DNS server based on firewall rules. We have already achieved blocking of queries to anything except our own DNS forwarder. Certainly we can switch that on or off based on firewall rules.

    However, what we want is slightly different:

    Day: ".apple.com" gets resolved by the DNS server at 208.67.222.222 and ".yahoo.com" gets resolved by the DNS server at 8.8.8.8 (let's say).

    Night: ".apple.com" gets resolved by the DNS server at 8.8.8.8 and ".yahoo.com" gets resolved by the DNS server at 8.8.8.8 (let's say).

    Essentially: we only want queries that are querying to resolve certain domains (e.g. "apple.com") to send only those specific queries to different servers. This is also easily doable using domain overrides in the DNS forwarder with the dnsmasq options "–server=/apple.com/208.67.222.222" or "--server=/apple.com/8.8.8.8" depending on whether we want to send that query to OpenDNS (that can block certain subdomains of that depending on our web content filtering categories) or some other DNS like google's DNS (which will resolve it all no matter what the subdomain). This all works great. We just want to be able so "schedule" it.

    I realize every DNS query can easily be redirected in bulk using firewall rules for port 53, but unless I'm missing something, I don't see how a firewall rule can specifically match a DNS query where the originating device is querying DNS for a specific domain to query, e.g. *.apple.com, and leave others alone.

    pFSense doesn't use dnsmasq.conf, so there's nothing we can do with that directly. The only way seems to be adding in the --server parameters into the 'custom options' box of the DNS Forwarder in the GUI, or editing that related entry in pfSense's config.xml directly (i.e. writing a script to do that, and run the script as a scheduled cron job).

    It would be lovely if there's a better way, and I'm completely open to learning something new, but I couldn't see how firewall rules could do this, unless it involves policy filtering (tagging packets with one rule and then having those packets filtered using another rule).


  • Banned

    You did not get me. You need to schedule the redirect of the queries to two different resolvers. This can even be a forwarder and resolver on pfSense itself, they can run together, just using different ports.

    Other than that, no, there is no method to do this, plus even with the above, you cannot expect it will get switched from minute to minute, there are DNS caches in client OS, there are DNS caches in browsers, and there is TTL that generally gets respected by those.



  • @doktornotor:

    You did not get me. You need to schedule the redirect of the queries to two different resolvers. This can even be a forwarder and resolver on pfSense itself, they can run together, just using different ports.

    Thank you for the follow up! I can see how we can use two different forwarder/resolvers and manage these through firewall rules, and even schedule them.

    I was stuck because see any mechanism by which the rule could be configured to inspect what the initiating host is querying for… at the level of a DNS query, there is not yet any traffic to *.apple.com (for example)… it is traffic to the DNS server about *.apple.com (what is it's IP address?).

    Now what I'm understanding is that we simply set up two forwarder/resolvers and have the domain override settings in each be slightly different. Then schedule firewall rules accordingly. Will try it out, thanks!

    Other than that, no, there is no method to do this, plus even with the above, you cannot expect it will get switched from minute to minute, there are DNS caches in client OS, there are DNS caches in browsers, and there is TTL that generally gets respected by those.

    Our approach seems to work great despite DNS caches, or a service like OpenDNS would not be very useful within reasonable timescales. All devices, browsers, apps etc. - the effects are very quick, so we're very satisfied with using DNS for web content filtering.



  • Hi,

    You need a package called "Cron", must use DNS Resolver, and a bit of coding.

    To achieve your desired results, you need to create two files. One file for te 8.8.8.8 and the other is for the 208.67.222.222. No need to use wildcards. Domain overrides will get only the root domain for the rest of the FQDN/subdomains etc. By default the "/var/unbound/domainoverrides.conf" is empty. We will going to use this file.

    First create a folder for the "Day" and "Night" folders and put it on the "root" directory.

    Day folder: Create a file and name it "domainoverrides.conf":

    forward-zone:
    	name: "facebook.com"
    	forward-addr: 208.67.222.222
    forward-zone:
    	name: "yahoo.com"
    	forward-addr: 8.8.8.8
    

    Night folder: Create a file and name it "domainoverrides.conf":

    forward-zone:
    	name: "apple.com"
    	forward-addr: 8.8.8.8
    forward-zone:
    	name: "yahoo.com"
    	forward-addr: 8.8.8.8
    

    Create this file and name it like "dayandnightDNS" and put it on your root directory:

    ********* to be continued later im too sleepy *********