advertisement

Print
O'Reilly Book Excerpts: DNS & BIND Cookbook

Cooking with DNS & BIND

Related Reading

DNS & Bind Cookbook
By Cricket Liu

by Cricket Liu

Editor's Note: Cricket Liu has selected another five recipes from his book, DNS & BIND Cookbook, this time from Chapter 7 on "Security." The problems and solutions in this excerpt range from configuring a name server to work with a firewall to configuring an authoritative-only name server. And if you're interested in BIND name server operations, be sure to check out the last batch of recipes we published from Cricket's book.

Concealing a Name Server's Version

Problem

Modern BIND name servers respond with their version to queries for TXT records attached to the pseudo domain name version.bind in the CHAOSNET class. For example:

$ dig version.bind txt chaos

; <<>> DiG 9.2.1 <<>> version.bind txt chaos
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5096
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;version.bind.                  CH      TXT

;; ANSWER SECTION:
version.bind.           0       CH      TXT     "9.2.1"

You want to conceal the version a name server returns.

Solution

The simplest way to accomplish this is to use the version options substatement. The version substatement takes it as a string to return to version.bind queries as an argument. For example:

options {
    directory "/var/named";
    version "None of your business";
};

Some folks, however, don't want their name servers to return anything, not even a bogus answer, to unauthorized queriers. Others want authorized queriers to see the real version instead of a bogus one.

To set that up, create a CHAOSNET zone called bind and a zone statement for it in named.conf . Then use allow-query to restrict queries to the zone. Here's a sample bind zone data file:

$TTL 1d
@    CH    SOA     ns1.foo.example.    hostmaster.foo.example.    (
     2002052600 86400 3600 604800 3600 )
     CH    NS    ns1.foo.example.

version.bind.    CH    TXT    "BIND 9.2.1"

Notice that the records in the bind zone are all in the CHAOSNET class, as you would expect.

On a BIND 8 name server, the zone statement for the bind zone might look like this:

zone "bind" chaos {
    type master;
    file "db.bind";
    allow-query { localnets; };
};

On BIND 9, the configuration is a little more complicated. Even if you don't explicitly use views, BIND 9 creates zones in an implicit "default" view in the Internet class. So you can't just create a CHAOSNET zone in the default view because the zone and the view have different classes: you need to create a new CHAOSNET view and define the bind zone in it. And, if you weren't using views before, you need to create an explicit Internet view for your other zones and move their zone statements into the view.

For example, if your BIND 9 name server's named.conf file looks like this now:

options {
    directory "/var/named";
};

zone "foo.example" {
    type master;
    file "db.foo.example";
};

You might change it to look like this:

options {
    directory "/var/named";
};

view internet in {

    zone "foo.example" {
        type master;
        file "db.foo.example";
    };
};

view chaosnet chaos {

    zone "bind" {
        type master;
        file "db.bind";
        allow-query { localnets; };
    };
};

Discussion

Camouflaging a name server's version is no substitute for running an up-to-date version of BIND or for configuring the name server securely. About the best you can hope for is that concealing a name server's version will prevent hackers from identifying it as an obvious, first-choice target if the version of BIND it's running has a vulnerability.

See Also

"BIND Version" in Chapter 11 of DNS and BIND, 4th Edition.

Configuring a Name Server to Work with a Firewall (or Vice Versa)

Problem

You want to configure a name server to work through a firewall, or configure a firewall to work with a name server.

Solution

Configure your firewall to pass the UDP and TCP traffic that a BIND name server requires. This matrix shows you the traffic necessary for each purpose.

Purpose Protocol Source address Source port Destination address Destination port
Queries from your name server UDP or TCP Your name server > 1023 Any 53
Responses to your name server UDP or TCP Any 53 Your name server > 1023
Queries from remote name servers UDP or TCP Any > 1023 Your name server 53
Responses to remote name servers UDP or TCP Your name server 53 Any > 1023

Refresh queries--the queries a slave name server sends to its master name server to see if a zone's serial number has increased--and NOTIFY messages are also sent from a high-numbered port (above 1023) to port 53.

Discussion

Normally, BIND name servers choose a source port to use for outbound queries when they start, which means you must allow DNS messages from any unprivileged port. However, you can configure a name server to use a particular source port for outbound queries with the query-source options substatement. (On BIND 8 name servers, query-source also controls the source port for NOTIFY messages and refresh queries.) For example, to instruct a name server to use port 1053 as the source port for all outbound queries, use:

options {
    directory "/var/named";
    query-source address * port 1053;
};

This may let you simplify the firewall rules somewhat because you can limit outbound, UDP-based query traffic to a single source port. If the name server has multiple network interfaces, you can also use the query-source substatement to choose which source address it uses in queries. For example, to tell a name server to use 192.168.0.1 as the source address in queries, use:

options {
    directory "/var/named";
    query-source address 192.168.0.1;
};

You can specify both the source address and source port, too:

options {
    directory "/var/named";
    query-source address 192.168.0.1 port 1053;
};

If you run a BIND 9 name server, use the transfer-source substatement in a zone, view, or options statement to specify the source port used in refresh queries and forwarded dynamic updates. For example:

zone "foo.example" {
    type slave;
    masters { 192.168.0.1; };
    file "bak.foo.example";
    transfer-source * port 1053;
};

This tells the name server to use port 1053 as the source for all refresh queries and dynamic updates it forwards. The port specification doesn't apply to zone transfers, however, that use TCP. For TCP-based traffic, the source port is always chosen randomly. The address specification (here, "*") does apply to the source address of TCP zone transfer requests, though.

On BIND 8 name servers, transfer-source is only a zone substatement until BIND 8.2.2, when it's also supported as an options substatement. It only sets the source address used in zone transfers, that is, you can't specify a port argument:

options {
    directory "/var/named";
    transfer-source 192.168.0.2;
};

For NOTIFY messages, BIND 9.1.0 and later and BIND 8.3.2 and later name servers understand the notify-source substatement, which has the same argument syntax as transfer-source and can also be used as a zone , view, or options substatement.

Remember that queries can be TCP-based as well as UDP-based, so you must allow traffic from queriers to TCP port 53 as well as UDP port 53, and from your name server to TCP port 53.

See Also

"Configuring the IPv4 Transport" in Chapter 10 of DNS and BIND .

Setting Up a Hidden Primary Master Name Server

Problem

You want to run a primary master name server "hidden," so that other name servers don't query it.

Solution

Configure the slave name servers for your zones to use the primary master as their master name server, but don't list the primary master in the zones' NS records. For example, if ns1.foo.example, at 192.168.0.1, is the primary master name server for foo.example, you'd add zone statements like these to the slaves' named.conf files:

zone "foo.example" {
    type slave;
    masters { 192.168.0.1; };
    file "bak.foo.example";
};

But the NS records for foo.example wouldn't include ns1.foo.example :

foo.example.    IN    NS    ns2.foo.example.
foo.example.    IN    NS    ns.isp.net.

In addition, make sure the delegation information for foo.example does not include ns1.foo.example.

Discussion

"Hidden primary" configurations are often used to give the administrator of the primary master name server direct control over zone data without incurring any of the zone's query load. For example, a broadband Internet customer could run a local primary master name server on which to administer the zone but leave his ISP's slaves to answer queries for data in the zone.

If you use Microsoft dynamic update clients, such as Windows 2000, be sure to list the real primary master name server in the MNAME field of the SOA records of dynamically updated zones. Microsoft dynamic update clients will send their updates to the name server designated in the MNAME field regardless of whether that name server also appears in the zone's NS records.

Clients with BIND-based update code will only send updates to name servers listed in a zone's NS records, so make sure your zones' slave name servers support update forwarding, that is, run BIND name servers from 9.1.0 on and have update forwarding configured. See Recipe 3.11 for instructions on configuring update forwarding.

See Also

Recipe 3.11, for configuring update forwarding.

Setting Up a Stealth Slave Name Server

Problem

You want to set up a stealth slave name server, one that isn't queried by remote name servers.

Solution

Configure the name server as you would any other slave, but don't include it in the NS records for the zone (or zones) it's authoritative for.

Discussion

A stealth slave name server is a close cousin of a hidden primary master. Like a hidden primary, a stealth slave isn't included in the NS records for the zone it's authoritative for. Other than that, though, it has the same configuration as any other slave name server for that zone.

The function of a stealth slave name server may not be as obvious as that of a hidden primary. A hidden primary's benefit--making it possible to manage a zone without the burden of serving queries for the zone--doesn't apply to a stealth slave. So what's a stealth slave for?

Sometimes, you need another authoritative name server for a zone to serve some group of resolvers. Say you need a name server on a particular subnet, to serve the local resolvers. All of the subnet's resolvers live in the same zone, so they'll probably generate lots of queries for domain names in that zone. Shouldn't their local name server be authoritative for the zone?

But what if you already have as many NS records for the zone as you can fit in a UDP-based DNS message (usually 10 or 11)? Or what if you don't want remote name servers to query the new slave, because the subnet it's on isn't well connected to the rest of the network? Just don't list it in the zone's NS records: remote name servers won't follow delegation to it, but you can configure local resolvers to query it directly.

Since the slave isn't in the list of NS records for the zone, the zone's other authoritative name servers won't send it NOTIFY messages by default. You'll have to configure the stealth slave's master name server to send it NOTIFY messages; for instructions, see Recipe 3.12.

See Also

Recipe 3.12 for configuring the stealth slave's master name server to send NOTIFY messages to the stealth slave.

Configuring an Authoritative-Only Name Server

Problem

You want to configure an "authoritative-only" or nonrecursive name server.

Solution

Disable recursion with the recursion options substatement:

options {
    directory "/var/named";
    recursion no;
};

If the name server isn't already configured as authoritative for one or more zones, add zone statements to named.conf, too.

Discussion

Since "authoritative-only" isn't a standard term (nor is "nonrecursive," really), a few words of explanation are in order. A nonrecursive or authoritative-only name server is one that only answers nonrecursive queries from remote name servers. It can't directly serve resolvers, since all resolvers send recursive queries by default, but you can delegate zones to it, and it's nearly invulnerable to spoofing attacks, since it normally doesn't send queries. It's also more resistant to denial of service attacks, since it doesn't process resource-intensive recursive queries.

For completeness, you may also want to disable glue fetching on BIND 8 name servers:

options {
    directory "/var/named";
    recursion no;
    fetch-glue no;
};

This step prevents the name server from sending queries to look up A records for name servers that appear in NS records. That, together with disabling recursion, makes the name server completely passive. It may prevent NOTIFY from working correctly, though, since the name server won't look up the addresses of name servers outside of the zones it's authoritative for. In that case, use Recipe 3.13 to configure the name server to send NOTIFY messages to the slaves explicitly.

Remember to limit concurrent zone transfers (Recipe 5.16), and accept only authorized zone transfer requests (Recipe 7.10) if the name server acts as a master.

Cricket Liu is the co-author of all of O'Reilly's Nutshell Handbooks on the Domain Name System, "DNS and BIND," "DNS on Windows NT," "DNS on Windows 2000," "DNS on Windows Server 2003," and the "DNS & BIND Cookbook," and was the principal author of Managing Internet Information Services.


Return to the O'Reilly Network.