Настройте bootpd и bootpc для успешного взаимодействия друг с другом.

Вопрос или проблема

Текущие bootpc и bootpd (из bootp) в Debian, похоже, не работают вместе в текущей среде ядра Linux. Кажется, есть проблема 🐔/🥚; bootpd отправляет ответы как однонаправленные UDP-пакеты на еще не настроенный IP-адрес. Ядро клиента затем отбрасывает их, не доставляя в сокет клиента bootpc, потому что этот IP-адрес еще не является действительным локальным адресом на хосте.

Как это вообще работало?

  • Существует ли параметр ядра или другая модификация, которая может заставить ядро передать эти пакеты процессу bootpc?
  • Существует ли конфигурация для bootpd, которая позволит использовать IP-адреса назначения, заполненные всеми единицами или всеми нулями, вместо еще не настроенного однонаправленного IP-адреса клиента?

У нас есть потенциальный клиент с большой инфраструктурой bootp, не использующей DHCP. Поддержка старого bootp является одним из их требований.

Детали проблемы

  • bootpd отправляет свои ответные пакеты как однонаправленные пакеты на MAC-адрес клиента bootpc, используя значение IP-адреса назначения, соответствующее адресу, который также находится в полезной нагрузке, указывая клиенту настроить себя.
  • Ядро затем отбрасывает эти пакеты, а не передает их процессу bootpc, который их запросил.
  • bootpc корректно открыл сокет для прослушивания на 0.0.0.0:68 0.0.0.0:* (см. вывод netstat ниже)
  • Я подтвердил этот анализ несколькими способами:
    • Я запустил tcpdump и вижу, что ответы доходят до сетевого интерфейса
    • Я использовал dropwatch и вижу, что пакеты отбрасываются с причиной IPINADDRERROR, что в основном означает “недействительный IP-адрес”
    • Я могу заставить bootpd использовать 0.0.0.0 как IP-адрес назначения, пропуская фактическую настройку IP; когда я это делаю, bootpc получает ответы и обрабатывает их. Однако это не помогает, потому что в этом случае клиент не получает IP-адрес
    • Я пытался добавить IP-адрес к интерфейсу во время того, как bootpc делает запросы. Как только я его добавляю, следующий ответ доходит до процесса.
  • Я также попробовал опцию bootpc --serverbcast. Это не срабатывает по аналогичной причине:
    • bootpd отправляет ответы на широковещательный адрес подсети (например, 10.0.43.255)
    • Так как IP-адрес и маска подсети еще не настроены на интерфейсе, у ядра нет причин считать это действительным адресом для себя.

Вывод netstat, показывающий сокет для прослушивания bootpc:

$ sudo netstat -unlp
Активные интернет-соединения (только серверы)
Протокол Recv-Q Send-Q Локальный адрес           Удаленный адрес         Состояние       PID/Имя программы    
udp        0      0 0.0.0.0:68              0.0.0.0:*                           2295/bootpc         

Решение с обходом

Я нашел обходное решение, которое выглядит хакерским. В частности, я думаю, что оно использует непреднамеренное поведение, возможно, мы не можем рассчитывать на его работу в будущем:

  • Модуль отслеживания соединений iptables имеет матч ctstate со значением DNAT.
  • Это можно использовать для принятия пакетов, у которых адрес назначения не распознан
  • Я не думаю, что это предназначено для сопоставления произвольных IP назначения:
    • Он может использоваться только с пакетами, которые были NAT’d тем же хостом
    • Я думаю, что его цель – сопоставлять пакеты, адреса которых были переписаны (что мы не делаем), но это “дешевая” реализация, которая игнорирует таблицу сопоставления NAT вместо проверки наличия записи, соответствующей этому пакету.
    • Я обеспокоен тем, что это может быть удалено или переписано, чтобы быть менее неразборчивым в будущем
    • Чтобы это заработало, мне нужно переназначить эти пакеты на их существующий порт назначения, просто чтобы получить данные о состоянии соединения NAT на пакет, иначе --ctstate DNAT не применяется к пакету.

Фон/должная осмотрительность

  • Наша тестовая платформа использует Debian 12 на Linux 6.1.0.
  • Наши тестовые хосты являются стандартными образами виртуальных машин UTM Debian 12 с полки
  • bootpd имеет очень немного опций cli, ни одна из которых не касается ответов, портов или адресов. В руководстве не упоминаются “широковещательная” или “однонаправленная” передача, и упоминаний о “адресе” или “назначении” очень мало и они не актуальны.
  • Наш фактический продукт – это Debian 12 на пользовательском ядре Linux 5.19.9 (и ведет себя так же)
  • IP-соединение полностью работает между клиентом и сервером тестовой платформы
  • bootpc отказывается отправлять запросы, если не выполняются следующие условия:
    • На интерфейсе нет маршрутизируемого IP-адреса (169.254/16 приемлемо)
    • Существует маршрут по умолчанию 0/0, указывающий на интерфейс, где ожидается сервер bootp
      • В противном случае он говорит сеть недоступна
      • Примечание: указание --dev <iface> в командной строке bootpc не помогает в этом случае
  • Я все еще работаю над оценкой конфигурации bootptab, чтобы увидеть, есть ли какие-либо варианты, которые влияют на это. Не нашел хорошей ссылки на них, страница man bootptab очень кратка по этому поводу.

Альтернативное решение

Я смог заставить это работать с менее запутанным решением на iptables: я добавил правило NAT, которое сопоставляет UDP-порт 68 (bootpc) и перенаправляет IP-адрес назначения на 255.255.255.255 (и сохраняет тот же UDP-порт).

Это работает, но я считаю это хакерским. Очевидно, это не тот способ, как должен работать протокол, поэтому я бы предпочел “реальное” решение, если это возможно.

Ответ или решение

Как настроить взаимодействие между bootpd и bootpc

Проблема и ее корни

Ваша проблема с взаимодействием между bootpd и bootpc на Debian обусловлена тем, что сервер bootpd отправляет ответы как юникастовые UDP-пакеты на еще не настроенный IP-адрес клиента. Ввиду того что это IP-адрес не может быть валидным для клиента на момент получения пакета, операционная система отклоняет эти пакеты, и они не доходят до сокета bootpc.

Решение данной проблемы требует комплексного подхода, в рамках которого можно подумать как о конфигурациях, так и о возможных изменениях в настройках операционной системы.

Работа с kernel и конфигурацией

  1. Использование широковещательных адресов: Для демонстрации работы Bootp (Boot Protocol) необходимо протестировать использование широковещательных адресов, таких как 255.255.255.255. Однако, как вы заметили, когда bootpd отправляет пакеты на широковещательный адрес, клиент не имеет настроенного IP-адреса и, следовательно, пакеты не признаются валидными. Потенциальным решением было бы конфигурировать bootpd для использования как широковещательного адреса, так и указанного адреса клиента. К сожалению, если это не предусмотрено в текущей конфигурации bootpd, нет ясных CLI-параметров для решения этой проблемы.

  2. Добавление параметров ядра: Ядро Linux может требовать дополнительных параметров для работы с такими сценариями. Вам следует проверить наличие параметров, которые могут изменять поведение обработки IP-пакетов с недопустимыми адресами. Например, параметры, модифицирующие обработку маршрутизации и поиска IP-адресов в локальной машине:

    echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
    echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter

    Обратите внимание, что эти настройки могут снизить безопасность, поскольку они отключают некоторые проверки маршрутизации.

  3. Использование iptables для манипуляции пакетами: Ваш подход с использованием iptables может быть наиболее "работоспособным" решением в данной ситуации, и, хотя оно в определенной степени является хакерским, оно все же может дать стабильный результат. Вы уже пробовали NAT-преобразование, что является хорошим решением. Убедитесь, что ваши правила iptables настроены правильно и не блокируют другие подобные запросы.

    Пример команды для добавления правила NAT:

    iptables -t nat -A PREROUTING -p udp --dport 68 -j DNAT --to-destination 255.255.255.255:68

Настройки конфигурации bootpd и bootpc

  1. Проверка конфигурации bootptab: Обязательно проверьте файл конфигурации bootptab. Некоторые параметры могут влиять на поведение bootpd. Возможно, стоит дополнительно изучить другие опции, которые могли бы помочь в вашем сценарии, например, изменение параметров IP-адреса или управления клиентами.

  2. Запуск bootpc с указанием интерфейса: Параметры командной строки, такие как --dev <iface>, иногда требуют дополнительно включенного адреса в интерфейсе. Попробуйте временно назначить адрес для интерфейса, прежде чем запускать запрос на bootpc. Это может помочь в установлении первоначальной связи.

Заключение

Ваша задача — справиться с проблемой взаимодействия между bootpd и bootpc в контексте современного ядра Linux. Это может требовать как доработок в конфигурации приложений, так и модификаций системных параметров. Учитывая, что ваша проблема затрагивает важные функциональные аспекты для осуществления сервисов на базе Bootp в рамках вашей инфраструктуры, тестирование различных подходов и соглашений может стать основой для успешного достижения результата. Важно оставаться на связи с сообществом разработки и поддерживать адаптацию к новым версиям программного обеспечения и ядра, чтобы минимизировать возможные проблемы в будущем.

Оцените материал
Добавить комментарий

Капча загружается...