Local DNS serving using BIND and DHCP with Fedora Core Linux

Background history

I've been happily running BIND on Red Hat 8.0 Linux with the local DHCP server updating the local DNS server.  I updated to Red Hat 9.0 Linux, and lost that ability.  I've since resolved that issue, which involved partially ignoring something in the examples I've read (don't put a semi-colon after the closing braces in the “/etc/dhcp.conf” file data), and using secret keyfiles for allowing updates (before I'd been able to allow it without such authentication proof being needed—I seem to recall that I could simply allow updates from certain addresses).  This information is included on this page, though it's still only been tested on Redhat 9.0 Linux, not Fedora.

I installed Fedora Core 2 Linux on another PC and decided to try out BIND on it, and struck a different unresolved problem:  The supplied GUI tool for configuring BIND couldn't update the chrooted BIND data.  I tried manually altering configuration files, making links, moving files about, etc., but didn't sort out why it couldn't do it.  But if I unchrooted the server, the GUI tool worked as expected.  To be honest, I see little point in chrooting a server on a LAN that's totally under my control.

Fedora Core 2 Linux has now been superceded by Fedora Core 3, and I've wiped off my Fedora Core 2 installation, updating to Fedora Core 3.  So I've given up trying to resolve that issue with the GUI tool, and it didn't appear to be supplied with Fedora Core 3 (well I couldn't find any mention of one in the package manager), though I did find an RPM for it on the installation discs, I tried it out, and this version crashes while it tries to starts up.  I found the old GUI tool a pain, anyway; it was too inflexible with how you entered data, and quite confusing as to how you were supposed to use it (poor documentation, as usual, didn't help).

Then I had Fedora Core 3 Linux to play with.  This time I tried to do something else, something that did work on Red Hat 9.0:  Setting up a slave zone, and getting it to populate its records from some other master server (this was just an experiment just to see how it worked, for curiosity's sake).  I kept getting very badly worded error messages about it failing while receiving data (see below), which seemed to indicate that it wasn't receiving the data, but the real problem was that it couldn't write the data to a file on the local disk, despite me playing fast and loose with ownership and permissions for the directories it was working in (trying to resolve that error message).  There's two simple solutions:

  1. Write the data into the “slaves/” sub-directory, like you should do but isn't explained anywhere, and the bleeding obvious didn't occur to me until I searched for more information using different terms.  (This is what I ended up doing, as outlined further below.)

  2. Don't write a file, just cache the results in memory.  (This is probably a good solution for a slave server on a LAN with frequently updated dynamic addresses.)

Not very helpful error messages:

dumping master file: tmp-XXXXMlOPYb: open: permission denied

transfer of 'example.com/IN' from 192.168.0.1#53: failed while receiving responses: permission denied

I can't guess what the first error is about, it certainly ought to be able to write to its “tmp” directory (inside the chroot jail), the directory permissions seem correct (“rwx,rwx,---” and it's owned by the “named” user and group).

Nor the second error.  It was certainly able to “receive” data, and I did try changing permissions so that the “named” directory should have been writable by it (not that the error messsage gives any indication that problem is due to not being able to write a file).

Latest history

Since then, everything's been updated to Fedora Core 4 Linux, and things are working fine following the directions outlined on this page.  There's, now, a working GUI tool that allows you to set name server records, albeit a complex thing to use.  I'd say that it's so complex that you may as well hand edit the files, because you're going to need to know the same level of details to do it properly.  And I'd strongly advise against trying to use it to modify a zone that gets dynamically updated via a DHCP server, the two aren't aware of each other, and they'll mangle the zone records.  If you want to do that, stop both servers, update records, update the serial number(s), delete the journal files, then restart the servers (probably should restart the name server first).  But it's probably easier to run a sub-domain, with its own zone file, for the dynamic addresses.

I've changed SELinux settings so that the named server can change master records, on the master name server.  That's necessary, because the DHCP integration with the name server will need to do this.  The slave servers don't need this, as they only rewrite slave records.


What I'm aiming to do

What I wanted to do, and eventually managed, was to set up a local DNS server to handle the local machines name resolution queries, both for other machines on the LAN and for internet addresses.  This way, I can configure all local machines to use this DNS server for all name resolution, and not have to mess with hosts files.  I also wanted to play with having a backup DNS server on another machine (I'm still resolving this, I've only got part way), to help me come to grips with how that works, and working out how best to set up DNS records.

I also wanted to set up a DHCP server for assigning addresses, and configuring other parameters, for some computers being attached to my network (e.g. visitors), and for those address assignments to fit around some fixed IP addresses that are being used for servers on the network.  And for the two of them to be integrated (as machines are added and removed from the network, the DHCP server updates the records of the DNS server).

I eventually managed most of it, and the following details the settings that were used, with some explanations of some parts of it.  Of course reading manuals and guides helps, and shouldn't be avoided, but it's easier to do follow them when you've got a working system.  The guides that I'd read didn't work with my system (many were for obsoleted versions), and neither did some of the documentation help very much (a lot of which was just a list of parameters that could be set, but without any explanations about what they meant nor how to use them, and some quite obscure examples).

At this stage, my DHCP server is running on Red Hat 9.0 Linux, as is my main DNS server, it's my slave DHCP server that's running on Fedora Core 3 Linux.  There may be some differences in configurations on the different systems, and you may need to adjust things if you're not doing it in the same way.  Now, everything's running Fedora Core 4 Linux, and these guides are still applicable.

I haven't worked out the trick of propagating DHCP initiated changes to the DNS records to the slave server at the time it happens, yet.  A server with changed records is supposed to send “notifies” to its slaves, when changes occur, but it doesn't seem to be doing this.  This, now, seems to be working properly by itself, though I've not paid enough attention to it to see if there's an unexpected delay. anything you configure to be notified is notified instantly, other slave servers will find out in due course.

DNS wasn't designed for rapid changes, anyway; all changes take time to propagate through the network of DNS servers (each caching results for a certain time period, only updating itself when the period expires—so caches of caches suffer even longer delays), and this can be a problem for devices that change a lot (computers turned on and off, moved between networks, etc.).  The easiest solutions for that sort of problem are to ensure that DHCP lease expiry times are fairly long (so each device usually gets the same address as last time), to have short time values in DNS records (so slave servers update themselves fairly often), and to have enough spare addresses on a network that each new device doesn't have to re-use something else's address.

A “gotcha” while testing this is to remember that changes to the DNS records aren't written to the zone file immediately.  The results are stored only in the memory for about fifteen minutes, before committing them to disk.  This is an optimisation to avoid lots of little writes to a disk at the same time, should lots of devices be added to a network simultaneously (e.g. an entire office network booting up at the same time).  The data is on the system, and you can query the server for it, but reading the zone file in a text reader is going to be misleading.

NB:  I keep on adjusting this page as I work through different things, so you may want to read it more than once.  It's a bit of a mess of deletions and insertions, while I sort out things, before I get around to rewriting it.

(Last modified:  18 Jan 2017)


Example settings

Let's say that, for example, you're running a DNS service for your local area network, using the “example.com” domain name.  You have several machines using static IP addresses from 192.168.0.1–192.168.0.4, and will have visitors using other addresses configured by hand or DHCP.  You have your main (master) DNS server at 192.168.0.1, a backup (slave) server at 192.168.0.2, and the other addresses mentioned in the following records are other workstations on your LAN.  There's also a DHCP server running on 192.168.0.1 (the master name server machine) which can update the records of the DNS server running on the same machine, as other devices are added and removed from the network, and eventually the changes will ripple through to the slave server(s).

NB:  Substitute your own domain name for anywhere that these set of examples use the “example.com” domain.  Likewise, with sub-domains.

If you don't own a domain name, be sure that any name you invent doesn't exist on the internet, or you will strike networking problems (e.g. at the moment, you could fake up a domain ending with “.lan” but that may change in the future).  It can be advantageous, in many ways, to register your own domain name, even if you don't intend to run a public service, and it's not that expensive.  Once a domain name is registered, and while you keep it registered, it's yours to do with what you like.

It's advisable not to use “.local” as a LAN domain name, when manually configuring networking and naming services, as it can conflict with various automatic, self-configuring, networking systems (Avahi, zeroconf, bonjour).  Yes, some sources did advise using it, in the past, but that advice has superceded by changes in networking implementations.

192.168.0.1 (master) machine

“/etc/named.conf” file contents:

## named.conf

# Let only the local machine control the server:

controls {
        inet 127.0.0.1 allow { localhost; } keys { rndckey; };
};


# Include other things into the configuration file, things that
# automatic configuration tools that modify this file might make
# a mess of:  (Though, if you don't use such tools, you can do
# all the configuration within this file.  Nowadays, I have it
# all in the one /etc/named.conf file.)

include "/etc/named.custom";


# Cryptographic key to allow certain things:  (Refer to a file
# with the information, here, and in other configuration files,
# rather than copy the information in that file into each
# configuration file.)

include "/etc/rndc.key";


# Set up the file used for the local domain's records:

zone "example.com" {
        type master;
        file "example.com.zone";
        allow-update { key "rndckey"; };
        allow-transfer { 192.168.0/24; };
        notify yes;
};

zone  "0.168.192.in-addr.arpa" { 
        type master; 
        file  "0.168.192.in-addr.arpa.zone"; 
        allow-update { key "rndckey"; };
        allow-transfer { 192.168.0/24; };
        notify yes;
};

The “allow-update” line allows my local DHCP server to add records to the zone, the key that it refers to is named in that “/etc/rndc.key” file that's included (these aren't needed for running master and slave DNS servers).

The “allow-transfer” allows only my local slave DNS server(s) (in the same 192.168.0.x subnets) to read the zone records for duplication, other slave servers (if any were connected) will be ignored.  This setting allows slave servers to operate from any address within that subnet, but specific addresses for slave servers could be used, instead.

“/etc/named.custom” file contents:

## named.custom

# These are extra configuration options in a separate file, one
# that'll be left alone by other programs that might modify the
# "named.conf" file:


# Set the server to only listen on LAN addresses, and only allow
# queries from LAN addresses:

options {
        directory "/var/named/";
        allow-query { lan; };
        query-source address * port 53;
        listen-on { 127.0.0.1; };
        listen-on { 192.168.0.1; };
};


# Define what you consider to be your LAN: (In this case, the
# local loopback address, and the IP range used by the local
# area network:  192.168.0.0-192.168.0.255)
 
acl lan {
        127.0.0.1;
        192.168.0/24;
};


# Refer to a file with the root server (for the entire internet)
# addresses:

zone "." {
        type hint;
        file "named.ca";
};

The opening set of options set parameters for the server:  The directory the DNS records are stored in.  Where queries will be allowed from (what “lan” means is defined further down).  Where the server will make queries from when it queries other servers (in this case, a “wildcard” meaning any interface on this machine, and using port 53).  And where it will listen for queries made of it.

The definition of an Access Control List (ACL) named “lan”, referring to the local loopback address (127.0.0.1) and the private address range of 192.168.0.0–192.168.0.255.  An other configuration control can use this definition, merely by referring to the “lan” ACL.  You can name it what you like, I named mine that way because I'm using it with my LAN.

A definition for the root level servers for the entire internet.  These servers are the master servers for all other DNS servers in the world.

As mentioned in the configuration file, you can use one file with all those configuration details in it, rather than separate .conf and .custom files, if you're going to hand-edit the file.  Mine was separated thanks to the configuration GUI tool I was using, but now I have it all in the one /etc/named.conf file.

“/etc/rndc.key” file contents:

key "rndckey" {
        algorithm       hmac-md5;
        secret "BCHdfIJKdLfMgfNhgOwPeQreUhRhShdSJWdewjERUzGwT";
};

The “secret” information is a generated random string of characters.  The one I've displayed (above) is fake, you need to generate your own.  You'll have to read the manuals for how to do that, I generated mine so long ago that I don't recall the process.

“/var/named/example.com.zone” file contents:

$TTL 86400
@       IN      SOA     ns.example.com. hostmaster.example.com. (
                        50 ; serial
                        28800 ; refresh (8 hours)
                        7200 ; retry (2 hours)
                        604800 ; retire (1 week)
                        86400 ; ttl (1 day)
                        )

        IN      NS      ns.example.com.

@       IN      MX      1       mail.example.com.

@       IN      A       192.168.0.1
ns      IN      A       192.168.0.1
mail    IN      A       192.168.0.1
www     IN      A       192.168.0.1
one     IN      A       192.168.0.1
two     IN      A       192.168.0.2
three   IN      A       192.168.0.3
four    IN      A       192.168.0.4

This starts off with a time-to-live value of 86400 seconds (8 hours), and has other time values in the following section (the values in brackets are for our benefit, the computer only uses the number left of the semi-colon).

Following is a start-of-authority (SOA) record which mentions which server will be the authoritative name server for this domain (“ns.example.com”), and the e-mail address for the person responsible for maintaining it (“hostmaster@example.com”).  The @ sign has a special meaning in DNS records, so it can't be used.  The first dot is interpreted as being an @ sign.  This means you couldn't have an address like “firstname.lastname@example.com”, here, unless you escape the preceeding dots with a backslash (e.g. “mr\.john\.smith.example.com.”).  Don't ask me why they didn't decide to let you escape the @ sign, instead.

Within the SOA record is a serial number and various time values.  There's a serial number that's incremented each time the record is altered (so other servers can tell when the record has been updated, and know to update theirs).  And several different bits of information about expiry times for this data:  Refresh the records every 8 hours (check for updates from the master server).  If the master server isn't responding wait for two 2 hours before trying to refresh the records again (retry).  Discard unrefreshed (retire) the data after a week (if the server hasn't been able to refresh the data, it stops acting as an authoritative server).  Other servers should cache this data for at least one day, and keep serving the information, even if they've not been able to check master servers for updates during this time (minimum/TTL/time-to-live).  The values I've used were copied from somewhere else, I haven't put any great thought into what's best to use.

Then there's a line that sets a name server (NS) record in this zone file. It identifies the address for the nameserver.  The address is supposed to be a domain name, so if you're typing in a fully-qualified domain name, then end it with a dot.  Else it'll be treated as a hostname, and this record's domain name will be appended to it (to create a fully-qualified domain name).  e.g. If you mistakenly wrote it as just “ns.example.com”, without the trailing dot, it'd be treated as being “ns.example.com.example.com.” (and, naturally, won't work).  Normally a domain would have at least two name servers, you'd do that with another similar looking “NS” record (with a different address for the other server), but I don't have a second name server on my network running all the time.

Followed by a line setting a mail exchanger (MX) record for this domain.  It not only sets the address, but also the priority (the number after “MX”).  Normally a domain should have more than one mail server, and at least one of them ought to have a higher priority than the others (I don't have a spare machine to use as an extra mail server).  The address is a domain name, so it follows the same rule about ending it with a dot as I just detailed for the name server record (above).

Following that is a series of A records which'll provide the IP address for queries about the hostnames listed on the left.  Since they don't end with a dot they're “hostnames”, and the domain name will be appended to them to make a “fully-qualified domain name” (e.g. because of the way the record is written, there, the “www” entry is “www.example.com.”).  You could write “www.example.com.” (note the trailing dot) there, instead of “www”, but you'd just be wasting your effort—it's unneccessary.  And a query to find the numerical IP for “www.example.com.”, would return a result of “192.168.0.1”.

The first “@” record is the IP address for the domain name by itself (“example.com”).  The following records return the IP addresses for queries about the fully-qualified domain names for this domain name (e.g. “mail.example.com.” is at “192.168.0.1”, “two.example.com.” is at “192.168.0.2”, and so on).

“/var/named/0.168.192.in-addr.arpa.zone” file contents:

$TTL 86400
@       IN      SOA     ns.example.com. hostmaster.example.com. (
                        50 ; serial
                        28800 ; refresh
                        7200 ; retry
                        604800 ; expire
                        86400 ; ttl
                        )
 
 
@       IN      NS      ns.example.com.
 
1       IN      PTR     one.example.com.
2       IN      PTR     two.example.com.
3       IN      PTR     three.example.com.
4       IN      PTR     four.example.com.

As before, there's a SOA record, constructed in the same manner, followed by the name server record for this zone file.

Following this is a block of PTR records which'll provide the named address for any queries about numerical IP records.  For instance, a query to find the named address associated with the numerical IP of “192.168.0.1” would return a result of:  “www.example.com.”

Reverse look-up records, as these are, cannot have multiple answers for the same queries.  Unlike the forward records (see the prior section, above), which can have multiple names associated with the same IP.

192.168.0.2 (the slave's)

“/etc/named.conf” file contents:

## named.conf

controls {
        inet 127.0.0.1 allow { localhost; } keys { rndckey; };
};

include "/etc/named.custom";
include "/etc/rndc.key";

# Configure the server to act as a slave for the example.com
# domain, and copy the records from a master server for that
# domain from the supplied address(es):

zone "example.com" {
        type slave;
        file "slaves/example.com.zone";
        masters { 192.168.0.1; };
};

zone "0.168.192.in-addr.arpa" {
        type slave;
        file "slaves/0.168.192.in-addr.arpa.zone";
        masters { 192.168.0.1; };
};

192.168.0.2's /etc/named.custom file can be exactly the same as 192.168.0.1's, and its ”/var/named/slaves/example.com.zone“ file will be generated when the server updates the records.  Likewise, its “slaves/0.168.192.in-addr.arpa.zone” file will be generated at the same time.

If the server is running chrooted, these files inside the “/etc/” and “/var/” directories aren't directly in the filesystem's root, but within their own directories inside “/var/named/chroot/”.  The “chroot” sub-directory will be regarded as the root directory, as far as the chrooted DNS server is concerned.

e.g. “/var/named/chroot/etc/named.conf”, “/var/named/chroot/etc/named.custom”, “/var/named/chroot/var/named/example.com.zone”, and “/var/named/chroot/var/named/slaves/example.com.zone”

This is done for security reasons—if anyone manages to find an exploit in the DNS server, theoretically they'll only be able to stuff up the files within its own chrooted environment, instead of any file on the system.  Of course, if they find an exploit in your computer that gives them access to the entire filesystem, chrooting it isn't going to help.


Integrating a local DHCP server with the local DNS server

I have occasional visitors with computers, and it's useful for them to be automatically configured by my DHCP server, and for it to also automatically reconfigure the local DNS server records with their addresses.  The following configuration file allows that to happen, as well as providing these guest machines with quite a few local service addresses.  This allows a lot of things to be automatically configured, though most of that information will be ignored by many clients.

On systems using SELinux protection, you'll need to adjust SELinux settings to allow the name server to overwrite master records on the master name server.  You don't need to do anything (like this) on the slave servers, they do all their work on the slave files.

“/etc/dhcpd.conf” file contents:

authoritative;

include "/etc/rndc.key";
# (This is the same key used by BIND and the rndc tool, it's needed to
#  be able to update DNS records.)

# Server configuration:
ddns-domainname         "example.com.";
ddns-rev-domainname     "in-addr.arpa.";
ddns-update-style       interim;
ddns-updates            on;
allow                   client-updates;

default-lease-time      21600;  # 6 hours
max-lease-time          43200;  # 12 hours

# Client configuration:
option domain-name      "example.com.";
option nntp-server      news.example.com;
option pop-server       pop3.example.com;
option smtp-server      smtp.example.com;
option wpad-curl        code 252 = text;
option wpad-curl        "http://proxy.example.com/wpad.dat";
option www-server       www.example.com;
option ntp-servers      time.example.com;
#option time-offset     34200;  # Australian Central Standard Time
option time-offset      37800;  # Central Australia Daylight Time

option ip-forwarding    off;    # tell clients not to act as gateways (?)


subnet 192.168.0.0 netmask 255.255.255.0 {

        range 192.168.0.100 192.168.0.200; # allocate IPs within this range

        option routers                  192.168.0.1;  # default gateway
        option subnet-mask              255.255.255.0;
        option broadcast-address        192.168.0.255;
        option domain-name-servers      192.168.0.1;

        option netbios-name-servers     192.168.0.1;  # WINS
        option netbios-dd-server        192.168.0.1;  # SMB
        option netbios-node-type 8;
        option netbios-scope "";

        option finger-server            192.168.0.1;

        zone  0.168.192.in-addr.arpa. {
                primary 192.168.0.1;
                key rndckey;
        }

        zone example.com. { 
                primary 192.168.0.1;
                key rndckey;
        }
}

The configuration file starts with the “authoritative” statement, meaning that this DHCP server is an authoritative one.

The following line includes a secret key used to allow changes to configurations.  Both the DHCP and DNS server use the same key.  Anything else (e.g. something trying to hack the server) won't have that key, and will be ignored.

The next block (starting with “ddns”, for the dynamic DNS settings) controls the domain names used (for resolving domain names to numerical IP addresses), the reverse domain names used (for resolving numerical IP to domain names), the protocol for communicating between the DHCP and DNS server (interim), whether to update the DNS records with DHCP-configured details (ddns-updates on), and whether to allow the clients (the connecting devices) to provide some of the details used (allow client-updates), else the DHCP server would make all the decisions for the clients (this is chiefly to do with the clients being able to ask to use the hostname that they want to).

The next block sets the lease times (how long addresses are assigned for, before the assignment is renegotiated).

The next block sets various optional parameters that can be supplied to the clients for them to automatically configure themselves to use various services.  Many of them are ignored by many clients, though the WPAD ones are used by Microsoft's Internet Explorer and some of the newer Mozilla browsers to set up their proxy server details (the mysterious “automatically detect settings” in the “connections” part of the “internet options” control panel for Internet Explorer, and the “auto-detect proxy settings for this network” in Mozilla Firefox, to give just a couple of examples).

There's a line configuring “ip-forwarding” that's not adequately explained in the manuals, so I can't explain it properly either, other than the comment I've made in the configuration file.

Then the next section are parameters that are specific to a certain subnet (the “192.168.0.0” subnet using the “255.255.255.0” netmask).  Although there's only one subnet mentioned in this example, there could be several.  It (literally) brackets the options particular to that subnet.

This subnet allocates IP addresses to client machines from “192.168.0.100” through to “192.168.0.200”.  These clients are configured to use the parameters mentioned in the following option statements.

The first block of four options are the main network configuration details needed on the clients for TCP/IP networking to work.

The next block of four options are for SMB resource sharing (“network neighbourhood” on Windows, for sharing files, printers, etc.), and are only needed if you're doing that sort of thing (and probably ignored by your computer anyway, requiring you to manually configure them in some other way).

The next one is the address for a finger server (used to find out information about users on a system).  Most systems don't have one of them, I happen to have one, and it can be handy (it can say who's currently on-line, provide their contact details, and let you know when you've got waiting mail).

The next two things control what DNS zones will be updated by this DHCP server.

The options placed inside the subnet section only apply to that subnet (allowing you to control different networks with different parameters from each other), options placed outside of it apply to all subnets.  You don't need most of these options (they're for various servers on this network), they're just examples of the sorts of thing that can be set.  You definitely don't want to tell your systems details for services that you don't have available, so don't copy everything I've written without customising it for your own system (copy it, modify addresses to suit your system, and remove the stuff that doesn't).  And you don't need to arrange them in the order that I've written them in, that's just for my benefit, and to help with writing the explanations that go along with the examples.

Notice that the closing braces aren't followed by a semi-colon, unlike the DNS server's configuration files.  The examples I originally followed had them, and the service refused to work until I removed them.

The comments written after hash marks are ignored by the software, they're only there for our benefit.

I haven't worked out whether the DHCP server configuration file follows the rule of ending “fully-qualified domain names” with a dot, or it just assumes whatever you type in is a domain name (like most internet software assumes—most seem to assume a hostname is a fully-qualified domain name if it has more than one dot in it, rather than checking if it ends in a dot).


Contents
Main sections:
homepage
contact details
business info
personal info
eBay & trading
“sales” ads
“wanted” ads
electronics
video production
photography
computing
reviews
misc info
website info/help
links
index
search
Computing
Introduction
my computers
Linux
Windows
general info
desktop publishing
typing skills
WWW authoring
internet primer
turn it off?
electrical safety
Linux
Introduction
why use Linux
why I use Linux
compatible hardware
feeling lucky?
Evolution signatures
installing software
auto NTPD restart
local DNS serving
restoring GRUB
overzealous HDD parking
Post-install customising
NFS serving
SMTP settings for Yahoo
time serving