Configure DHCP Failover with Dynamic DNS on CentOS 7

We are going to set up a DHCP failover with dynamic DNS.

This article is part of the Homelab Project with KVM, Katello and Puppet series.

Homelab

We have two CentOS 7 (minimal) servers installed which we want to configure as follows:

admin1.hl.local (10.11.1.2) – will be configured as a DHCP master server
admin2.hl.local (10.11.1.3) – will be configured as a DHCP slave server

Both servers have SELinux set to enforcing mode.

See the image below to identify the homelab part this article applies to.

Software

Software used in this article:

  1. CentOS 7
  2. DHCP 4.2

Configure Master DHCP Server

Installation and Firewall

Install packages and ensure that the service is enabled:

[admin1]# yum install dhcp
[admin1]# systemctl enable dhcpd

Configure firewall to allow DHCP traffic (we use iptables):

[admin1]# iptables -A INPUT -p udp -m state --state NEW -m udp --dport 67 -j ACCEPT

Allow DHCP peer communication from admin2:

[admin1]# -A INPUT -s 10.11.1.3/32 -p tcp -m state --state NEW -m tcp --dport 647 -j ACCEPT

Master dhcpd.conf Configuration

Open the file /etc/dhcp/dhcpd.conf and configure as per below.

Note that the parameter mclt (Maximum Client Lead Time) must be defined on the master server but must not be defined on the slave server. The parameter split is another parameter that should be defined on the primary and omitted from the configuration on the secondary. It is worth noting that the communication between failover nodes is neither encrypted nor authenticated.

failover peer "failover-dhcp" {
  primary; # This defines the master
  address 10.11.1.2;
  port 647;
  peer address 10.11.1.3;
  peer port 647;
  max-response-delay 60;
  max-unacked-updates 10;
  mclt 3600;
  split 128; # 128 is balanced; use 255 if primary is 100% responsible until failure
  load balance max seconds 3;
}

authoritative;
allow booting;
allow bootp;
next-server 10.11.1.4; # Katello TFTP
filename "pxelinux.0";
default-lease-time 86400; # 1 day
max-lease-time 86400; # 1 day

ddns-update-style interim;

update-static-leases on;
one-lease-per-client on;

# We generated the rndc-key when setting up DNS servers
key "rndc-key" {
  algorithm hmac-md5;
  secret "T0+1uWvaiKLkhWutTNhsGvLw7m4CXbjHr+3CrDwQP5ZMNHeRSvghg2XxQvT3uGVwNle9oMvBEcjB+4GEPDK1Qg==";
};
# We created zones when setting up DNS servers
zone 1.11.10.in-addr.arpa {
  primary 10.11.1.2;
  key "rndc-key";  
}
zone hl.local {
  primary 10.11.1.2;
  key "rndc-key";
}

subnet 10.11.1.0 netmask 255.255.255.0 {
  option subnet-mask 255.255.255.0;
  option broadcast-address 10.11.1.255;
  option routers 10.11.1.1;
  option domain-name-servers dns1.hl.local, dns2.hl.local;
  option domain-search "hl.local";
  pool {
    failover peer "failover-dhcp";
    range 10.11.1.40 10.11.1.59;
  }
}

# DHCP leases for PXE boot
host ldap1 {
  hardware ethernet 00:22:FF:00:00:11;
  fixed-address 10.11.1.11;
  option host-name "ldap1";
}
host ldap2 {
  hardware ethernet 00:22:FF:00:00:12;
  fixed-address 10.11.1.12;
  option host-name "ldap2";
}
host monitoring {
  hardware ethernet 00:22:FF:00:00:13;
  fixed-address 10.11.1.13;
  option host-name "monitoring";
}
host syslog {
  hardware ethernet 00:22:FF:00:00:14;
  fixed-address 10.11.1.14;
  option host-name "syslog";
}
host storage1 {
  hardware ethernet 00:22:FF:00:00:15;
  fixed-address 10.11.1.15;
  option host-name "storage1";
}
host storage2 {
  hardware ethernet 00:22:FF:00:00:16;
  fixed-address 10.11.1.16;
  option host-name "storage2";
}
host db1 {
  hardware ethernet 00:22:FF:00:00:17;
  fixed-address 10.11.1.17;
  option host-name "db1";
}
host db2 {
  hardware ethernet 00:22:FF:00:00:18;
  fixed-address 10.11.1.18;
  option host-name "db2";
}
host proxy1 {
  hardware ethernet 00:22:FF:00:00:19;
  fixed-address 10.11.1.19;
  option host-name "proxy1";
}
host proxy2 {
  hardware ethernet 00:22:FF:00:00:20;
  fixed-address 10.11.1.20;
  option host-name "proxy2";
}
host web1 {
  hardware ethernet 00:22:FF:00:00:21;
  fixed-address 10.11.1.21;
  option host-name "web1";
}
host web2 {
  hardware ethernet 00:22:FF:00:00:22;
  fixed-address 10.11.1.22;
  option host-name "web2";
}
host backup {
  hardware ethernet 00:22:FF:00:00:23;
  fixed-address 10.11.1.23;
  option host-name "backup";
}

Harden file permissions because of the plaintext rndc-key:

[admin1]# chmod 0600 /etc/dhcp/dhcpd.conf

Test the configuration file:

[admin1]# dhcpd -t -cf /etc/dhcp/dhcpd.conf

Restart the service:

[admin1]# systemctl restart dhcpd

Check leases:

[admin1]# tail /var/lib/dhcpd/dhcpd.leases

Configure Slave DHCP Server

Installation and Firewall

This part is the same as for the master server.

Install packages and ensure that the service is enabled:

[admin2]# yum install dhcp
[admin2]# systemctl enable dhcpd

Configure firewall to allow DHCP traffic (we use iptables):

[admin2]# iptables -A INPUT -p udp -m state --state NEW -m udp --dport 67 -j ACCEPT

Allow DHCP peer communication from admin1:

[admin2]# -A INPUT -s 10.11.1.2/32 -p tcp -m state --state NEW -m tcp --dport 647 -j ACCEPT

Slave dhcpd.conf Configuration

Open the file /etc/dhcp/dhcpd.conf and configure the following:

failover peer "failover-dhcp" {
  secondary; # This defines the slave
  address 10.11.1.3;
  port 647;
  peer address 10.11.1.2;
  peer port 647;
  max-response-delay 60;
  max-unacked-updates 10;
  load balance max seconds 3;
}

authoritative;
allow booting;
allow bootp;
next-server 10.11.1.4; # Katello TFTP
filename "pxelinux.0";
default-lease-time 86400; # 1 day
max-lease-time 86400; # 1 day

ddns-update-style interim;

update-static-leases on;
one-lease-per-client on;

# We generated the rndc-key when setting up DNS servers
key "rndc-key" {
  algorithm hmac-md5;
  secret "T0+1uWvaiKLkhWutTNhsGvLw7m4CXbjHr+3CrDwQP5ZMNHeRSvghg2XxQvT3uGVwNle9oMvBEcjB+4GEPDK1Qg==";
};
# We created zones when setting up DNS servers
zone 1.11.10.in-addr.arpa {
  primary 10.11.1.2;
  key "rndc-key";  
}
zone hl.local {
  primary 10.11.1.2;
  key "rndc-key";
}

subnet 10.11.1.0 netmask 255.255.255.0 {
  option subnet-mask 255.255.255.0;
  option broadcast-address 10.11.1.255;
  option routers 10.11.1.1;
  option domain-name-servers dns1.hl.local, dns2.hl.local;
  option domain-search "hl.local";
  pool {
    failover peer "failover-dhcp";
    range 10.11.1.40 10.11.1.59;
  }
}

# DHCP leases for PXE boot
host ldap1 {
  hardware ethernet 00:22:FF:00:00:11;
  fixed-address 10.11.1.11;
  option host-name "ldap1";
}
host ldap2 {
  hardware ethernet 00:22:FF:00:00:12;
  fixed-address 10.11.1.12;
  option host-name "ldap2";
}
host monitoring {
  hardware ethernet 00:22:FF:00:00:13;
  fixed-address 10.11.1.13;
  option host-name "monitoring";
}
host syslog {
  hardware ethernet 00:22:FF:00:00:14;
  fixed-address 10.11.1.14;
  option host-name "syslog";
}
host storage1 {
  hardware ethernet 00:22:FF:00:00:15;
  fixed-address 10.11.1.15;
  option host-name "storage1";
}
host storage2 {
  hardware ethernet 00:22:FF:00:00:16;
  fixed-address 10.11.1.16;
  option host-name "storage2";
}
host db1 {
  hardware ethernet 00:22:FF:00:00:17;
  fixed-address 10.11.1.17;
  option host-name "db1";
}
host db2 {
  hardware ethernet 00:22:FF:00:00:18;
  fixed-address 10.11.1.18;
  option host-name "db2";
}
host proxy1 {
  hardware ethernet 00:22:FF:00:00:19;
  fixed-address 10.11.1.19;
  option host-name "proxy1";
}
host proxy2 {
  hardware ethernet 00:22:FF:00:00:20;
  fixed-address 10.11.1.20;
  option host-name "proxy2";
}
host web1 {
  hardware ethernet 00:22:FF:00:00:21;
  fixed-address 10.11.1.21;
  option host-name "web1";
}
host web2 {
  hardware ethernet 00:22:FF:00:00:22;
  fixed-address 10.11.1.22;
  option host-name "web2";
}
host backup {
  hardware ethernet 00:22:FF:00:00:23;
  fixed-address 10.11.1.23;
  option host-name "backup";
}

Harden file permissions because of the plaintext rndc-key:

[admin2]# chmod 0600 /etc/dhcp/dhcpd.conf

Restart the service:

[admin2]# systemctl restart dhcpd

10 thoughts on “Configure DHCP Failover with Dynamic DNS on CentOS 7

  1. One thing to note in dhcpd.conf:

    Setting FQDN in (option host-name) while (option domain-name) and (option-domain-name-servers) are set will cause your DNS to create records with duplicate tlds, meaning it will create something like storage1.hl.local.hl.local.

    Just set option host-name to “storage” instead of “storage1.hl.local” and you should be fine.

  2. Hi

    Don’t you need to install foreman proxy on DHCP server? How your katello is communicating with this DHCP server?

    • I don’t, because I use PXE boot with static DHCP leases based on MAC address.

      I provide Katello with a MAC address when provisioning a new VM and DHCP server issues a static lease.

  3. Hi Tomas,

    I really like your tutorial, however, I cannot make it working.
    named.conf
    include “/etc/named.rfc1912.zones”;
    include “/etc/named.root.key”;
    include “/etc/rndc.key”;

    # Allow rndc management
    controls {
    inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { “rndc-key”; };
    };

    # Limit access to local network
    acl “acjo_infra” {
    127.0.0.0/8;
    10.123.116.0/24;
    10.10.72.0/24;
    };

    options {
    listen-on port 53 { 127.0.0.1; 10.123.116.2; }; ## netserv1
    listen-on-v6 { none; };
    directory “/var/named”;
    dump-file “/var/named/data/cache_dump.db”;
    statistics-file “/var/named/data/named_stats.txt”;
    memstatistics-file “/var/named/data/named_mem_stats.txt”;

    tcp-clients 50;

    # Disable built-in server information zones
    version none;
    hostname none;
    server-id none;

    recursion yes;
    recursive-clients 50;
    allow-recursion { acjo_infra; };
    allow-query {
    acjo_infra;
    };
    allow-transfer {
    localhost;
    10.123.116.3;
    };

    auth-nxdomain no;
    notify no;
    dnssec-enable yes;
    dnssec-validation auto;
    #dnssec-lookaside auto;

    bindkeys-file “/etc/named.iscdlv.key”;
    managed-keys-directory “/var/named/dynamic”;
    pid-file “/run/named/named.pid”;
    session-keyfile “/run/named/session.key”;
    };

    # Specifications of what to log, and where the log messages are sent
    logging {
    channel common_log {
    file “/var/log/named/named.log”;
    print-category yes;
    print-severity yes;
    print-time yes;
    };
    category lame-servers {
    null;
    };
    category query-errors {
    common_log;
    };
    category security {
    common_log;
    };
    category client {
    common_log;
    };
    category queries {
    common_log;
    };
    category general {
    common_log;
    };
    category default {
    common_log;
    };
    };

    zone “.” IN {
    type hint;
    file “named.ca”;
    };

    # Internal zone definitions
    zone “acj.net” {
    type master;
    file “data/db.acj.net”;
    allow-update { key rndc-key; };
    notify yes;
    };

    zone “116.123.10.in-addr.arpa” {
    type master;
    file “data/db.116.123.10”;
    allow-update { key rndc-key; };
    notify yes;
    };

    DNS Server DIG – OK
    [root@netserv1 ~]# dig google.com

    ; <> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <> google.com
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<nslookup google.com
    DNS request timed out.
    timeout was 2 seconds.
    Server: UnKnown
    Address: 10.123.116.2

    DNS request timed out.
    timeout was 2 seconds.
    DNS request timed out.
    timeout was 2 seconds.

    Any thoughts will be much appreciated

    • The error message suggests a firewall issue. Are your servers configured to allow inbound/outbound DNS traffic on both TCP and UDP ports?

  4. Thanks, Thomas,
    I just completely disabled the SELinux and, checked the firewall.
    Now it’s working.
    Thanks

    • That’s fine. Try setting SELinux to permissive mode and check the audit log to see if anything gets blocked. You can enable firewall logging to see if any traffic gets blocked.

  5. Great Tomas,
    I really liked this tutorial and you gave me some new ideas for lessons for my students.

    But I have a question for you.
    Doing tests I noticed that if the master primary DDNS is offline, the secondary DDNS correctly supplies the IP addresses trough dhcp service, but for it is not possible to update the primary DDNS server (…is offline.).
    There is a possible configuration that allows the dhcp service on secondary to dynamically update “on board” DNS table with the new entries, and when the primary goes back online, the secondary transfers the modified table with the new entries dhcp?

    Thanks in advance for your help.
    Dario M.

Leave a Reply

Your email address will not be published. Required fields are marked *