Главная страница » Резервный DHCP сервер Linux AD-DC Ubuntu 18.04

Резервный DHCP сервер Linux AD-DC Ubuntu 18.04

by Belfigor
63 views
Резервный DHCP сервер Linux AD-DC Ubuntu 18

Резервный DHCP сервер Linux AD-DC всегда должен быть готов в максимально короткие сроки принять на себя функционал основного DHCP сервера. Для этого резервный DHCP сервер должен быть проинтегрирован с DHCP сервером контроллера домена Linux AD-DC. После интеграции он будет находиться в режиме ожидания. Всегда готовый автоматически принять на себя роль DHCP сервера в случае падения олимпа. А в случае восстановления основного контроллера домена, резервный DHCP сервер вернёт главенствующую роль его DHCP серверу.

Резервный DHCP сервер Linux AD-DC

Настраиваем DHCP сервер

Начинаем конечно же с установки.

sudo apt-get install isc-dhcp-server

Экспортируем данные необходимые для интеграции dhcp и dns сервера

sudo samba-tool domain exportkeytab --principal=dhcpduser@ADMINGUIDE.LAN /etc/dhcpduser.keytab
sudo chown dhcpd:dhcpd  /etc/dhcpduser.keytab
sudo chmod 400  /etc/dhcpduser.keytab

Создаём скрипт ответственный за обновления локальной DNS зона

sudo nano /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=$?
;;
delete)
     _KERBEROS

nsupdate -g ${NSUPDFLAGS} << UPDATE
server 127.0.0.1
realm ${REALM}
update delete ${name}.${domain} 3600 A
send
UPDATE
result1=$?
;;
*)
echo "Invalid action specified"
exit 103
;;
esac

result="${result1}"

if [ "${result}" != "0" ]; then
    logger "DHCP-DNS Update failed: ${result}"
else
    logger "DHCP-DNS Update succeeded"
fi

exit ${result}

Устанавливаем права на скрипт:

sudo chmod 755 /usr/local/bin/dhcp-dyndns.sh

Настраиваем dhcp сервер, предварительно забекапив старый конфиг

sudo cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.original
sudo nano /etc/dhcp/dhcpd.conf

Вставляем следующее содержимое:

authoritative;
ddns-update-style none;
omapi-port 7911;
omapi-key omapi_key;

key omapi_key {
     algorithm hmac-md5;
     secret "ваш_OMAPI_ключ_для_интеграции"; #
}

failover peer "adminguide-dhcp-failover" {
  secondary;
  address ag-dc-2.adminguide.lan; #Полное DNS имя резервного DHCP сервера
  peer address ag-dc-1.adminguide.lan; #Полное DNS имя основного DHCP сервера
  max-response-delay 60;
  max-unacked-updates 10;
  load balance max seconds 3;
}

subnet 192.168.1.0 netmask 255.255.255.0 { #Подсеть и маска на которую будет вещать dhcp сервер
  option subnet-mask 255.255.255.0; #Маска сети
  option broadcast-address 192.168.1.255; #Адрес броадкаста
  option time-offset 0;
  option routers 192.168.1.1; #Шлюз
  option domain-name "adminguide.lan"; #Имя домена
  option domain-name-servers 192.168.1.101, 192.168.1.100; #ДНС сервера
  option netbios-name-servers 192.168.1.101, 192.168.1.100; #NetBIOS сервера
  option ntp-servers 192.168.1.101, 192.168.1.100; #NTP сервера
  pool { #Пулл адресов
    failover peer "adminguide-dhcp-failover";
    max-lease-time 1800; # Максимальное время аренды в секундах
    range 192.168.1.110 192.168.1.199; #Диапазон адресов
  }
}

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("adminguide.ru 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, ClientName);
}

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");
}


Настройка ag-dc-1.adminguide.lan

Теперь переходим к текущему владельцу FSMO ролей, серверу ag-dc-1

Открываем конфиг dhcpd

sudo nano /etc/dhcp/dhcpd.conf

Вставляем следующее содержимое:

authoritative;
ddns-update-style none;
omapi-port 7911;
omapi-key omapi_key;

key omapi_key {
     algorithm hmac-md5;
     secret "ваш_OMAPI_код_для_интеграции";
}

failover peer "adminguide-dhcp-failover" {
  primary;
  address ag-dc-1.adminguide.lan; #FQDN мастера (текущего сервера)
  peer address ag-dc-2.adminguide.lan; #FQDN резервного DHCP сервера
  max-response-delay 60;
  max-unacked-updates 10;
  mclt 3600;
  split 255;
  load balance max seconds 3;
}
subnet 192.168.1.0 netmask 255.255.255.0 { #Подсеть и маска на которую будет вещать dhcp сервер
  option subnet-mask 255.255.255.0;
  option broadcast-address 192.168.1.255;
  option time-offset 0;
  option routers 192.168.1.1; #Шлюз
  option domain-name "adminguide.lan"; #Имя домена
  option domain-name-servers 192.168.1.100, 192.168.1.101; #ДНС сервера
  option netbios-name-servers 192.168.1.100, 192.168.1.101; #NetBIOS сервера
  option ntp-servers 192.168.1.100, 192.168.1.101; #NTP сервера
  pool { #Пулл адресов
    failover peer "adminguide-dhcp-failover";
    max-lease-time 1800; # Максимальное время аренды в секундах
    range 192.168.1.110 192.168.1.199; #Диапазон адресов
  }
}

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("adminguide.ru 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, ClientName);
}

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");
}

Генерируем на ag-dc-1 случайный OMAPI ключ и отображаем его с помощью команды

sudo dnssec-keygen -a HMAC-MD5 -b 512 -n USER DHCP_OMAPI
sudo cat Kdhcp_omapi.+*.private |grep ^Key|cut -d ' ' -f2-

У меня ключ следующий:

08bfJKl4Sg++xTfRnDlTbCT9PhxOAf9QSyULgppI77Hv2Wc8iD4tvl4NU8BZhPU62WjQNVt08VBhEpeZa+0Mvw==

Его то мне и нужно подставить dhcpd.conf в блок key, чтобы в конфигах обоих серверов получилось вот так:

key omapi_key {
     algorithm hmac-md5;
     secret "08bfJKl4Sg++xTfRnDlTbCT9PhxOAf9QSyULgppI77Hv2Wc8iD4tvl4NU8BZhPU62WjQNVt08VBhEpeZa+0Mvw==";
}


Перезапускаем DHCP сервер на обоих серверах:

sudo service isc-dhcp-server stop && sudo service isc-dhcp-server start

Если всё сделано правильно, то за считанные секунды DHCP сервера придут к соответствию. DHCP сервер ag-dc-1 передаст на DHCP сервер ag-dc-2 всю имеющуюся у себя инфу по лизам и в сислогах обоих контроллеров доменов появится следующая строчка:

Jan  1 21:09:38 ag-dc-1 dhcpd[5071]: failover peer adminguide-dhcp-failover: Both servers normal

Пришла пора к донастройке DHCP сервера ag-dc-2. А именно к дообучению его аппармора (в случае если он у вас не отключен)

Резервный DHCP сервер Linux AD-DC – Проверяем

Выключаем ISC-DHCP на ag-dc-1 командой

sudo service isc-dhcp-server stop

В сислоге на ag-dc-2 вы увидите:

Jan  1 21:14:28 ag-dc-2 dhcpd[25150]: peer adminguide-dhcp-failover: disconnected
Jan  1 21:14:28 ag-dc-2 dhcpd[25150]: failover peer adminguide-dhcp-failover: I move from normal to communications-interrupted

И очень вскоре ISC-DHCP на ag-dc-2 начнёт переобуваться и приступать к выполнению роли основного DHCP сервера сети. Если не начнёт пишите, будем разбираться. Но в процессе ему в этом активно будет мешать apparmor. Потому нам необходимо дообучить apparmor, чтобы он перестал блокировать попытки обновить новым DHCP сервером локальную ДНС зону домена.

Наиболее простой способ это утилита aa-logprof и любой dhcp клиент имеющийся в сети и не являющийся членом домена. У меня для подобных тестов есть отдельная линуксовая машина. Если утилита aa-logprof не стоит, она входит в комплект утилит apparmor-utils. Потому установим весь комплект командой

sudo apt install apparmor-utils

На ag-dc-2 я запускаю aa-logprof

sudo aa-logprof

Если я вижу что-то кроме

Reading log entries from /var/log/syslog.
Updating AppArmor profiles in /etc/apparmor.d.
Enforce-mode changes:

Я всячески соглашаюсь с тем что запрашивает apparmor, нажимая (A)llow, (I)nherit, (S)ave Changes

Потом иду на линуксовую машину, сбрасываю текущий полученный от DHCP сервера адрес, и запрашиваю новый с помощью команды:

sudo dhclient -r && sudo dhclient

Ииии снова запускаю sudo aa-logprof на ag-dc-2. Занимаюсь я этим до тех пор, пока aa-logprof не выведет мне долгожданные 3 строки и ничего более:

Reading log entries from /var/log/syslog.
Updating AppArmor profiles in /etc/apparmor.d.
Enforce-mode changes:

После того как apparmor перестал реагировать на перезапрос клиентом информации у DHCP сервера, вы увидите в сислоге привычную картину валидно работающего автообновления DNS зоны.

Теперь обратно включаем isc-dhcp сервер на ag-dc-1. Для этого используем команду:

sudo service isc-dhcp-server start

Если сразу глянуть сислог на ag-dc-2 вы увидите

Jan  2 11:46:10 ag-dc-2 dhcpd[8344]: failover peer adminguide-dhcp-failover: I move from communications-interrupted to normal

dhcp сервер резервного контроллера домена начал разоружаться.

Подождав несколько секунд, и снова дёрнув dhcp клиент, вы увидите что ag-dc-2 – видит запросы, но не реагирует на них.

Jan  2 11:50:49 ag-dc-2 dhcpd[8344]: DHCPDISCOVER from 00:0c:29:20:ce:dc via ens160: load balance to peer adminguide-dhcp-failover
Jan  2 11:50:49 ag-dc-2 dhcpd[8344]: DHCPDISCOVER from 00:0c:29:20:ce:d2 via ens160: load balance to peer adminguide-dhcp-failover
Jan  2 11:50:50 ag-dc-2 dhcpd[8344]: DHCPREQUEST for 192.168.1.111 (192.168.1.100) from 00:0c:29:20:ce:dc via ens160: lease owned by peer
Jan  2 11:50:50 ag-dc-2 dhcpd[8344]: DHCPREQUEST for 192.168.1.112 (192.168.1.100) from 00:0c:29:20:ce:d2 via ens160: lease owned by peer

В то время как ag-dc-1 полноценно отрабатывает каждую полученную запись.

Заключение

Собственно на этом данная серия статей объявляется завершённой. Далее будут только правки и уточнения. Так же возможны небольшие статьи дополнения. Потому следите за обновлениями :). Освещение последующих вопросов, таких как кроссплатформенная интеграция контроллеров домена, всевозможные миграции и многое другое вы сможете прочитать в будущем (конец 2021 – начало 2022 года). Подписывайтесь чтобы быть в курсе событий :).

Ещё больше интересного контента в моём блоге в Zen и на моём канале YouTube. Особенно если вас интересуют видеоуроки. Подписывайтесь на каналы, ставьте лайки, делайте репосты, это поможет развитию контента проекта AdminGuide.Ru

Text.ru - 100.00%

You may also like

Leave a Comment