Взаимоотношения dhcpclient и resolv.conf'а в Linux

    Abstract: описание того, как обновляется файл /etc/resolv.conf в условиях работающего dhcp-клиента, специфика различных ОС и варианты реализации.

    Охват: Debian, Ubuntu, Centos/Fedora/RHEL; dhclient с resolvconf и без. NetworkManager не учитывается.

    Лирика: Я только что потратил несколько дней (подробности на английском [1], [2]) разбираясь как правильно сохранять 'options rotate' в /etc/resolv.conf в разных дистрибутивах при работающим DHCP. Оказалось, внятной документации по этому вопросу нет, и информацию пришлось собирать из разных источников, исходных текстов и экспериментальных данных. Дальше будет сухо и по делу.

    О чём речь?

    У компьютера сетевой интерфейс принципиально может быть сконфигурирован тремя видами: вручную/специализированным софтом, статически заданными настройками и через DHCP-клиент. (Есть ещё сколько-то экзотики, но эти три — основные методы). Первый метод нам не интересен, со статической конфигурацией всё просто — как написано, так и будет. DHCP интересен тем, что компьютер запрашивает настройки по сети «у кого-то». Протокол DCHP имеет множество опций (настроек), которые могут изменять совершенно неожиданные настройки компьютера — часовой пояс, адрес сервера с точным временем, таблицу маршрутизации, имя или домен сервера, и т.д. Из всего этого нас интересует возможность задавать настройки DNS.

    Традиционно, настройки DNS-ресолвера хранятся в файле /etc/resolv.conf, и после обновления dhcp-аренды этот файл обновляется. В этой статье объясняется, как именно "-ся" этот файл.

    Устройство DHCP client


    Существует несколько реализаций dhcp-клиента, нас интересует ISC DHCP, как наиболее распространённая.
    Сам клиент называется /sbin/dhclient, однако, стандартно, для обновления настроек, вызывается не он, а /sbin/dhclient-script. dhclient-script вызывает dhclient и использует его ответ для изменения разных частей системы. В самом dhclient-script есть функция make_resolv_conf, которая, собственно, и создаёт файл resolv.conf.

    Для удобства модификации (и запутывания системных администраторов) у dhclient-script'а есть хуки. Их положение разнится (в Ubuntu Xenial и Debian Stretch это /etc/dhcp/dhclient-exit-hooks.d, для какой-то версии Centos — /etc/dhclient-enter-hooks/ и т.д.). Хуки есть двух видов — entry и exit. Entry вызываются до основного когда dhclient-script, exit в конце. В хуках можно прописать свою версию функции make_resolv_conf(), и тогда dhclient-script будет вызывать её, а не встроенную. Что именно происходит с арендой определяет переменная reason (примеры значений: PREINIT, BOUND, RENEW, REBIND, REBOOT, EXPIRE, FAIL, RELEASE, etc). Спасибо maxzhurkin за указания на (исправленные) неточности в этом разделе.

    resolvconf


    Этим активно пользуются авторы пакета resolvconf, который позволяет формировать файл /etc/resolv.conf по заданному шаблону (а не фиксированно, как в случае родной реализации dhclient-script). Они кладут файл (в Debian/Ubuntu) /etc/dhcp/dhclient-enter-hooks.d/resolvconf, который вызывает resolvconf -u (обновление) для создания новой версии resolvconf'а.

    Чтобы не мешать жить dhcpclient-script, resolvconf управляет файлом /run/resolvconf/resolv.conf, а пакет resolvconf (не путать с программой, которую он предоставляет) при установке заменяет /etc/resolvconf на симлинк ../run/resolvconf/resolv.conf.

    Типовой проблемой при использовании resolvconf'а является отсутствие симлинка. Если его нет, то dhclient-script будет просто перезаписывать /etc/resolv.conf с настройками от DHCP-сервера, а resolvconf будет обновлять свой файл в уголочке, лишь выдавая предупреждение, что /etc/resolv.conf не симлинк.

    Шаблоны resolvconf'а довольно просты:
    • /etc/resolvconf/resolv.conf.d/head
    • /etc/resolvconf/resolv.conf.d/base
    • /etc/resolvconf/resolv.conf.d/tail

    head и tail просто дописываются куда положено, а вот base позволяет всякие странные штуки, которые описываются в man resolvconf в разделе «CONSUMERS OF NAMESERVER INFORMATION»).

    Специфика RHEL/Centos/Fedora


    Red Hat использует свою версию скрипта dhclient-script, весьма обширную и сложную, учитывающую множество настроек из ifcfg-ethXXX, в частности, интересовавшую меня опцию RES_OPTIONS. Debian и Ubuntu используют большей частью апстримовую версию, в которой такие изыски отсутствуют. В Centos 7 одно время в этом скрипте был баг, приводивший к тому, что при наличии строчки 'options' в /etc/resolv.conf при перезагрузке, из него удалялись все остальные строчки, кроме строчки с options, причём новые DNS-сервера в файл не добавлялись.
    Поделиться публикацией

    Комментарии 21

      +2
      Не сказать, что сильно надо, но дополнить статью примерами под спойлерами самих файлов, или важных частей из них на мой скромный взгляд не помешало бы.
      Или, скажем, если новичок наткнётся на статью — иметь готовую комманду для симлинка.
      А в целом спасибо, интересно
        0
        Примеры каких файлов? Которые make_resolv_conf() делает?
          +1
          Да, это было бы замечательно, сразу вся логика станет полностью понятной. Спасибо за статью!
            0
            man resolv.conf?
            Там вроде всё довольно понятно описано, но примеры не помешают.
              0
              В этом случае вы не поняли суть статьи. resolv.conf не пишется человеком, а генерируется роботами.
          0
          Спасибо. Давно хотел разобраться, как работает resolvconf.
            0
            Интересная информация! А как можно уберечься от ситуации, когда злоумышленник получит физический доступ к сети, поднимет свой фиктивный сервер DHCP и начнёт делать разные неприятные штуки?
              0
              Вы не поверите как быстро смониторится новый dhcp в сети…
              Раз как-то запустил кто-то из коллег виртуалку (bridged) со включенным dhcp — получил по рукам уже через 2 минуты (даже гнездо сетевое назвали, откуда уши торчат).
              Злоумышленник должен себя вести тише воды ниже травы (а тут как залезть ночью в супермаркет и начать бить посуду, орать и вообще всеми доступными способами семафорить — я тут, берите меня тепленького).
                0
                А у меня нет такой мониторилки :( Подскажите, какая у вас?
                  0
                  смотрите документацию к вашим свичам на тему DHCP snooping и 82 опции.
                0
                теоретически есть штуки типа "port security", но их не используют. Иногда файрволят dhcp на прикладном уровне (т.е. пропускают ack/offer только от авторизованных узлов). В случае обычной неуправляемой сети — с трудом.
                Более того, злоумышленника, который дублирует анонсы обычного dhcp-сервера, но отдаёт опцией маршрутизацию на себя (для mitm'а) будет довольно сложно найти (если нет внимательности на местах).
                0
                Про dhclient-script, а именно, про хуки бред написан:
                В начале dhclient-script определяются некоторые функции, которые могут быть переопределены в хуках entry.
                Эти функции могут быть вызваны в теле dhclient-script после вызовов хуков entry и до вызовов хуков exit, или эти функции могут быть вызваны в хуках exit
                А хуки exit предназначены для выполнения дополнительных действий.
                  0
                  Поясните насчёт "бред" побдробнее. Зарнее спасибо.
                    +1
                    <бред>
                    Entry вызываются когда dhcp-client только-только получает (получил) аренду, exit, соответственно, когда освободил (или она истекла).
                    </бред>
                    <на самом деле>
                    и entry и exit хуки вызываются и при получении аренды и при освобождении, только первые — в начале скрипта, а последние — в конце
                    </на самом деле>
                      0
                      Вы хотите сказать, что при release entry-хук тоже будет вызван?
                        0
                        Прочитайте код dhclient-script и/или текст моего сообщения, пожалуйста!
                          0
                          Прочитал. Вы хотите сказать, что при release entry-хук тоже будет вызван?
                            +1
                            Вот код вызова enter-hooks из dhcp-4.3.4/client/scripts/linux
                            if [ -f /etc/dhclient-enter-hooks ]; then
                            exit_status=0
                            . /etc/dhclient-enter-hooks
                            allow the local script to abort processing of this state
                            local script must set exit_status variable to nonzero.
                            if [ $exit_status -ne 0 ]; then
                            exit $exit_status
                            fi
                            fi
                            Перед ним только определение функции make_resolv_conf, то есть, никаких условий кроме наличия файла /etc/dhclient-enter-hooks
                            Да, я хочу сказать, что хуки вызываются в любом случае, если они есть и если до их вызова не произошла ошибка.
                              +1
                              Информация, позволяющая отличить события друг от друга, содержится в переменной $reason
                                0
                                Ага, спасибо. Я неправильно понял их назначение. Сейчас статью поправлю.
                  0
                  Red Hat использует свою версию скрипта dhclient-script, весьма обширную и сложную, учитывающую множество настроек из ifcfg-ethXXX, в частности, интересовавшую меня опцию RES_OPTIONS. Debian и Ubuntu используют большей частью апстримовую версию, в которой такие изыски отсутствуют. В Centos 7 одно время в этом скрипте был баг, приводивший к тому, что при наличии строчки 'options' в /etc/resolv.conf при перезагрузке, из него удалялись все остальные строчки, кроме строчки с options, причём новые DNS-сервера в файл не добавлялись.


                  Со строчкой опшнс все проще. Я не совсем до конца раскопал этот скрипт, но я как я понял — ситуация следующая: Если есть файл /etc/resolv.conf.save — То абсолютно неважно чо у вас там в Ifcfg-xxxx написано — он тупо будет его ресторить. Наличие опции RES_OPTIONS, PEER_DNS и прочих ему по барабану. И собственно почему он его создает только с опшнс (Без резолверов к примеру) — я долго не мог понять, но видимо это связано как-то с изменениями в файле/настройках.

                  В итоге — после удаления этого .save файла и прописывания опций в resolv.conf — они вполне остаются на своих местах даже при изменении самих серверов (скрипт таки умеет отфильтровывать и оставялть опции)

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое