Two-in-one DNS server with BIND9

Want to support HowtoForge? Become a subscriber!
 
Submitted by pupeno (Contact Author) (Forums) on Thu, 2006-02-23 15:22. :: BIND | DNS

This tutorial shows you how to configure BIND9 DNS server to serve an internal network and an external network at the same time with different set of information. To accomplish that goal, a new feature of BIND9 called view is used. As a tutorial it'll walk you through the whole set up, but initial knowledge of BIND and DNS is required, there are plenty of documents that cover that information on the Internet.

Continue reading at original site or download PDF.

Contents

1 The problem

It is a typical problem in organizations that are growing that they have to resolve two problems at once:

  • To have a DNS server for the internal network of the company because long ago there were already too many computers to remember their IPs1 and even too many computers to maintain a set of host files2.
  • To have a DNS server for the external servers, for external clients, etc.

to solve this problems become a bigger problem when the growing organization can't supply more resources than one DNS server3. It is a bigger problem because if you just configure your server with all your names, public and private, you'll end up polluting the Internet with private addresses, something that is very bad, and also showing the world part of the topology of your internal network. Something you don't want a possible attacker/cracker to have.

The other part of the problem is that for efficiency you may want to resolve to internal IPs when you are inside and external IPs when you are outside. Here I am taking about computers which have public and private connections.

There are many different solutions to this problem and I remember solving it even with BIND4, but now I am going to use BIND9 to make a solution that is very clean. This was deployed in a Debian GNU/Linux 3.1 server but it should also work for other operating systems that run BIND9, just be sure to change your paths appropriately.

2 Initial configuration

Let's imagine the organization I work for makes examples... of what ? I don't know, but you can order them on example.com. Examples Corporation has been assigned the network 192.0.2.0/24 and internally we are using 10.0.0.0/24.

Let's start serving the external names and IPs, we edit /etc/bind/named.conf.local4 and add:

zone "example.com" {
type master;
file "/etc/bind/db.example.com";
};

and then we create /etc/bind/db.example.com with the following contents:

; example.com
$TTL 604800
@ IN SOA ns1.example.com. root.example.com. (
2006020201 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800); Negative Cache TTL
;
@ IN NS ns1
IN MX 10 mail
IN A 192.0.2.1
ns1 IN A 192.0.2.1
mail IN A 192.0.2.128 ; We have our mail server somewhere else.
www IN A 192.0.2.1
client1 IN A 192.0.2.201 ; We connect to client1 very often.

As you can see, our start up has one computer to serve all, except mail, it even holds the IP forwarding and a couple of databases.

Now, a good DNS set up has at least one secondary server and in fact, some registrars (where you register domain names) enforce this. Since we don't have a second computer, we go to XName, open an account and register example.com as secondary with 192.0.2.1 as IP to transfer from. We now need to let XName's IP do the transfer; we are a small organization but since we want to be a successful start up we try to do everything as smartly as possible. So we use the BIND9 configuration directive acl to define an identifier that aliases to the XName's IP addresses; at the beginning of /etc/bind/named.conf.local we add:

acl slaves {
195.234.42.0/24; // XName
193.218.105.144/28; // XName
193.24.212.232/29; // XName
};

and we change the zone declaration to:

zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-transfer { slaves; };
};

We could have just typed the IPs where we type "slaves".

3 Internals and externals

Now that we have a solid base, we can start to thing about serving different contents to the internal and external network, but first, we have to define what is internal and what is external.

On /etc/bind/named.conf.local we add the following definition (at the top or below the definition of slaves):

acl internals {
127.0.0.0/8;
10.0.0.0/24;
};

If we had more internal networks, we could just add them there. We don't define externals because everything that is not internal is external. You may, if you want, define sets of different externals if you want to serve different content to different chunks of the Internet.

We will use a new feature of BIND9 called views. A view let's put a piece of configuration inside a conditional that can depend on a number of things, in this case we'll just depend on internals. We replace the zone declaration at /etc/bind/named.conf.local with:

view "internal" {
match-clients { internals; };
zone "example.com" {
type master;
file "/etc/bind/internals/db.example.com";
};
};
view "external" {
match-clients { any; };
zone "example.com" {
type master;
file "/etc/bind/externals/db.example.com";
allow-transfer { slaves; };
};
};

The match clients configuration directive allow us to conditionally show that view based on a set of IPs, "any" stands for any IP. Internal IPs will be cached by the internal view and the rest will be dropped on the external view. The outside world can't see the internal view, and that includes XName, our secondary DNS provider, but we removed the allow-transfer from the internal view since we don't want anyone to be able to transfer under any circumstances the contents of the internal view.

We also changed the path, we will have to create the directory /etc/bind/externals and /etc/bind/internals and move /etc/bind/db.example.com to /etc/bind/externals/.

On /etc/bind/internals/db.example.com we put a zone file similar to the counterpart on external but holding the internal IPs:

; example.com
$TTL 604800
@ IN SOA ns1.example.com. root.example.com. (
2006020201 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800); Negative Cache TTL
;
@ IN A 10.0.0.1
boss IN A 10.0.0.100
printer IN A 10.0.0.101
scrtry IN A 10.0.0.102
sip01 IN A 10.0.0.201
lab IN A 10.0.0.103

Great, we can now ping our boss' computer with

ping boss.example.com

but trying to reach mail.example.com will disappoint us, what happened ? There's no reference to mail.example.com on the internal zone file and since we are in the internal network we can resolve mail.example.com. Fine, let's just copy the contents of the external zone file to the internal zone file. That'll work.

But we are a small, smart start up, we can do better than copy-paste each modification to the zone file, furthermore, that is very error prone (will you always remember to modify the internal zone file when you modify the external one, or will you forget and spend some days debugging network problems ?).

What we will do is include the external zone file in the internal file this way:

$include "/etc/bind/external/db.example.com"
@ IN A 10.0.0.1
boss IN A 10.0.0.100
printer IN A 10.0.0.101
scrtry IN A 10.0.0.102
sip01 IN A 10.0.0.201
lab IN A 10.0.0.103

and voila! Finding the $include directive in the current documentation was hard.. Just remember to change the serial of the external zone file whenever you change the internal one, but it is not a big deal, if you forget, nothing bad will happen since you are not likely to have caching servers inside your own small network.

4 Security

It is not recommended to use the same DNS server as primary for some domain (in our case example.com) and as caching DNS server, but in our case we are forced to do it. From the outside world 192.0.2.1 is the primary DNS server for example.com, from our own internal network, 192.0.2.1 (or its private address, 10.0.0.1) is our caching name server that should be configured as the nameserver to use on each workstation we have.

One of the problems is that someone might start using our caching nameserver from the outside, there's an attack called cache-poisoning and many other nasty things that can be done and are documented on [SINS] (including how to avoid them).

To improve our security a bit, we'll add a couple of directives to the configuration file:

view "internal" {
match-clients { internals; };
recursion yes; zone "example.com" { type master; file "/etc/bind/internals/db.example.com"; }; }; view "external" { match-clients { any; }; recursion no; zone "example.com" { type master; file "/etc/bind/externals/db.example.com"; allow-transfer { slaves; }; }; };

That will prevent anyone on the dangerous Internet to use our server recursively while we, on our own network, can still do it.

5 Configuration files

5.1 /etc/bind/named.conf.local

acl slaves {
195.234.42.0/24; // XName
193.218.105.144/28; // XName
193.24.212.232/29; // XName
};

acl internals {
127.0.0.0/8;
10.0.0.0/24;
};

view "internal" {
match-clients { internals; };
recursion yes;
zone "example.com" {
type master;
file "/etc/bind/internals/db.example.com";
};
};
view "external" {
match-clients { any; };
recursion no;
zone "example.com" {
type master;
file "/etc/bind/externals/db.example.com";
allow-transfer { slaves; };
};
};

5.2 /etc/bind/externals/db.example.com

; example.com
$TTL 604800
@ IN SOA ns1.example.com. root.example.com. (
2006020201 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800); Negative Cache TTL
;
@ IN NS ns1
IN MX 10 mail
IN A 192.0.2.1
ns1 IN A 192.0.2.1
mail IN A 192.0.2.128 ; We have our mail server somewhere else.
www IN A 192.0.2.1
client1 IN A 192.0.2.201 ; We connect to client1 very often.

5.3 /etc/bind/internals/db.example.com

$include "/etc/bind/external/db.example.com"
@ IN A 10.0.0.1
boss IN A 10.0.0.100
printer IN A 10.0.0.101
scrtry IN A 10.0.0.102
sip01 IN A 10.0.0.201
lab IN A 10.0.0.103

Bibliography

SINS
Securing an Internet Name Server

Footnotes

... IPs1
For me, two computers already qualify as too many computers to remember their IPs.
... files2
The host file resides on /etc/hosts and is a simple mapping for the local computer from names to IP. It was the first way to resolve names to IPs and long ago a central big hosts file was maintained, latter distributed by FTP or similar. It rapidly grow into a problem which was solved by the invention of DNS. Try not to let your hosts file grow into a problem before you turn it into DNS, learn from the pioneers!
... server3
Or when you are a perfectionist and believe that this should be doable with only one server.
.../etc/bind/named.conf.local4
It may be just /etc/bind/named.conf in your operating system if it is not Debian.

Please do not use the comment function to ask for help! If you need help, please use our forum.
Comments will be published after administrator approval.
Submitted by Francis Lee (not registered) on Sun, 2012-11-18 10:48.

I agree. I have used this guide but the $include directive will return both IPs defined in the internal and external zones. Is their a way to only return one? specifically on the internal host. External hosts can get only the external IP, not both.

 

Submitted by gibbi (not registered) on Wed, 2011-07-06 07:45.
you can also use http://www.zonefile.org to create a zone file. You can change most values or leave it default if you're not so skilled. ;)
Submitted by dktakeshi (registered user) on Fri, 2010-05-14 08:49.

Hi there,

I've followed your tutorial to the T!  But for some unknown reason, if I use the "view" option, the DNS server will NOT server DNS records for the  zones.

I then proceeded to remove the "view" configuration and just serve up the same zone file, but only the internal one, and it served the request.

Is there something that I have missed that would be the problem?

I am running Ubuntu 10.04 LTS with BIND 9.7.0

Submitted by Nik Rolls (not registered) on Mon, 2010-12-20 06:09.

Check /etc/bind/named.conf to see if it is still including /etc/bind/named.conf.default-zones. If so, this will be throwing an error because once you start using views you can't have any zones defined outside a view.

The default zones are only needed internally, so you can cut and paste that import command to the bottom of your internal zone definition.

Submitted by Anonymous (not registered) on Thu, 2010-05-06 05:10.
Thank you very much for this how-to.  I was looking at other ones and trying to learn out how to use views, but you made it very simple.
Submitted by guytools (not registered) on Sat, 2009-05-23 23:06.

Hello all!

Currently, I am steel looking for a solution

After doing this all, I added a slave in my DNS and there is a great problem of security.

Look!

The problem is when the server's master tranfers zones files to the server's slave.

Explanation :


I configured 2 DNS servers 1 master and 1 slave.

I used the views to allow external users to have a limited use of my servers and internal users differents views.

Everything works fine except that :

When master is transferring zones files to the slave.

This happens because the server's slave is multi-site (internal and external views)

Problem :

I note that both zones files (for external and internal view), which normally are different in master's server for a domain come together and identical in the two different files names that I gave.

So after a transfer I optain 2 files identiques, containing the fusion of zone file in internal and external view.


example:

first:
Master (Fichier1_zone_int, Fichier1_zone_ext) with different contents,
Second:
when I get zone transfer

finally:
Slave(Fichier1_zone_int + Fichier1_zone_ext, Fichier1_zone_int + Fichier1_zone_ext) with the same content.

Can anyone help me solve this problem? 


If someone from the outside use the slave's server as dns server resolution, the establishment of the views have not served because it has access to all hosts on the LAN.

because the zone file is merged

Someone to help me please.
thank you

Submitted by Tyler Wagner (not registered) on Tue, 2009-09-01 17:04.

guytools,

Your problem is documented in the FAQ:

https://www.isc.org/node/282

You can transfer multiple views to slaves by using keys.

Submitted by sgla1 (registered user) on Sat, 2007-06-16 18:33.
For Ubuntu you will want to install the "bind9" package.  "apt-get install bind" fetches bind 8.4x which will not support views.
Submitted by ulfdag (registered user) on Wed, 2007-01-17 22:40.
Reverse zone files or file for the preceeding example.com file is not mentioned in this how-to.  I can only infer that either a reverse zone file for a external view is not necessary.  I would however think that for proper resolution of dns names that one would include a "db.192.0.2" reverse zone file.  Was the fact that reverse files are not mentioned in this how-to due to an assumption by the author that those using this how-to would know to have reverse zone files for each forward zone file refered to in the named.conf.local file?
Submitted by Maarten (not registered) on Sat, 2010-02-27 21:57.

Well reverse lookups should be made. Not properly setting up the reverse dns records is the first common mistake named in rfc1912 (http://tools.ietf.org/html/rfc1912) 

 I really think that this should be added to the howto or at least mention that it's nececery to do this so that the unknowing will not make this mistake.

Submitted by Anonymous (not registered) on Wed, 2006-04-12 19:12.

Hi, first of all I would like to thank you for your great posting. I had the same problem and it was a great help to me.

But I think including the external zone is not a good idea, since the name server now answers all internal queries with two different IP adresses: The internal address (since the requesting client is within acl internal) as well as the included address from the external zone file.

Or did I get it wrong?

Regards,Grischa

Submitted by Anonymous (not registered) on Fri, 2006-02-24 00:50.
It works wonders, i've been using this feature for about 2 years now and it's made things a lot easier now that we have internal and external dns running on the same servers. The only caveat is you have to maintain 2 trees zone files.