Главная страница » DHCP сервер для Linux AD-DC Ubuntu 18.04. Интеграция с BIND9

DHCP сервер для Linux AD-DC Ubuntu 18.04. Интеграция с BIND9

by Belfigor
634 views
post_logo_ru DHCP сервер для Linux AD-DC Ubuntu 18.04. Интеграция с BIND9

DHCP сервер для Linux AD-DC Ubuntu 18.04. Интеграция с BIND9. Вишенка на торте. Это классно когда у нас есть работающий Active Directory Domain Controller на Linux, но этого мало. Жизнь в мире, где в нашей локальной DNS зоне автоматически обновляются только IP адреса устройств непосредственно состоящих в домене не так радужна как могла бы быть. Решить это проблему мы и попробуем в этой статье. Заранее нужно обозначить что наше решение не будет обновлять обратную зону (PTR записи).

  1. Контроллер домена Ubuntu – Настройка DHCP сервера

    1. Для начала устанавливаем DHCP сервер
      sudo apt-get install isc-dhcp-server

       

    2. Затем создаём пользователя домена для работы с обновлениями
      sudo samba-tool user create dhcpduser --description="Unprivileged user for TSIG-GSSAPI DNS updates via ISC DHCP server" --random-password

       

    3. Так же устанавливаем истечение пароля и добавляем в группу DnsAdmins
      sudo samba-tool user setexpiry dhcpduser --noexpiry
      sudo samba-tool group addmembers DnsAdmins dhcpduser
      AdminGuide.Ru@ag-dc-1:~$ sudo samba-tool user setexpiry dhcpduser --noexpiry
      Expiry for user 'dhcpduser' disabled.
      AdminGuide.Ru@ag-dc-1:~$ sudo samba-tool group addmembers DnsAdmins dhcpduser
      Added members to group DnsAdmins

       

    4. Теперь экспортируем данные
      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

       

    5. Создаём скрипт
      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
    6. Модифицируем файл с настройками
      Создаём бекап и модифицируем конфиг

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

      Заменив содержимое на следующее:

      authoritative;
      ddns-update-style none;
      
      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; #ДНС сервера
        option netbios-name-servers 192.168.1.100; #NetBIOS сервера
        option ntp-servers 192.168.1.100; #NTP сервера
        pool { #Пулл адресов
          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");
      }

       

    7. Редактируем права на запуск
      sudo nano /etc/apparmor.d/usr.sbin.dhcpd

      Добавляем в конец файла перед закрывающей скобкой }

      /usr/local/bin/dhcp-dyndns.sh rix,
      /dev/tty wr,
      /usr/sbin/samba rix,
      /usr/bin/gawk rix,
      /usr/bin/grep rix,
      /usr/bin/hostname rix,
      /usr/bin/logger rix,
      /usr/bin/wbinfo rix,
      /usr/bin/date rix,
      /usr/bin/klist rix,
      /usr/bin/host rix,
      /proc/** wr,
      /usr/bin/kinit rix,
      /etc/dhcpduser.keytab rk,
      /run/samba/winbindd/pipe wr,
      /etc/dhcpduser.keytab rk,
      /tmp/* wrk,
      /usr/bin/nsupdate rix,

      Рестарт AppArmor

      sudo /etc/init.d/apparmor stop && sudo /etc/init.d/apparmor start

      Рестарт DHCP сервера

      sudo service isc-dhcp-server stop && sudo service isc-dhcp-server start
    8. DHCP сервер для Linux AD-DC – Проверяем работу DHCP

      В сети с ad-dc-1 у меня есть еще 1 ubuntu server с именем client-lin-1. Он не в домене, он не настраивался, он просто есть и он получает сетевые настройки по dhcp.
      Пытаюсь пингануть этот клиент по имени, результат нулевой.
      Включаю этот сервер, жду пока загрузится. После того как сервер загрузился, пытаюсь снова, пинг идёт.
      Команды ping client-lin-1 и ping client-lin-1.adminguide.lan теперь будут успешно пинговать эту машину по имени. Как и другие ваши устройства не находящиеся в домене и получающие адреса по DHCP от контроллера домена.
      Освобождаю и повторно запрашиваю IP адрес выполняя на клиенте команду:

      sudo dhclient -r && sudo dhclient

      Смотрю логи командой

      tail -n 250 /var/log/syslog

      Вижу ответ похожий на:

      Aug 30 16:56:23 ag-dc-1 dhcpd[10880]: Release: IP: 192.168.1.114
      Aug 30 16:56:23 ag-dc-1 dhcpd[10880]: execute_statement argv[0] = /usr/local/bin/dhcp-dyndns.sh
      Aug 30 16:56:23 ag-dc-1 dhcpd[10880]: execute_statement argv[1] = delete
      Aug 30 16:56:23 ag-dc-1 dhcpd[10880]: execute_statement argv[2] = 192.168.1.114
      Aug 30 16:56:23 ag-dc-1 dhcpd[10880]: execute_statement argv[3] = 00:0c:29:20:ce:d2
      Aug 30 16:56:23 ag-dc-1 named[675]: samba_dlz: starting transaction on zone adminguide.lan
      Aug 30 16:56:23 ag-dc-1 named[675]: samba_dlz: allowing update of signer=dhcpduser\@ADMINGUIDE.LAN name=3\(NXDOMAIN\).adminguide.lan tcpaddr=127.0.0.1 type=A key=3167229815.sig-ag-dc-1.adminguide.lan/160/0
      Aug 30 16:56:23 ag-dc-1 named[675]: client @0x7f1c180b8670 127.0.0.1#58645/key dhcpduser\@ADMINGUIDE.LAN: updating zone 'adminguide.lan/NONE': deleting rrset at '3\(NXDOMAIN\).adminguide.lan' A
      Aug 30 16:56:23 ag-dc-1 named[675]: samba_dlz: committed transaction on zone adminguide.lan
      Aug 30 16:56:23 ag-dc-1 dhcpd: DHCP-DNS Update succeeded
      Aug 30 16:56:23 ag-dc-1 dhcpd[10880]: DHCPRELEASE of 192.168.1.114 from 00:0c:29:20:ce:d2 (client-lin-1) via ens160 (found)
      Aug 30 16:56:23 ag-dc-1 dhcpd[10880]: DHCPDISCOVER from 00:0c:29:20:ce:d2 via ens160
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: DHCPOFFER on 192.168.1.114 to 00:0c:29:20:ce:d2 (client-lin-1) via ens160
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: adminguide.ru commit: IP: 192.168.1.114 DHCID: 00:0c:29:20:ce:d2 Name: client-lin-1
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: execute_statement argv[0] = /usr/local/bin/dhcp-dyndns.sh
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: execute_statement argv[1] = add
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: execute_statement argv[2] = 192.168.1.114
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: execute_statement argv[3] = 00:0c:29:20:ce:d2
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: execute_statement argv[4] = client-lin-1
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: starting transaction on zone adminguide.lan
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: allowing update of signer=dhcpduser\@ADMINGUIDE.LAN name=client-lin-1.adminguide.lan tcpaddr=127.0.0.1 type=A key=3775092585.sig-ag-dc-1.adminguide.lan/160/0
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: allowing update of signer=dhcpduser\@ADMINGUIDE.LAN name=client-lin-1.adminguide.lan tcpaddr=127.0.0.1 type=A key=3775092585.sig-ag-dc-1.adminguide.lan/160/0
      Aug 30 16:56:24 ag-dc-1 named[675]: client @0x7f1bf808a7f0 127.0.0.1#60997/key dhcpduser\@ADMINGUIDE.LAN: updating zone 'adminguide.lan/NONE': deleting rrset at 'client-lin-1.adminguide.lan' A
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: subtracted rdataset client-lin-1.adminguide.lan 'client-lin-1.adminguide.lan.#0113600#011IN#011A#011192.168.1.112'
      Aug 30 16:56:24 ag-dc-1 named[675]: client @0x7f1bf808a7f0 127.0.0.1#60997/key dhcpduser\@ADMINGUIDE.LAN: updating zone 'adminguide.lan/NONE': adding an RR at 'client-lin-1.adminguide.lan' A 192.168.1.114
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: added rdataset client-lin-1.adminguide.lan 'client-lin-1.adminguide.lan.#0113600#011IN#011A#011192.168.1.114'
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: subtracted rdataset adminguide.lan 'adminguide.lan.#0113600#011IN#011SOA#011ag-dc-1.adminguide.lan. hostmaster.adminguide.lan. 48 900 600 86400 3600'
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: added rdataset adminguide.lan 'adminguide.lan.#0113600#011IN#011SOA#011ag-dc-1.adminguide.lan. hostmaster.adminguide.lan. 49 900 600 86400 3600'
      Aug 30 16:56:24 ag-dc-1 named[675]: samba_dlz: committed transaction on zone adminguide.lan
      Aug 30 16:56:24 ag-dc-1 dhcpd: DHCP-DNS Update succeeded
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: DHCPREQUEST for 192.168.1.114 (192.168.1.100) from 00:0c:29:20:ce:d2 (client-lin-1) via ens160
      Aug 30 16:56:24 ag-dc-1 dhcpd[10880]: DHCPACK on 192.168.1.114 to 00:0c:29:20:ce:d2 (client-lin-1) via ens160
      

       

  2. DHCP сервер для Linux AD-DC – Заключение

    Таким образом мы и подошли к концу. Никогда не стоит забывать, что для улучшений ещё очень большой простор, но этот вариант позволит админу иметь в небольшом офисе лицензионный Active Directory Domain Controller с DNS и DHCP серверами, способными обслуживать не только компьютеры присоединённые к домену, но и все машины вообще. Что позволит уйти от настройки локальных сервисов на статические ip адреса, и перейти на использование динамических ip адресов в связке с dns именами устройств

P.S. Если у вас несколько сетевых интерфейсов настроенных на получение сетевых настроек по DHCP, они все получат настройки. Но команда host <device_name> вернёт адрес последнего интерфейса обратившегося к DHCP серверу.

Text.ru - 100.00%

You may also like

5 комментариев

Андрей 29.09.2020 - 16:42

Добрый день,
Все работает все тесты прошли успешно. Но при подключении к оснастке DNS обратная зона не видна. Прямая зона загрузилась. Это правильное поведение?

Reply
asylalim 01.10.2020 - 21:44

После перезагрузки настроенный и работающий сервер перестает авторизовывать даже уже введённые в домен машинки.
kinit administrator возвращает: Cannot contact any KDC for realm ‘*******.LAN’ while getting initial credentials.

Копал в сторону krb5kdc, пока ничего не накопал.

Reply
Belfigor 05.10.2020 - 08:37

Опытным путём, было выяснено что проблемы начинаются после версии самбы 4.6.8, пока я жду появления стабильной версии среди последних релизов, о чём наверное сделаю отдельную публикацию.

Reply
ASYLALIM 16.10.2020 - 14:29

Пропустил момент из этой статьи с настройкой и перезапуском Apparmor — и, о чудо! — контроллер домена заработал, как положено. Пока не раскопал, почему Apparmor блокировал работу керберос.

Ещё из непонятного — днс форвардинг с контроллера доменана шлюз иногда как будто отваливается, на клиентских компьютерах “пропадает” интернет из-за отсутствия резолвинга. Проходит само.

Reply
ASYLALIM 19.10.2020 - 14:19

Отваливание днс-форвардинга на шлюз вроде понял — управляемый свитч des-3028 (ещё разбираюсь, какой из них и не все ли попеременно — их у меня 10 штук по зданию) начинают блокировать трафик контроллера домена о.О: одновременно отваливается локальная сеть и интернет на машинках, висящих на этих свитчах. Машинки, висящие на других свитчах, локальную сеть не теряют, но теряют интернет, бо шлюз подключен к КД через один из свитчей des-3028.

С наскоку проблему не победил, надо курить документацию свитчей.

Reply

Leave a Comment