Configure DHCP to update DNS records: Difference between revisions
m (/* minor update re the user and group 'dhcpd' runs as) |
m (/* updated dhcpd.conf) |
||
(9 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
This HowTo describes how to configure isc DHCP to update a Samba DC BIND DNS backend. See [[Setting_up_a_BIND_DNS_Server]] for how to set up Bind. |
This HowTo describes how to configure isc DHCP to update a Samba DC BIND DNS backend. See [[Setting_up_a_BIND_DNS_Server]] for how to set up Bind. |
||
It has not been tested with the Samba |
It has not been tested with the Samba AD internal DNS server and it probably will not work with the Samba AD internal DNS. |
||
This HowTo is based on a Debian OS install, the paths given may be different if you use another OS. |
|||
Line 11: | Line 11: | ||
= Preconditions = |
= Preconditions = |
||
* The computer has been provisioned as an AD DC and the samba, smbd and winbindd daemons are running. |
|||
* Bind9 is installed and working with the Samba 4 DC, tested with various 9.x versions |
|||
* Bind9_dlz is installed and working on the Samba AD DC, tested with various 9.x versions. |
|||
* you are logged into the DC as 'root' |
|||
* You have created the reverse zone. |
|||
* You are logged into the DC as 'root' |
|||
* You are doing this on the same DC as Bind9 is installed on |
|||
Line 53: | Line 59: | ||
Now export the required keytab. |
Now export the required keytab. |
||
# samba-tool domain exportkeytab --principal=dhcpduser@SAMDOM.EXAMPLE.COM /etc |
# samba-tool domain exportkeytab --principal=dhcpduser@SAMDOM.EXAMPLE.COM /etc/dhcpduser.keytab |
||
# chown root:root /etc |
# chown root:root /etc/dhcpduser.keytab |
||
# chmod 400 /etc |
# chmod 400 /etc/dhcpduser.keytab |
||
{{Imbox |
{{Imbox |
||
| type = note |
| type = note |
||
Line 64: | Line 70: | ||
= Create the script for the updates = |
= Create the script for the updates = |
||
Copy this script to /usr/local/bin/dhcp-dyndns.sh |
|||
First make a directory to store the script in. |
|||
# mkdir -p /etc/dhcp/bin |
|||
Next, copy this script to /etc/dhcp/bin/dhcp-dyndns.sh |
|||
#!/bin/bash |
#!/bin/bash |
||
# / |
# /usr/local/bin/dhcp-dyndns.sh |
||
# This script is for secure DDNS updates on Samba 4 |
# This script is for secure DDNS updates on Samba 4 |
||
# Version: 0.8. |
# Version: 0.8.9 |
||
# Uncomment the next line if using a self compiled Samba and adjust for your PREFIX |
|||
#PATH="/usr/local/samba/bin:/usr/local/samba/sbin:$PATH" |
|||
BINDIR=$(samba -b | grep 'BINDIR' | grep -v 'SBINDIR' | awk '{print $NF}') |
|||
WBINFO="$BINDIR/wbinfo" |
|||
# DNS domain |
# DNS domain |
||
domain=$(hostname -d) |
domain=$(hostname -d) |
||
if [ -z ${domain} ]; then |
if [ -z ${domain} ]; then |
||
echo "Cannot obtain domain name, is DNS set up correctly?" |
|||
echo "Cannot continue... Exiting." |
|||
logger "Cannot obtain domain name, is DNS set up correctly?" |
logger "Cannot obtain domain name, is DNS set up correctly?" |
||
logger "Cannot continue... Exiting." |
logger "Cannot continue... Exiting." |
||
Line 91: | Line 96: | ||
# Additional nsupdate flags (-g already applied), e.g. "-d" for debug |
# Additional nsupdate flags (-g already applied), e.g. "-d" for debug |
||
NSUPDFLAGS="-d" |
|||
# krbcc ticket cache |
# krbcc ticket cache |
||
Line 102: | Line 107: | ||
# krbcc ticket cache |
# krbcc ticket cache |
||
# /tmp/dhcp-dyndns.cc |
# /tmp/dhcp-dyndns.cc |
||
TESTUSER="$($WBINFO -u) | grep 'dhcpduser')" |
|||
TESTUSER=$(wbinfo -u | grep dhcpduser) |
|||
if [ -z "${TESTUSER}" ]; then |
if [ -z "${TESTUSER}" ]; then |
||
logger "No AD dhcp user exists, need to create it first.. exiting." |
|||
logger "you can do this by typing the following commands" |
|||
logger "kinit Administrator@${REALM}" |
|||
logger "samba-tool user create dhcpduser --random-password --description=\"Unprivileged user for DNS updates via ISC DHCP server\"" |
|||
logger "samba-tool user setexpiry dhcpduser --noexpiry" |
|||
logger "samba-tool group addmembers DnsAdmins dhcpduser" |
|||
exit 1 |
exit 1 |
||
fi |
fi |
||
# Check for Kerberos keytab |
# Check for Kerberos keytab |
||
if [ ! -f /etc |
if [ ! -f /etc/dhcpduser.keytab ]; then |
||
echo "Required keytab /etc/dhcpduser.keytab not found, it needs to be created." |
echo "Required keytab /etc/dhcpduser.keytab not found, it needs to be created." |
||
echo "Use the following commands as root" |
echo "Use the following commands as root" |
||
Line 134: | Line 138: | ||
{ |
{ |
||
echo "USAGE:" |
echo "USAGE:" |
||
echo " |
echo " $(basename $0) add ip-address dhcid|mac-address hostname" |
||
echo " |
echo " $(basename $0) delete ip-address dhcid|mac-address" |
||
} |
} |
||
Line 150: | Line 154: | ||
if [ "$?" != "0" ]; then |
if [ "$?" != "0" ]; then |
||
logger "${test} [dyndns] : Getting new ticket, old one has expired" |
logger "${test} [dyndns] : Getting new ticket, old one has expired" |
||
kinit -F -k -t /etc |
kinit -F -k -t /etc/dhcpduser.keytab -c /tmp/dhcp-dyndns.cc "${SETPRINCIPAL}" |
||
if [ "$?" != "0" ]; then |
if [ "$?" != "0" ]; then |
||
logger "${test} [dyndns] : dhcpd kinit for dynamic DNS failed" |
logger "${test} [dyndns] : dhcpd kinit for dynamic DNS failed" |
||
Line 179: | Line 183: | ||
## nsupdate ## |
## nsupdate ## |
||
case "${action}" in |
case "${action}" in |
||
add) |
add) |
||
Line 212: | Line 215: | ||
UPDATE |
UPDATE |
||
result1=$? |
result1=$? |
||
nsupdate -g ${NSUPDFLAGS} << UPDATE |
nsupdate -g ${NSUPDFLAGS} << UPDATE |
||
server 127.0.0.1 |
server 127.0.0.1 |
||
Line 240: | Line 244: | ||
Set the permissions on the script. |
Set the permissions on the script. |
||
# chmod 755 / |
# chmod 755 /usr/local/bin/dhcp-dyndns.sh |
||
It has been reported that on raspbian stretch, you have to specify the zone in the reverse update command, if you find that you have problems updating the reverse zone, you can make the following changes to the script above. |
|||
Find these lines: |
|||
# Set PTR address and its reverse lookup zone |
|||
ptr=$(echo ${ip} | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}') |
|||
and add this line immediately after them: |
|||
rzone=$(echo ${ip} | awk -F '.' '{print $3"."$2"."$1".in-addr.arpa"}') |
|||
Now, in the 'add)' section of the '## nsupdate ##' command, change this: |
|||
nsupdate -g ${NSUPDFLAGS} << UPDATE |
|||
server 127.0.0.1 |
|||
realm ${REALM} |
|||
update delete ${ptr} 3600 PTR |
|||
update add ${ptr} 3600 PTR ${name}.${domain} |
|||
send |
|||
UPDATE |
|||
result2=$? |
|||
;; |
|||
To this: |
|||
nsupdate -g ${NSUPDFLAGS} << UPDATE |
|||
server 127.0.0.1 |
|||
realm ${REALM} |
|||
zone ${rzone} |
|||
update delete ${ptr} 3600 PTR |
|||
update add ${ptr} 3600 PTR ${name}.${domain} |
|||
send |
|||
UPDATE |
|||
result2=$? |
|||
;; |
|||
Line 273: | Line 312: | ||
set noname = concat("dhcp-", binary-to-ascii(10, 8, "-", leased-address)); |
set noname = concat("dhcp-", binary-to-ascii(10, 8, "-", leased-address)); |
||
set ClientIP = binary-to-ascii(10, 8, ".", leased-address); |
set ClientIP = binary-to-ascii(10, 8, ".", leased-address); |
||
set ClientDHCID = |
set ClientDHCID = concat ( |
||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2) |
|||
); |
|||
set ClientName = pick-first-value(option host-name, config-option-host-name, client-name, noname); |
set ClientName = pick-first-value(option host-name, config-option-host-name, client-name, noname); |
||
log(concat("Commit: IP: ", ClientIP, " DHCID: ", ClientDHCID, " Name: ", ClientName)); |
log(concat("Commit: IP: ", ClientIP, " DHCID: ", ClientDHCID, " Name: ", ClientName)); |
||
execute("/ |
execute("/usr/local/bin/dhcp-dyndns.sh", "add", ClientIP, ClientDHCID, ClientName); |
||
} |
} |
||
on release { |
on release { |
||
set ClientIP = binary-to-ascii(10, 8, ".", leased-address); |
set ClientIP = binary-to-ascii(10, 8, ".", leased-address); |
||
set ClientDHCID = |
set ClientDHCID = concat ( |
||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":", |
|||
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2) |
|||
); |
|||
log(concat("Release: IP: ", ClientIP)); |
log(concat("Release: IP: ", ClientIP)); |
||
execute("/ |
execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, ClientDHCID); |
||
} |
} |
||
Line 291: | Line 344: | ||
log(concat("Expired: IP: ", ClientIP)); |
log(concat("Expired: IP: ", ClientIP)); |
||
# cannot get a ClientName here, for some reason that always fails |
# cannot get a ClientName here, for some reason that always fails |
||
execute("/ |
execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, "", "0"); |
||
} |
} |
||
Start the dhcp server and see what happens |
Start the dhcp server and see what happens. |
||
: {{Imbox |
|||
| type = important |
|||
| text = You must stop your windows clients from trying to update their own records, as this will fail and fill your logs with errors. |
|||
}} |
|||
Line 389: | Line 448: | ||
For more information, read the dhcpd.conf manpage <code>man dhcpd.conf</code>. |
For more information, read the dhcpd.conf manpage <code>man dhcpd.conf</code>. |
||
Any questions or problems, ask on the Samba mailing list. |
|||
= Apparmor = |
|||
To get DHCP updates working with Apparmor, you need to alter /etc/apparmor.d/usr.sbin.dhcpd to match this. |
|||
/etc/dhcp/ r, |
|||
/etc/dhcp/** r, |
|||
/etc/dhcpd{,6}.conf r, |
|||
/etc/dhcpd{,6}_ldap.conf r, |
|||
/usr/local/bin/dhcp-dyndns.sh ix, |
|||
/bin/grep rix, |
|||
/usr/sbin/samba rix, |
|||
/usr/bin/gawk rix, |
|||
/bin/hostname rix, |
|||
/usr/bin/wbinfo rix, |
|||
/usr/bin/heimtools rix, |
|||
/usr/bin/logger rix, |
|||
/usr/bin/kinit.heimdal rix, |
|||
/bin/date rix, |
|||
/dev/tty wr, |
|||
/dev/urandom w, |
|||
/proc/** r, |
|||
/usr/bin/kinit w, |
|||
/run/samba/winbindd/pipe wr, |
|||
The first 4 lines are the default, you will need to add everything else. |
|||
With these settings the dhcp-server will start and work. |
|||
The above settings have been tested on Ubuntu 18.04 and were supplied by Stefan Kania. |
|||
Any questions or problems, ask on the Samba mailing list. |
|||
Revision as of 14:57, 20 March 2019
Introduction
This HowTo describes how to configure isc DHCP to update a Samba DC BIND DNS backend. See Setting_up_a_BIND_DNS_Server for how to set up Bind.
It has not been tested with the Samba AD internal DNS server and it probably will not work with the Samba AD internal DNS.
This HowTo is based on a Debian OS install, the paths given may be different if you use another OS.
Preconditions
- The computer has been provisioned as an AD DC and the samba, smbd and winbindd daemons are running.
- Bind9_dlz is installed and working on the Samba AD DC, tested with various 9.x versions.
- You have created the reverse zone.
- You are logged into the DC as 'root'
- You are doing this on the same DC as Bind9 is installed on
Names and Addresses used in this howto
- Realm : SAMDOM.EXAMPLE.COM
- Subnet : 192.168.0.0
- Netmask : 255.255.255.0
- Subnet-mask : 255.255.255.0
- Broadcast-address : 192.168.0.255
- Gateway : 192.168.0.1
- Domain-name : samdom.example.com
- Domain-name-servers : 192.168.0.6, 192.168.0.5
- Netbios-name-servers : 192.168.0.5, 192.168.0.6
- Ntp-servers : 192.168.0.5, 192.168.0.6;
- Pool range : 192.168.0.50 192.168.0.229
Install isc DHCP
First install the DHCP server
# apt-get install isc-dhcp-server
Create a user to carry out the updates
You need a user that the script will run as, set a random password because you will never logon as the user.
# samba-tool user create dhcpduser --description="Unprivileged user for TSIG-GSSAPI DNS updates via ISC DHCP server" --random-password
Now set the users password to never expire and add the user to the DnsAdmins group.
# samba-tool user setexpiry dhcpduser --noexpiry # samba-tool group addmembers DnsAdmins dhcpduser
Now export the required keytab.
# samba-tool domain exportkeytab --principal=dhcpduser@SAMDOM.EXAMPLE.COM /etc/dhcpduser.keytab # chown root:root /etc/dhcpduser.keytab # chmod 400 /etc/dhcpduser.keytab
In the chown command above root:root is used, you need to check what user & group DHCP runs as on your distro and if different, change root:root to the correct user & group. |
Create the script for the updates
Copy this script to /usr/local/bin/dhcp-dyndns.sh
#!/bin/bash # /usr/local/bin/dhcp-dyndns.sh # This script is for secure DDNS updates on Samba 4 # Version: 0.8.9 # Uncomment the next line if using a self compiled Samba and adjust for your PREFIX #PATH="/usr/local/samba/bin:/usr/local/samba/sbin:$PATH" BINDIR=$(samba -b | grep 'BINDIR' | grep -v 'SBINDIR' | awk '{print $NF}') WBINFO="$BINDIR/wbinfo" # DNS domain domain=$(hostname -d) if [ -z ${domain} ]; then logger "Cannot obtain domain name, is DNS set up correctly?" logger "Cannot continue... Exiting." exit 1 fi # Samba 4 realm REALM=$(echo ${domain^^}) # Additional nsupdate flags (-g already applied), e.g. "-d" for debug NSUPDFLAGS="-d" # krbcc ticket cache export KRB5CCNAME="/tmp/dhcp-dyndns.cc" # Kerberos principal SETPRINCIPAL="dhcpduser@${REALM}" # Kerberos keytab # /etc/dhcpduser.keytab # krbcc ticket cache # /tmp/dhcp-dyndns.cc TESTUSER="$($WBINFO -u) | grep 'dhcpduser')" if [ -z "${TESTUSER}" ]; then logger "No AD dhcp user exists, need to create it first.. exiting." logger "you can do this by typing the following commands" logger "kinit Administrator@${REALM}" logger "samba-tool user create dhcpduser --random-password --description=\"Unprivileged user for DNS updates via ISC DHCP server\"" logger "samba-tool user setexpiry dhcpduser --noexpiry" logger "samba-tool group addmembers DnsAdmins dhcpduser" exit 1 fi # Check for Kerberos keytab if [ ! -f /etc/dhcpduser.keytab ]; then echo "Required keytab /etc/dhcpduser.keytab not found, it needs to be created." echo "Use the following commands as root" echo "samba-tool domain exportkeytab --principal=${SETPRINCIPAL} /etc/dhcpduser.keytab" echo "chown XXXX:XXXX /etc/dhcpduser.keytab" echo "Replace 'XXXX:XXXX' with the user & group that dhcpd runs as on your distro" echo "chmod 400 /etc/dhcpduser.keytab" exit 1 fi # Variables supplied by dhcpd.conf action=$1 ip=$2 DHCID=$3 name=${4%%.*} usage() { echo "USAGE:" echo " $(basename $0) add ip-address dhcid|mac-address hostname" echo " $(basename $0) delete ip-address dhcid|mac-address" } _KERBEROS () { # get current time as a number test=$(date +%d'-'%m'-'%y' '%H':'%M':'%S) # Note: there have been problems with this # check that 'date' returns something like # 04-09-15 09:38:14 # Check for valid kerberos ticket #logger "${test} [dyndns] : Running check for valid kerberos ticket" klist -c /tmp/dhcp-dyndns.cc -s if [ "$?" != "0" ]; then logger "${test} [dyndns] : Getting new ticket, old one has expired" kinit -F -k -t /etc/dhcpduser.keytab -c /tmp/dhcp-dyndns.cc "${SETPRINCIPAL}" if [ "$?" != "0" ]; then logger "${test} [dyndns] : dhcpd kinit for dynamic DNS failed" exit 1; fi fi } # Exit if no ip address or mac-address if [ -z "${ip}" ] || [ -z "${DHCID}" ]; then usage exit 1 fi # Exit if no computer name supplied, unless the action is 'delete' if [ "${name}" = "" ]; then if [ "${action}" = "delete" ]; then name=$(host -t PTR "${ip}" | awk '{print $NF}' | awk -F '.' '{print $1}') else usage exit 1; fi fi # Set PTR address ptr=$(echo ${ip} | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}') ## nsupdate ## case "${action}" in add) _KERBEROS nsupdate -g ${NSUPDFLAGS} << UPDATE server 127.0.0.1 realm ${REALM} update delete ${name}.${domain} 3600 A update add ${name}.${domain} 3600 A ${ip} send UPDATE result1=$? nsupdate -g ${NSUPDFLAGS} << UPDATE server 127.0.0.1 realm ${REALM} update delete ${ptr} 3600 PTR update add ${ptr} 3600 PTR ${name}.${domain} send UPDATE result2=$? ;; delete) _KERBEROS nsupdate -g ${NSUPDFLAGS} << UPDATE server 127.0.0.1 realm ${REALM} update delete ${name}.${domain} 3600 A send UPDATE result1=$? nsupdate -g ${NSUPDFLAGS} << UPDATE server 127.0.0.1 realm ${REALM} update delete ${ptr} 3600 PTR send UPDATE result2=$? ;; *) echo "Invalid action specified" exit 103 ;; esac result="${result1}${result2}" if [ "${result}" != "00" ]; then logger "DHCP-DNS Update failed: ${result}" else logger "DHCP-DNS Update succeeded" fi exit ${result}
Set the permissions on the script.
# chmod 755 /usr/local/bin/dhcp-dyndns.sh
It has been reported that on raspbian stretch, you have to specify the zone in the reverse update command, if you find that you have problems updating the reverse zone, you can make the following changes to the script above.
Find these lines:
# Set PTR address and its reverse lookup zone ptr=$(echo ${ip} | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}')
and add this line immediately after them:
rzone=$(echo ${ip} | awk -F '.' '{print $3"."$2"."$1".in-addr.arpa"}')
Now, in the 'add)' section of the '## nsupdate ##' command, change this:
nsupdate -g ${NSUPDFLAGS} << UPDATE server 127.0.0.1 realm ${REALM} update delete ${ptr} 3600 PTR update add ${ptr} 3600 PTR ${name}.${domain} send UPDATE result2=$? ;;
To this:
nsupdate -g ${NSUPDFLAGS} << UPDATE server 127.0.0.1 realm ${REALM} zone ${rzone} update delete ${ptr} 3600 PTR update add ${ptr} 3600 PTR ${name}.${domain} send UPDATE result2=$? ;;
Modify the dhcp conf file
First backup the original conf file.
# cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.orig
Now edit /etc/dhcp/dhcpd.conf and make it look similar to the this.
authoritative; ddns-update-style none; subnet 192.168.0.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 192.168.0.255; option time-offset 0; option routers 192.168.0.1; option domain-name "samdom.example.com"; option domain-name-servers 192.168.0.6, 192.168.0.5; option netbios-name-servers 192.168.0.5, 192.168.0.6; option ntp-servers 192.168.0.5, 192.168.0.6; pool { max-lease-time 1800; # 30 minutes range 192.168.0.50 192.168.0.229; } } on commit { set noname = concat("dhcp-", binary-to-ascii(10, 8, "-", leased-address)); set ClientIP = binary-to-ascii(10, 8, ".", leased-address); set ClientDHCID = concat ( suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2) ); set ClientName = pick-first-value(option host-name, config-option-host-name, client-name, noname); log(concat("Commit: IP: ", ClientIP, " DHCID: ", ClientDHCID, " Name: ", ClientName)); execute("/usr/local/bin/dhcp-dyndns.sh", "add", ClientIP, ClientDHCID, ClientName); } on release { set ClientIP = binary-to-ascii(10, 8, ".", leased-address); set ClientDHCID = concat ( suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2) ); log(concat("Release: IP: ", ClientIP)); execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, ClientDHCID); } on expiry { set ClientIP = binary-to-ascii(10, 8, ".", leased-address); # cannot get a ClientMac here, apparently this only works when actually receiving a packet log(concat("Expired: IP: ", ClientIP)); # cannot get a ClientName here, for some reason that always fails execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, "", "0"); }
Start the dhcp server and see what happens.
You must stop your windows clients from trying to update their own records, as this will fail and fill your logs with errors.
Add failover
Add the following to the /etc/dhcp/dhcpd.conf file on the primary:
failover peer "dhcp-failover" { primary; address dc1.samdom.example.com; peer address dc2.samdom.example.com; max-response-delay 60; max-unacked-updates 10; mclt 3600; split 128; load balance max seconds 3; }
..and secondary:
failover peer "dhcp-failover" { secondary; address dc2.samdom.example.com; peer address dc1.samdom.example.com; max-response-delay 60; max-unacked-updates 10; load balance max seconds 3; }
Make sure that you add the failover section, above the 'subnet' section.
Add references for the subnet/pool which will do failover.
subnet 192.168.0.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 192.168.0.255; option time-offset 0; option routers 192.168.0.1; option domain-name "samdom.example.com"; option domain-name-servers 192.168.0.5, 192.168.0.6; option ntp-servers 192.168.0.5, 192.168.0.6; pool { failover peer "dhcp-failover"; max-lease-time 1800; # 30 minutes range 192.168.0.50 192.168.0.229; } }
Configure OMAPI and define a secret key.
Generate a random OMAPI key on the primary, using the dnssec-keygen utility distributed with BIND.
dnssec‐keygen ‐a HMAC‐MD5 ‐b 512 ‐n USER DHCP_OMAPI
Now extract the actual key:
cat Kdhcp_omapi.+*.private |grep ^Key|cut -d ' ' -f2-
Add the following to dhcpd.conf on both primary and secondary.
omapi-port 7911; omapi-key omapi_key; key omapi_key { algorithm hmac-md5; secret "PUT_YOUR_KEY_HERE"; }
Replace PUT_YOUR_KEY_HERE with the key you extracted from the private key created by the dnssec command
Restart both servers to apply the configuration changes.
You should find lines similar to these, in the system logs on both machines:
Feb 28 17:34:39 dc1 dhcpd: failover peer dhcp-failover: peer moves from recover-done to normal Feb 28 17:34:39 dc1 dhcpd: failover peer dhcp-failover: Both servers normal
If OMAPI is working properly you can test failover by stopping the primary server.
If you are using a firewall, you will need to open TCP ports 647 and 7911
Once you are sure everything is working as expected, restart both servers to ensure everything is running correctly.
The 'split' value '128' on the 'primary', divides responsibility for the clients between the two failover partners. If you want the primary to answer all dhcp requests unless it is down (for whatever reason) set the value to '255', use '0' to make the secondary responsible.
For more information, read the dhcpd.conf manpage man dhcpd.conf
.
Apparmor
To get DHCP updates working with Apparmor, you need to alter /etc/apparmor.d/usr.sbin.dhcpd to match this.
/etc/dhcp/ r, /etc/dhcp/** r, /etc/dhcpd{,6}.conf r, /etc/dhcpd{,6}_ldap.conf r, /usr/local/bin/dhcp-dyndns.sh ix, /bin/grep rix, /usr/sbin/samba rix, /usr/bin/gawk rix, /bin/hostname rix, /usr/bin/wbinfo rix, /usr/bin/heimtools rix, /usr/bin/logger rix, /usr/bin/kinit.heimdal rix, /bin/date rix, /dev/tty wr, /dev/urandom w, /proc/** r, /usr/bin/kinit w, /run/samba/winbindd/pipe wr,
The first 4 lines are the default, you will need to add everything else. With these settings the dhcp-server will start and work.
The above settings have been tested on Ubuntu 18.04 and were supplied by Stefan Kania.
Any questions or problems, ask on the Samba mailing list.