4

Hopefully this is possible to do.

The question

Is it possible to configure a DNS server that is authorative for a given domain, to "fallback" and recurse via Forwarders / Root Hints when it cannot find the record locally?

The scenario

To give a concrete scenario, imagine a private (internal) network that is served by an internal Active Directory-backed DNS server (10.10.10.10) for the domain poorlyplanned.com

Internal clients that query for records like hostgroupA.poorlyplanned.com get their answer from the local internal DNS server (10.10.10.10). Queries from internal clients for other domains are recursively resolved via the internal DNS server (10.10.10.10) using forwarders/root hints.

Additionally, there is a public DNS server (large highly available load balanced servers actually), say at IP 1.2.3.4 and is authorative for the same domain name poorlyplanned.com.

External clients that query for records go directly to the public DNS server at 1.2.3.4 for resolution. For example, a public query for webserverX.poorlyplanned.com is resolved directly from public DNS server 1.2.3.4 and returns say 50.51.52.53 to the client. When I say resolved directly, I mean that the NS records point to the public DNS server and the query is not going via the internal server (it isn't publicly accessible anyway).

The internal DNS gets populated with private DNS records for poorlyplanned.com that are not intended to be publicly resolvable, whereas the external DNS gets populated with public DNS records (for the same domain) that should be publicly resolvable.

So far, pretty standard DNS stuff, though arguably not ideal.

The problem

Internal clients cannot resolve public DNS records like webserverx.poorlyplanned.com because these records are not defined on the internal DNS server. Since the internal DNS server is authorative for the same poorlyplanned.com domain, it simply returns a 'DNS record not found' result after looking at the internal records only - as authorative DNS server normally do.

A constraint we have is that the public DNS server is administered by a 3rd party and has frequent churn, making it a very hard task to manually maintain a duplicate set of records on the internal DNS server, without dropping the ball.

As a workaround, we tried adding additional client-side DNS lookup server entries pointing to the external DNS servers (in an attempt to supplement the internal DNS servers) but that doesn't work because both are authorative and the client doesn't try subsequent servers on the list once one returns with a result.

Split-brain or horizontal configurations are not feasible either because those have both servers containing the same DNS records, just with different IPs or can share zone files.

However, if it were possible to have the internal DNS server recursively resolve via forwarder/root hints when it cannot find the record locally that would work a charm. But how?

I realise that if the internal domain was originally configured with some sub-domain offset like int.poorlyplanned.com then we don't have a problem. Unfortunately the scale of the resources already deployed and the sites involved, is prohibitive of such a change.

Surely this isn't a unique problem?

I hope I've expressed myself clearly enough - please let me know if I can help clarify.

Thanks for reading/helping!

Jaans
  • 173
  • 8
  • Do you have access to the external DNS (can you do configurations on it ) or is it managed by another entity ? – Soulimane Mammar Mar 06 '19 at 13:03
  • @SoulimaneMammar It is administered by the 3rd party, but we can request record changes/additions to be made. – Jaans Mar 06 '19 at 13:05
  • This isn't possible with Windows DNS as far as I'm aware. – joeqwerty Mar 06 '19 at 13:15
  • @joeqwerty I don't know much about `bind` or the like I'm afraid, but if we were to use a `*nix` based DNS server internally, would that maybe be viable? – Jaans Mar 06 '19 at 13:37
  • Unfortunately, I also don't know anything about Linux/Unix. – joeqwerty Mar 06 '19 at 13:41
  • 2
    DNS servers aren't going to recursively resolve for zones they are authoritative for. But you may be able to create pinpoint zones for the records, and specify the public name servers for the zone. – Greg Askew Mar 06 '19 at 13:55
  • Is the external DNS using BIND ? – Soulimane Mammar Mar 06 '19 at 14:19
  • 1
    Additionally, you should not mix internal/external DNS servers on clients. Clients should resolve names on your internal DNS servers ONLY. It is not "not working" because both zones are authoritative, its "not working" because DNS clients don't just keep checking all their DNS server entries when one name is returned as not found. – Semicolon Mar 06 '19 at 15:56
  • 1
    Normally mixing authoritative and recursive is a bad idea for a lot of reasons, which is why setup like yours are not really possible (except in some cases/proposals where an authoritative would need to fetch data like to emulate CNAME at apex, but this is exactly why there is a lot of pushback). The core of your poblem is that you have two authoritative nameservers for a given zone, which do not server the same content. This is the core issue to fix, going around that will only yield more problems. But look at bind RPZ feature and also at dnsmasq software. – Patrick Mevzek Mar 06 '19 at 20:31
  • @GregAskew Thanks for the suggestion of 'Pin Point' zones. Though not ideal for this scenario, it is good to know that exists (especially as an alternative to split-brain). – Jaans Mar 07 '19 at 02:01
  • @PatrickMevzek and Semicolon: Yeah, I realise that - unfortunately I inherit the problem as it was implemented this way before I got there. Longer term, I agree this would be the fundamentally better way to solve the core problem. – Jaans Mar 07 '19 at 02:06

2 Answers2

3

This is indeed not a unique problem. From the top of my head, there are two "solutions" commonly employed:

  • Manually copy over entries to both DNS infrastructures for records that need to be available publicly. Note that this is only the case for services hosted publicly, e.g. a VPS instance. Since app.example.com hosted internally would require a public IP address externally but probably a private IP address internally. Now that automation is the hype you will want to look into automating this should you frequently have to alter these public IP addresses on both locations. If your current DNS hosting provider is no good (bad quality or no API for automation) then you can simply switch to a different provider.
  • Use a different domain internally. If you own example.com and your public servers use this domain, e.g. www.example.com and mail.example.com then your internal network can use ad.example.com if you use Windows Active Directory, or comp.example.com or anything you like. Internal resources will live in this name space and public ones (e.g. www.example.com) will be forwarded to your public DNS provider. This way you do not need to replicate DNS entries.

There are pro's and cons to both solutions and other solutions might exist.

It is not possible to configure an authoritative DNS server to forward the query if it doesn't find an answer in its database. "Authoritative" means it knows everything about the zone. You could configure specific forwarders, e.g.:

zone "example.com" {
   type master;
   file "...";
};
zone "www.example.com" {
   type forward;
   forwarders { 203.0.113.53; };
};
zone "mail.example.com" {
   type forward;
   forwarders { 203.0.113.53; };
};
Tommiie
  • 5,547
  • 2
  • 11
  • 45
  • Thanks for the feedback. Unfortunately I've inherited the configuration and so using different domains internally vs. externally (though fundamentally the more correct solution) is not short term feasible. The conditional forwarders is another way to engage the external DNS server - but the administration of the records is then an issue for us given the churn of the external records. I'll look into automation options to keep the internal one updated with the external entries. – Jaans Mar 07 '19 at 02:32
1

If the external DNS is using BIND The following configuration file is just an example on how to solve the problem

acl localnet { 1.2.3.4/24; }; <---- this is the range of your public ip addresses
view internal {
     match-clients { localnet; };

     allow-recursion { any; };

     zone "myzone.example" {
          type master;
          file "external.db.myzone.example"; <--- in this file put all your internal and external records
                                                  even if they have local ip addresses
     };

     };
}; 
view external {
     match-clients { any; };

     allow-recursion { any; };

     zone "myzone.example" {
          type master;
          file "internal.db.myzone.example"; <--- in this file put all just your external records
     };

     };
}; 
};