Friday, October 31, 2008

Configuring LAN DCHP and Dynamic DNS under Ubuntu Linux

(This post is the 6th part of my Ubuntu Linux Router Upgrade Project.)

After configuring routing and NAT in my last post, while the Internet access may be shared, other clients won't know about it unless manually configured, requiring at least an IP address and subnet, local gateway, and one or more DNS servers for proper access.

DHCP

As DHCP is used to retrieve IP configuration information for the router from the Internet, it can also be served from the router to the LAN, and is probably the easiest way to configure networking within a LAN.

In OpenWrt, Dnsmasq was used for this purpose. However, it is relatively simple, and part of this project was to learn other Linux standards. For this project, I chose ISC's DHCP Distribution (a.k.a. "dhcpd", "dhcp3-server"), which seems to be the most popular and full-featured choice for a DHCP server under Linux. (See also dhcp3-server on help.ubuntu.com.)

ISC's DHCP Distribution is available as an Ubuntu-maintained package, "dhcp3-server". See "InstallingSoftware" on help.ubuntu.com for notes on installing software. A good write-up on installing and configuring dhcp3-server in particular is available at http://www.howtoforge.com/dhcp_server_linux_debian_sarge.

One of the main prerequisites is to have a static IP address on the interface that dhcp3-server will be bound to and serving IP addresses on. For this project, this was already done as part disabling NetworkManager in Configuring Persistent PPP.

The server then needs to be configured, using "/etc/dhcp3/dhcpd.conf". Shown below is mine:

# option definitions common to all supported networks...
option domain-name "lan.ziesemer.com";

default-lease-time 691200; #600;
max-lease-time 691200; #7200;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;

subnet 192.168.###.0 netmask 255.255.255.0 {
 range 192.168.###.### 192.168.###.###;
 option routers 192.168.###.1;
 option domain-name-servers 192.168.###.1; 
 ddns-domainname "lan.ziesemer.com.";
}

host static-host-name {
 hardware ethernet xx:xx:xx:xx:xx:xx;
 fixed-address 192.168.###.###;
}

DNS

In order for clients to resolve domain names to IP addresses, DNS Servers need to be defined. For many ISP consumers, DNS servers provided by the ISP are used. Unfortunately, more and more ISPs, including Charter Communications, feel obliged to break standard Internet protocol (RFC 2308) and hijack these requests, posing security and other implications. (See also "DNS hijacking" on Wikipedia.) As such, running a local resolver becomes rather desirable, which can also offer performance advantages, and the ability to offer DNS services for the local domain.

As with DHCP, in OpenWrt, Dnsmasq was also used for this purpose. Again, I chose something a bit more "heavy-weight" and popular, BIND (a.k.a. "named"). (See also: http://en.wikipedia.org./wiki/BIND and https://help.ubuntu.com/community/BIND9ServerHowto.) Again, "bind9" will have to be installed.

There are 3 main files for configuring BIND: "/etc/bind/named.conf", "/etc/bind/named.conf.options", and "/etc/bind/named.conf.local", the later two of which are both included by the first.

There is really nothing needed for a basic configuration. However, adding the RFC 1918 zones into named.conf.local as commented in the file is recommended. However, as I'm using 192.168.###.###, I didn't want to uncomment the line to include the entire file. Instead, I did a "literal" include by copying in the contents of the "/etc/bind/zones.rfc1918" file, except for the last line that contained zone "168.192.in-addr.arpa".

Making this DNS server known to the LAN was already accomplished in the dhcpd configuration above by "option domain-name-servers".

Local DNS and Dynamic Updates

Now for the advanced part - configuring a local domain with dynamic updates. Two other posts I reviewed were http://www.semicomplete.com/articles/dynamic-dns-with-dhcp/ and http://www.debian-administration.org/articles/343, neither of which seemed completely correct, comprehensive, or up-to-date - though this post isn't exactly meant to be completely comprehensive, either.

The first thing is to generate a secure key used to allow dhcpd to send updates to named. "/usr/sbin/rndc-confgen" can be used to generate this key context. Running it without any arguments will output 2 sections that are meant to be copied and pasted into the named files, "rndc.conf" and "named.conf". Alternatively, running it with the "-a" argument will generate just the "key" clause, and write it to the default key file ("(/etc/bind/rndc.key", run with sudo). It seems that I needed all 3 parts, but running both versions would result in separate keys. I used the "-a" argument, then copied out the key for manually updating the other 2 files. This assumes that both dhcpd and named are running on the same server, which isn't necessary.

Assume the following was output to "/etc/bind/rndc.key" using "sudo /usr/sbin/rndc-confgen -a":

key "rndc-key" {
 algorithm hmac-md5;
 secret "hp83n+fUOC2LdoDF9S12wg==";
};

The following should then be added to "/etc/bind/named.conf" (at no particular location):

include "/etc/bind/rndc.key";
controls {
 inet 127.0.0.1 allow {
  localhost;
 }
 keys {
  rndc-key;
 };
};

Next, the following should then be added to "/etc/dhcp3/dhcpd.conf" (at no particular location):

ddns-update-style interim;

key "rndc-key" {
 algorithm hmac-md5;
 secret hp83n+fUOC2LdoDF9S12wg==;
};

Note that quotes around the secret are not allowed here. Including quotes will produce errors.

At this point, both dhcpd and named now share a "secret" key used to authenticate dhcpd to named for updating DNS entries.

Now, we need to define a DNS zone in "/etc/bind/named.conf.local" for the LAN:

zone "lan.ziesemer.com" {
 type master;
 file "/var/lib/bind/lan.ziesemer.com.zone";
 allow-update {
  key "rndc-key";
 };
 notify yes;
};

zone "##.168.192.in-addr.arpa" {
 type master;
 file "/var/lib/bind/##.168.192.in-addr.arpa.zone";
 allow-update {
  key "rndc-key";
 };
 notify yes;
};

The "allow-update" sections with the "key" are references to the key defined in "/etc/bind/rndc.key" (and included from "/etc/bind/named.conf") that is allowed to make updates for the zones.

Note the location of the zone files. Originally, I had these in "/etc/bind" as well, but ran into "permission denied" errors whenever updates were attempted, even after editing permissions on the files. It seems that even with opened permissions, the files are protected by AppArmor. This is further described in the "bind / dhcp jnl failure - permission denied" thread on ubuntuforums.org.

The referenced zone files then need to be created, the process of which is outside the scope of this post. Refer to the above linked articles for further reference. For the purpose of dynamically updated zones, these files should be chmod'd to 755, with both the user and group set to "bind". (I don't recall doing this, so they may be automatically set at some point?)

Finally, the following should be included in the subnet block declared in "/etc/dhcp3/dhcpd.conf" (above):

subnet 192.168.###.0 netmask 255.255.255.0 {
 zone lan.ziesemer.com. {
  primary 127.0.0.1;
  key "rndc-key";
 }

 zone ##.168.192.in-addr.arpa. {
  primary 127.0.0.1;
  key "rndc-key";
 }
}

Restart the services for a fully functional LAN:

sudo /etc/init.d/dhcp3-server restart
sudo /etc/init.d/bind9 restart

No comments: