DHCP

Updated 21 September 2021

DHCP

DHCP is a network management protocol used on UDP/IP networks

DHCP configuration

Configure your network:

cl-setup-network --iface eth0:192.168.50.3:24 --route default:192.168.50.1 --dns 8.8.8.8

/etc/conf.d/net

config_eth0="192.168.50.3/24"
routes_eth0="default via 192.168.50.1/24"
dns_servers="8.8.8.8"

Then install the DHCP and the DNS packages:

emerge dhcp bind

Set up the DHCP server:

  • used network: 192.168.50.0/24, netmask: 255.255.255.0
  • IP addresses issued from 192.168.50.100 to 192.168.50.200
  • forwarded IP of the DNS server: 192.168.50.3
  • IP of the gateway, forwarded by default: 192.168.50.1
  • broadband address: 192.168.50.255
  • domain: example.org
  • leased for: a week

/etc/dhcp/dhcpd.conf

shared-network mylan {
    subnet 192.168.50.0 netmask 255.255.255.0 {
        range 192.168.50.100 192.168.50.200;
        option domain-name-servers 192.168.50.3;
        option domain-name "example.org";
        option routers 192.168.50.1;
        option broadcast-address 192.168.50.255;
        default-lease-time 604800;
        max-lease-time 604800;
    }
}

Add DHCP to autostart and start it, actually:

rc-update add dhcpd

rc-service dhcpd start

DNS configuration

Re-generate the key for updating DNS entries:

tsig-keygen rndc-key >/etc/bind/rndc.key

Configure access to the key:

chmod 640 /etc/bind/rndc.key

chown root:named /etc/bind/rndc.key

Use the sample settings to create your configuration file:

cp -a /etc/bind/named.conf.origin /etc/bind/named.conf

Apply the DNS configuration:

/etc/bind/named.conf
/*
 * Refer to the named.conf(5) and named(8) man pages, and the documentation
 * in /usr/share/doc/bind-* for more details.
 * Online versions of the documentation can be found here:
 * https://kb.isc.org/article/AA-01031
 *
 * If you are going to set up an authoritative server, make sure you
 * understand the hairy details of how DNS works. Even with simple mistakes,
 * you can break connectivity for affected parties, or cause huge amounts of
 * useless Internet traffic.
 */

acl "xfer" {
    /* Deny transfers by default except for the listed hosts.
     * If we have other name servers, place them here.
     */
    127.0.0.1;
};

/*
 * You might put in here some ips which are allowed to use the cache or
 * recursive queries
 */
acl "trusted" {
    127.0.0.0/8;
    192.168.50.0/24;
    ::1/128;
};

options {
    directory "/var/bind";
    pid-file "/run/named/named.pid";

    /* https://www.isc.org/solutions/dlv >=bind-9.7.x only */
    //bindkeys-file "/etc/bind/bind.keys";

    listen-on-v6 { ::1; };
    listen-on {
        127.0.0.1;
        192.168.50.0/24;
    };

    allow-query {
        /*
         * Accept queries from our "trusted" ACL.  We will
         * allow anyone to query our master zones below.
         * This prevents us from becoming a free DNS server
         * to the masses.
         */
        trusted;
    };

    allow-query-cache {
        /* Use the cache for the "trusted" ACL. */
        trusted;
    };

    allow-recursion {
        /* Only trusted addresses are allowed to use recursion. */
        trusted;
    };

    allow-transfer {
        /* Zone tranfers are denied by default. */
        xfer;
    };

    allow-update {
        /* Don't allow updates, e.g. via nsupdate. */
        none;
    };

    /*
    * If you've got a DNS server around at your upstream provider, enter its
    * IP address here, and enable the line below. This will make you benefit
    * from its cache, thus reduce overall DNS traffic in the Internet.
    *
    * Uncomment the following lines to turn on DNS forwarding, and change
    *  and/or update the forwarding ip address(es):
    */
    forward first;
    forwarders {
    //  123.123.123.123;    // Your ISP NS
    //  124.124.124.124;    // Your ISP NS
    //  4.2.2.1;        // Level3 Public DNS
    //  4.2.2.2;        // Level3 Public DNS
        8.8.8.8;        // Google Open DNS
        8.8.4.4;        // Google Open DNS
    };

    dnssec-enable yes;
    //dnssec-validation yes;

    /*
     * As of bind 9.8.0:
     * "If the root key provided has expired,
     * named will log the expiration and validation will not work."
     */
    dnssec-validation auto;

    /* if you have problems and are behind a firewall: */
    //query-source address * port 53;
};

/*
logging {
    channel default_log {
        file "/var/log/named/named.log" versions 5 size 50M;
        print-time yes;
        print-severity yes;
        print-category yes;
    };

    category default { default_log; };
    category general { default_log; };
};
*/

include "/etc/bind/rndc.key";
controls {
    inet 127.0.0.1 port 953 allow { 127.0.0.1/32; ::1/128; } keys { "rndc-key"; };
};

zone "." in {
    type hint;
    file "/var/bind/named.cache";
};

zone "localhost" IN {
    type master;
    file "pri/localhost.zone";
    notify no;
};

/*
 * Briefly, a zone which has been declared delegation-only will be effectively
 * limited to containing NS RRs for subdomains, but no actual data beyond its
 * own apex (for example, its SOA RR and apex NS RRset). This can be used to
 * filter out "wildcard" or "synthesized" data from NAT boxes or from
 * authoritative name servers whose undelegated (in-zone) data is of no
 * interest.
 * See http://www.isc.org/software/bind/delegation-only for more info
 */

//zone "COM" { type delegation-only; };
//zone "NET" { type delegation-only; };

//zone "YOUR-DOMAIN.TLD" {
//  type master;
//  file "/var/bind/pri/YOUR-DOMAIN.TLD.zone";
//  allow-query { any; };
//  allow-transfer { xfer; };
//};

//zone "YOUR-SLAVE.TLD" {
//  type slave;
//  file "/var/bind/sec/YOUR-SLAVE.TLD.zone";
//  masters { <MASTER>; };

    /* Anybody is allowed to query but transfer should be controlled by the master. */
//  allow-query { any; };
//  allow-transfer { none; };

    /* The master should be the only one who notifies the slaves, shouldn't it? */
//  allow-notify { <MASTER>; };
//  notify no;
//};

zone "example.org" {
        type master;
        file "/var/bind/dyn/example.org.zone";
        allow-update { key rndc-key; };
};

zone "50.168.192.in-addr.arpa" {
        type master;
        file "/var/bind/dyn/example.org.rev.zone";
        allow-update { key rndc-key; };
};
  • add 192.168.50.0/24 to the trusted zones
  • specify the DNS servers to access (~8.8.8.8.8~) if the current one cannot find the name or IP address of the request
  • add the forward zone example.org and the reverse zone 50.168.192.in-addr.arpa
  • specify the listen-on addresses 192.168.50.0/24
  • enable the current host to receive the contents of the zone (transfer)

Create the necessary files for the declared forward and reverse zones:

/var/bind/dyn/example.org.zone

$ORIGIN example.org.
$TTL 86400   ; 1 day
@ IN SOA ns1.example.org. root.example.org. (
    2018031401 ; Serial
    10800      ; Refresh (3 hours)
    3600       ; Retry (1 hour)
    604800     ; Expire (1 week)
    86400      ; Minimum (1 day)
)

               IN      NS  ns1.example.org.
@              IN      A   192.168.50.3
ns1            IN      A   192.168.50.3
gw             IN      A   192.168.50.1
localhost      IN      A   127.0.0.1
dns            IN      A   192.168.50.3

/var/bind/dyn/example.org.rev.zone

$ORIGIN 50.168.192.in-addr.arpa.
$TTL 86400   ; 1 day
@ IN SOA ns1.example.org. root.example.org. (
    2018031401 ; Serial
    10800      ; Refresh (3 hours)
    3600       ; Retry (1 hour)
    604800     ; Expire (1 week)
    86400      ; Minimum (1 day)
)

           IN      NS  ns1.example.org.
1          IN      PTR  gw.example.org.
3          IN      PTR  ns1.example.org.

Configure access to these zones:

chgrp -R named /var/bind/dyn

chmod 660 /var/bind/dyn/*

chmod 770 /var/bind/dyn

In settings, add the following lines for updating records when issuing an IP.

/etc/dhcp/dhcpd.conf

ddns-update-style interim;
# update static IPs registered in DHCP
update-static-leases on;

# use key from bind
include "/etc/bind/rndc.key"

zone example.org. {
    primary 127.0.0.0.1;
    key rndc-key;
}

zone 50.168.192.192.in-addr.arpa. {
    primary 127.0.0.0.1;
    key rndc-key;
}

Add DNS to autostart, then start it and restart DHCP:

rc-update add named

rc-service named start

rc-service dhcpd restart

Now, whenever an IP address is assigned to a host, a corresponding entry will be added to the zone description files (/var/bind/example.org.zone and /var/bind/example.org.rev.zone).

Overview

rndc sync

cat /var/bind/dyn/example.org.zone

$ORIGIN .
$TTL 86400  ; 1 day
example.org     IN SOA  ns1.example.org. root.example.org. (
                2018031406 ; serial
                10800      ; refresh (3 hours)
                3600       ; retry (1 hour)
                604800     ; expire (1 week)
                86400      ; minimum (1 day)
                )
            NS  ns1.example.org.
$ORIGIN example.org.
$TTL 3600   ; 1 hour
client          A   192.168.50.101
            TXT "317e714be5304884a0829b791e1d79b481"
$TTL 86400  ; 1 day
dns         A   192.168.50.3
gw          A   192.168.50.1
localhost       A   127.0.0.1
ns1         A   192.168.50.3
$ORIGIN .

cat /var/bind/dyn/example.org.rev.zone

$TTL 86400  ; 1 day
50.168.192.in-addr.arpa IN SOA  ns1.example.org. root.example.org. (
                2018031402 ; serial
                10800      ; refresh (3 hours)
                3600       ; retry (1 hour)
                604800     ; expire (1 week)
                86400      ; minimum (1 day)
                )
            NS  ns1.example.org.
$ORIGIN 50.168.192.in-addr.arpa.
1           PTR gw.example.org.
$TTL 3600   ; 1 hour
100         PTR client.example.org.
$TTL 86400  ; 1 day
3           PTR ns1.example.org.

Modifying zone entries

Zones that are updated dynamically can be modified either using a special tool or by editing files stored in /var/bind.

Updating dynamic zones with nsupdate

The nsupdate tool is found in the net-dns/bind-tools package. This package also containes dig, that allows to unload a zone.

Install bind-tools:

emerge bind-tools

To get the contents of the example.org zone, run:

dig -t axfr example.org.
; <<>> DiG 9.11.2-P1 <<>> -t axfr example.org.
;; global options: +cmd
example.org.        86400   IN  SOA ns1.example.org. root.example.org. 2018031402 10800 3600 604800 86400
example.org.        86400   IN  NS  ns1.example.org.
client.example.org. 3600    IN  A   192.168.50.100
client.example.org. 3600    IN  TXT "3173d9bec89af77517b8cff6e3c19edb9f"
dns.example.org.    86400   IN  A   192.168.50.3
gw.example.org.     86400   IN  A   192.168.50.1
localhost.example.org.  86400   IN  A   127.0.0.1
ns1.example.org.    86400   IN  A   192.168.50.3
example.org.        86400   IN  SOA ns1.example.org. root.example.org. 2018031402 10800 3600 604800 86400
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tu mar 15 15:12:23 MSK 2018
;; XFR size: 9 records (messages 1, bytes 314)

To get the contents of the reverse zone run:

dig -t axfr 50.168.192.in-addr.arpa
; &lt;&lt;&gt;&gt; DiG 9.11.2-P1 &lt;&lt;&gt;&gt; -t axfr 50.168.192.in-addr.arpa
;; global options: +cmd
50.168.192.in-addr.arpa. 86400  IN  SOA ns1.example.org. root.example.org. 2018031402 10800 3600 604800 86400
50.168.192.in-addr.arpa. 86400  IN  NS  ns1.example.org.
1.50.168.192.in-addr.arpa. 86400 IN PTR gw.example.org.
100.50.168.192.in-addr.arpa. 3600 IN    PTR client.example.org.
3.50.168.192.in-addr.arpa. 86400 IN PTR ns1.example.org.
50.168.192.in-addr.arpa. 86400  IN  SOA ns1.example.org. root.example.org. 2018031402 10800 3600 604800 86400
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tu mar 15 15:12:04 MSK 2018
;; XFR size: 6 records (messages 1, bytes 246)

Since zone update is configured with the /etc/bind/rndc.key key, it must be passed on to the utility:

nsupdate -k /etc/bind/rndc.key

The command line will open, so that you could work with DNS. To get the full list of commands, run help, to exit run +quit.

Run the following to remove the client.example.org entry from the zone:

nsupdate -k /etc/bind/rndc.key

del client.example.org
send
quit

To add client.example.org to the example.org zone, run:

nsupdate -k /etc/bind/rndc.key

nxdomain client.example.org
add client.example.org 3600 A 192.168.1.100
send
quit

The nxdomain command is used to check that there is no client.example.org entry in DNS. The add command adds an A record to client.example.org corresponding to ~192.168.1.100~~ with one hour TTL (3600).

You can use CNAME+ to assign an alias to a zone instead of an A record (the domain name matching an IP address). Add the CNAME entry, comp1.example.org to client.example.org:

nsupdate -k /etc/bind/rndc.key

nxdomain comp1.example.org
add comp1.example.org 3600 CNAME client.example.org
send
quit

To delete the 192.168.50.100 entry from the reverse zone, run the following command:

nsupdate -k /etc/bind/rndc.key

del 100.50.168.192.in-addr.arpa. 
send
quit

To add the reverse entry 192.168.50.100 on client.example.org to the reverse zone, run the following command:

nsupdate -k /etc/bind/rndc.key

nxdomain 100.50.168.192.in-addr.arpa 
add 100.50.168.192.in-addr.arpa. 3600 PTR client.example.org.
send
quit

Editing zone descriptions

To edit zone files manually, you must first temporarily disable dynamic modification and only then proceed to editing. Once the files modified, you have to enable dynamic modifications again:

rndc sync

rndc freeze example.org

/var/bind/dyn/example.org.zone

rndc reload example.org

rndc thaw example.org

Where:

  • rndc sync transfers temporary changes from the log to the zone description file;
  • rndc freeze disables dynamic modification;
  • rndc reload rereads the description file;
  • rndc thaw enables dynamic modification.

You must increase the serial number each time you edit the zone.

Example
$ORIGIN .
$TTL 86400  ; 1 day
example.org     IN SOA  ns1.example.org. root.example.org. (
                2018031406 ; serial
                10800      ; refresh (3 hours)
                3600       ; retry (1 hour)
                604800     ; expire (1 week)
                86400      ; minimum (1 day)
                )
            NS  ns1.example.org.
$ORIGIN example.org.
$TTL 3600   ; 1 hour
client          A   192.168.50.101
            TXT "317e714be5304884a0829b791e1d79b481"
$TTL 86400  ; 1 day
dns         A   192.168.50.3
gw          A   192.168.50.1
localhost       A   127.0.0.1
ns1         A   192.168.50.3

Update the MAC address for the host

The DNS entry will not be updated if a node with an identical host name exists already in the current zone, even though it has a different MAC address. This can also happen if the network card was changed on the computer. See the system log to check this:

/var/log/message

Mar 14 17:17:22 dns named[2760]: client @0x7fd25c042070 127.0.0.1#21937/key rndc-key: updating zone 'example.org/IN': update unsuccessful: client.example.org: 'name not in use' prerequisite not satisfied (YXDOMAIN)
Mar 14 17:17:22 dns named[2760]: client @0x7fd25c0389f0 127.0.0.1#21937/key rndc-key: updating zone 'example.org/IN': update unsuccessful: client.example.org/TXT: 'RRset exists (value dependent)' prerequisite not satisfied (NXRRSET)
Mar 14 17:17:22 dns dhcpd[2629]: Forward map from client.example.org to 192.168.50.101 FAILED: Has an address record but no DHCID, not mine.

If you want this entry to be updated from a new MAC address later on, you must delete an existing entry from the zone manually, in any of the ways described above.