
Views in BIND 9
by Cricket Liu
05/14/2000
The view that computers on the Internet see is usually considerably stripped
down from the internal version and only contains information about resources
available on the Internet, including Web servers and mail servers. The
internal view normally contains everything: all those hosts accessible from
the Internet plus all those on the internal network.
Until recently, presenting one view of a zone to one community of hosts and
another view to others has entailed running multiple sets of name servers or
multiple name server processes on a single host in a tricky configuration.
Nobody ever said being two-faced is easy.
BIND 9 introduced a new feature called "views" that makes delivering different
versions of a zone, and even different name server configurations, easy. In
this article, I'll describe how to use views to configure several two-faced
name servers, each a little more complex than the last.
Basic Syntax
The key to configuring views is the new BIND 9 configuration statement,
view. view takes a view name as an argument and has one
required substatement, match-clients. The view name is simply a
convenient mnemonic for identifying the view; I usually use names like
"internal" and "external" or "Internet." If you use a name that conflicts with
a reserved word in named.conf, be sure to quote it. I quote all of
my view names because I can't remember which words are reserved.
For more information on BIND 9, don't miss Cricket's recent
oreilly.com article on Upgrading to
BIND 9: The Top Nine Gotchas.
The match-clients substatement takes an address match list as an
argument. Only queriers whose IP addresses match this address match list will
see the configuration specified in the enclosing view. If a querier's IP
address matches multiple view statement's match-clients
substatements, the first view statement is the one that applies.
Here's an example of a simple view statement:
view "global" {
match-clients { any; };
};
This view statement doesn't do anything useful, because it applies to
all queries (in the absence of other view statements) and because it
doesn't include any substatements besides match-clients, which would
change the configuration of this view from the default configuration.
There's a list of substatements supported within a view statement in
the file doc/misc/options in the BIND 9 distribution, which you can
get from the Internet Software Consortium. The list grows with each
successive release of BIND 9, and it already includes most options
substatements.
If you don't specify a particular substatement within a view, the view
inherits the global setting for that substatement. So, for example, if you
don't turn recursion off within a view, that view would inherit the recursion
setting from your options statement (specified by the
recursion substatement) or, if you don't have one, would inherit the
global default, which is "recursion yes."
Here's an example of turning recursion off within a view:
view "external" {
match-clients { any; };
recursion no;
};
Here's a complete named.conf file that includes the previous
view statement:
/*
* BIND 9 name server allowing recursive queries from
* localhost, disallowing from anywhere else
*/
options {
directory "/var/named";
};
view "localhost" {
match-clients { localhost; };
recursion yes; /* this is the default */
};
view "external" {
match-clients { any; };
recursion no;
};
This name server allows recursive queries only if they come from the local
host. (The localhost access control list [ACL] is predefined to be all
of the IP addresses of the host that runs the name server, plus the loopback
address.) Queries from all other addresses are treated as non-recursive.
Here's a similar configuration, this one of a name server that allows
recursive queries from our internal network but not from the Internet:
/*
* Same name server serving an internal network and the
* Internet
*/
options {
directory "/var/named";
};
view "internal" {
match-clients { localnets; };
recursion yes; /* this is the default */
};
view "external" {
match-clients { any; };
recursion no;
};
This configuration takes advantage of the built-in ACL localnets,
which is predefined as all of the networks to which our name server is directly
connected.
Defining Zones in Views
In order to present a version of a zone to only some queriers, you need to
define the zone within a view. You simply use a zone statement as a
view substatement. Otherwise, its syntax is the same as if it were a
top-level statement. Note that if you define even one zone within a view, all
of your zones need to be defined inside views.
Here's an example:
/*
* A name server showing different zone data to different
* networks
*/
options {
directory "/var/named";
};
view "internal" {
match-clients { localnets; };
recursion yes; /* this is the default */
zone "oreilly.com" {
type master;
file "db.oreilly.com.internal";
allow-transfer { any; };
};
};
view "external" {
match-clients { any; };
recursion no;
zone "oreilly.com" {
type master;
file "db.oreilly.com.external";
allow-transfer { none; };
};
};
Note that the zone oreilly.com is defined in both the
internal and the external view, but the zone data file for
oreilly.com is db.oreilly.com.internal in the
internal view and db.oreilly.com.external in the
external view. Presumably, the contents of the zone data files are
different.
If you prefer to use different subdirectories for the internal and
external zone data, you can do that, too. For example, the
file substatement for oreilly.com in the internal
view could be:
file "internal/db.oreilly.com";
and the external view could use:
file "external/db.oreilly.com";
This way, you can keep all of your internal zone data files in the
/var/named/internal directory and your external zone data
files in the /var/named/external directory.
Views in Slave Name Servers
One minor wrinkle in views is the configuration of slave name servers. Many
people configure a primary master name server with multiple views, then want
to configure a slave with the same views. Unfortunately, when the slave tries
to transfer the zones (or the two versions of the same zone) from the primary
master name server, it only sees one version of the zone, the one defined in
the view the slave's IP address can see.
The solution to this problem is to configure an IP address alias on the slave
name server, giving it two IP addresses from which to initiate zone transfers.
Then configure the primary master to present one view to one of the slave's IP
addresses and the other view to the slave's other IP address. Finally, force
the slave to initiate zone transfers from the appropriate IP address within
each view.
Here's an example. Our slave has two IP addresses, 192.168.0.2 and
192.168.0.254. Our primary master has just one, 192.168.0.1. First, here's
the slave's named.conf file:
options {
directory "/var/named";
};
view "internal" {
match-clients { localnets; };
recursion yes;
zone "oreilly.com" {
type slave;
masters { 192.168.0.1; };
transfer-source 192.168.0.2;
file "internal/bak.oreilly.com ";
allow-transfer { any; };
};
};
view "external" {
match-clients { any; };
recursion no;
zone "oreilly.com" {
type slave;
masters { 192.168.0.1; };
transfer-source 192.168.0.254;
file "external/bak.oreilly.com ";
allow-transfer { none; };
};
};
Notice that the slave is configured to initiate transfers of
oreilly.com within the internal view from the IP address
192.168.0.2 and within the external view from 192.168.0.254.
Now, here's the primary master's named.conf file:
options {
directory "/var/named";
};
view "internal" {
match-clients { !192.168.0.254; localnets; };
recursion yes;
zone "oreilly.com" {
type master;
file "internal/db.oreilly.com ";
allow-transfer { any; };
};
};
view "external" {
match-clients { any; };
recursion no;
zone "oreilly.com" {
type master;
file "external/db.oreilly.com ";
allow-transfer { none; };
};
};
Notice that the internal view's match-clients substatement
explicitly places 192.168.0.254 into the external view by negating it
in the address match list. Any time the slave initiates a zone transfer from
that IP address, it'll get the version of oreilly.com described
by the zone data file /var/named/external/db.oreilly.com.
Summary
Though serving different versions of a single zone was possible in previous
versions of BIND, views makes the configuration much simpler. You no longer
need multiple named.conf files and multiple named processes,
each with its own working directory.
Now if someone could just make the Internet friendlier.
Cricket Liu is coauthor of both of O'Reilly & Associates'
books on the Domain Name System, DNS and BIND, 4th Edition
(covers BIND versions 8.2.3 and 9.1.0) and
DNS on Windows
NT, and he is the principal author of the now out-of-print Managing
Internet Information Services.
Cricket worked for five and one-half years at Hewlett-Packard's Corporate
Network Services where he ran hp.com, one of the largest corporate domains
in the world, and helped design the HP Internet's security architecture.
Cricket left HP in 1997 to start his own company, Acme Byte & Wire, with
his friend and coauthor Matt Larson. Network Solutions acquired Acme Byte & Wire in June of
2000, and subsequently, Network Solutions merged with VeriSign. Cricket became
director of DNS Product Management in the merged company, helping to determine
which new DNS-related products VeriSign would offer.
O'Reilly & Associates recently released DNS and BIND, 4th
Edition (April 2001).

|