Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have an internal network with a DNS server running BIND, connected to the internet through a single gateway. My domain "example.com" is managed by an external DNS provider. Some of the entries in that domain, say "host1.example.com" and "host2.example.com", as well as the top-level entry "example.com", point to the public IP address of the gateway.

I would like hosts located on the internal network to resolve "host1.example.com", "host2.example.com" and "example.com" to internal IP addresses instead of that of the gateway. Other hosts like "otherhost.example.com" should still be resolved by the external DNS provider.

I have succeeded in doing that for the host1 and host2 entries, by defining two single-entry zones in BIND for "host1.example.com" and "host2.example.com". However, if I add a zone for "example.com", all queries for that domain are resolved by my local DNS server, and e.g. querying "otherhost.example.com" results in an error.

Is it possible to configure BIND to override only some entries of a domain, and to resolve the rest recursively?

share|improve this question
    
Similar question: serverfault.com/questions/8694/… –  MikeyB Jun 3 '09 at 15:34
1  
"Is it possible to configure BIND to override only some entries of a domain ?" No, not with BIND. Use a subdomain. –  bortzmeyer Jun 4 '09 at 10:42
    
Unbound seems to do exactly what I asked for, so I'm setting Alnitak's reply as the accepted answer. But in the end, I'm going to follow bortzmeyer's advice and not override the domain entry. Thanks for all the replies! –  Remy Blank Jun 5 '09 at 16:31

8 Answers 8

up vote 9 down vote accepted

The Unbound recursive DNS server has the ability to override individual resource records.

Look at the local-zone and local-data configuration settings in the manual, e.g.:

local-zone: "example.com." transparent
local-data: "foo.example.com. IN A 192.168.1.1"

The transparent setting on the local-zone tells it to do normal recursive lookups for any names not supplied with local-data.

share|improve this answer
    
Seems to be exactly what I want to do, thanks. I'll read up on Unbound tonight. –  Remy Blank Jun 3 '09 at 16:19
    
On the other hand, the wisdom of it is quite questionable. Having an internal.example.com domain would be clearer. –  bortzmeyer Jun 4 '09 at 10:41
    
@Bortzmeyer - you could be right, but I don't imagine Wouter put it in just for fun ;-) –  Alnitak Jun 4 '09 at 11:25
1  
@bortzmeyer, sometimes there's no choice. Example: SBS 2008 must have a single LAN IP, yet it needs to be reached from outside using an external IP that the router is forwarding. Microsoft doesn't allow two network cards on SBS, nor two IP's configured on the same card. If local servers resolve the DNS name to the external IP, then the router needs to do both DNAT and SNAT for LAN ip's, and then the logs on the SBS will show all access to be from the router's IP, and that's just wrong. I'll install unbound on my own router, I think the solution is much better. –  Cosmin Prund Feb 9 '12 at 9:17

You may want to look into "dnsmasq", which lets you do some pretty clever things with tweaking resolution.

share|improve this answer
    
Thanks, good tip. Too bad dnsmasq doesn't do recursive resolution, so I'll still have to run BIND on another port for that (the DNS servers of my ISP are flakey). –  Remy Blank Jun 3 '09 at 14:38

What you're looking for is split DNS, which is defined by Webopedia as:

In a split DNS infrastructure, you create two zones for the same domain, one to be used by the internal network, the other used by the external network. Split DNS directs internal hosts to an internal domain name server for name resolution and external hosts are directed to an external domain name server for name resolution.

Essentially, you will need to make a copy of your external zone file and prop it up on your internal DNS server, then change or add the records needed specifically for your internal network. This is a pretty common setup, though it can be a pain to keep the "external" records synchronized between the two DNS servers. If you create or change a record on the public server, it will also need to be created or changed on the private server as well.

This can be implemented regardless of what DNS server implementation you use. In most setups, you will have one DNS server that serves the external network, and a different one that serves the internal network. With BIND, as possibly other implementations, you can have both versions of the zone on the same server through a use of the "allow-query" statement within the zone section of the named.conf file.

Another possibility on BIND (and I've never tried this) would be to set your example.com domain on the internal DNS server with only the records you use internally. Then, set a "forward" statement with the "first" argument (in conjunction with "forwarders"). In theory, this would go ask the external DNS server (as set in "forwarders" for an answer, which wouldn't have your internal records and return a failure response. Then, the internal server would look at itself for an answer. Not sure if that would work, but it's a thought.

share|improve this answer
    
Keeping the two zone files in sync will be complicated, as the external one is updated through a dynamic DNS client. I'll read up on the forward statement, though. Thanks for the tip. –  Remy Blank Jun 3 '09 at 16:12
    
No, the BIND forwarding will not work, it will be only for unknown domains but the internal name server will know about example.com, it will be authoritative for it. –  bortzmeyer Jun 4 '09 at 10:40
    
If I'm reading the documentation correctly, the "forward first" statement within a zone section should tell BIND to go out and look for an answer at the forwarder even for an authoritative local domain, then use the local information only if it can't get an answer from the forwarder. –  Justin Scott Jun 4 '09 at 20:52
    
If you put a global "forward first" 'it will send the queries to the forwarder and if not answered will attempt to answer the query' (from the doc) but if it receives a response, it won't try to resolve itself. It would be great if you could force to resolve if the response is not authoritative or even if it's a NXDOMAIN, but bind won't try if it gets a response from the forwarder. –  Pablo Martinez Jan 23 '13 at 16:38

Use dnsmasq makes it real easy. http://www.thekelleys.org.uk/dnsmasq/doc.html Acts as the dns server but gets answers from local dns server. Nice thing is you can override single domain records without messing with zone files

share|improve this answer

You're already on the right track.

On your internal DNS servers, you'll need to define a zone for every exception host immediately below the "example.com". To minimize these exceptions, it is common practice to name all internal machines "hosta.internal.example.com", with the DNS server sending most queries to external DNS servers, but authoritative for the zone "internal.example.com". (Once you get past a small operations, there is usually a couple DNS server to which clients are directed and a separate authoritative DNS to which those are servers are directed for "internal.example.com".)

Usually, it is only when a host must be reachable both externally and internally that the exceptions you describe get created. Even then, you may want to use "host1.example.com" from the outside and "host1.internal.example.com" from the inside. Internal hosts get configured to look for names within "internal.example.com". There are situations where what you're already doing is appropriate, such as if the certificate for a server identifies the server as "host1.example.com", in which case you want that to be the name to which clients connect.

share|improve this answer
    
Yes, for the "host1.example.com" hosts, it's already working well. The tricky part is handling the top-level "example.com" in the same way... –  Remy Blank Jun 3 '09 at 16:14

I have a very similar situation: I have nakarti.com with public alias www.nakarti.com. and nax.nakarti.com. I want either .www. or .nakarti.com to resolve publically to my dyndns for firewall, etc testing. I want to override nax.nakarti.com internally for the application it's named after, and also have a handful of other local-only names.

Because I need the split resolution path based on the fqdn it has to be a single resolver. I could use unbound, but I doubt the benefit of learning a new DNS application when I should be able to do it with the one I know. I didn't think dnsmasq is the bandaid I want, but after configuring it, it works better than I expected. Now if I can only make my router point to it....

share|improve this answer

In BIND I get to this results by defining a zone using desired host name. The approach is fine if you only want to override a few hosts.

My zone declaration looks like this:

zone "override.example.com" {
        type master;
        notify no;
        file "zone-config/override.example.com";
};

My zone definition looks like this:

$TTL 4H
@       IN      SOA     ns.override.example.com.    root.override.example.com. (
                        2009072215      ; Serial
                        3600            ; Refresh
                        600             ; Retry
                        604800          ; Expire
                        3600    )       ; Minimum
;
                NS      ns
        IN      NS      ns.override.example.com.
        IN      A       192.168.1.100
ns      IN      A       192.168.1.100

So if I query example.com on intranet DNS and ISP DNS I get same IP but if I query override.example.com I get different results if intranet DNS (primary) is accessible.

share|improve this answer

As a matter of fact there is another, even if perhaps slightly different, way to do this. I have the same situation, I have a domain which is used externally and internally, and I have external static and dynamic hosts. The only really painful ones are the external dynamic ones. The solution is possibly not the most elegant, but implementable with a small script. Mostly I am doing my own dynamic DNS script with the API of my dynamic DNS provider, I run this script by cron, every 5 mins:

1) get my external IP. has it changed ? no, exit.

2) changed IP, call API of dyndns-provider, with the new IP-address,

3) sed the db.mydomain.com with the external IP

4) restart bind.

Works very reliably for my home network

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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