Вопрос или проблема
Текущие 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
, чтобы увидеть, есть ли какие-либо варианты, которые влияют на это. Не нашел хорошей ссылки на них, страница manbootptab
очень кратка по этому поводу.
Альтернативное решение
Я смог заставить это работать с менее запутанным решением на iptables
: я добавил правило NAT, которое сопоставляет UDP-порт 68 (bootpc) и перенаправляет IP-адрес назначения на 255.255.255.255 (и сохраняет тот же UDP-порт).
Это работает, но я считаю это хакерским. Очевидно, это не тот способ, как должен работать протокол, поэтому я бы предпочел “реальное” решение, если это возможно.
Ответ или решение
Как настроить взаимодействие между bootpd и bootpc
Проблема и ее корни
Ваша проблема с взаимодействием между bootpd
и bootpc
на Debian обусловлена тем, что сервер bootpd
отправляет ответы как юникастовые UDP-пакеты на еще не настроенный IP-адрес клиента. Ввиду того что это IP-адрес не может быть валидным для клиента на момент получения пакета, операционная система отклоняет эти пакеты, и они не доходят до сокета bootpc
.
Решение данной проблемы требует комплексного подхода, в рамках которого можно подумать как о конфигурациях, так и о возможных изменениях в настройках операционной системы.
Работа с kernel и конфигурацией
-
Использование широковещательных адресов: Для демонстрации работы Bootp (Boot Protocol) необходимо протестировать использование широковещательных адресов, таких как 255.255.255.255. Однако, как вы заметили, когда
bootpd
отправляет пакеты на широковещательный адрес, клиент не имеет настроенного IP-адреса и, следовательно, пакеты не признаются валидными. Потенциальным решением было бы конфигурироватьbootpd
для использования как широковещательного адреса, так и указанного адреса клиента. К сожалению, если это не предусмотрено в текущей конфигурацииbootpd
, нет ясных CLI-параметров для решения этой проблемы. -
Добавление параметров ядра: Ядро Linux может требовать дополнительных параметров для работы с такими сценариями. Вам следует проверить наличие параметров, которые могут изменять поведение обработки IP-пакетов с недопустимыми адресами. Например, параметры, модифицирующие обработку маршрутизации и поиска IP-адресов в локальной машине:
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter
Обратите внимание, что эти настройки могут снизить безопасность, поскольку они отключают некоторые проверки маршрутизации.
-
Использование 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
-
Проверка конфигурации bootptab: Обязательно проверьте файл конфигурации
bootptab
. Некоторые параметры могут влиять на поведениеbootpd
. Возможно, стоит дополнительно изучить другие опции, которые могли бы помочь в вашем сценарии, например, изменение параметров IP-адреса или управления клиентами. -
Запуск bootpc с указанием интерфейса: Параметры командной строки, такие как
--dev <iface>
, иногда требуют дополнительно включенного адреса в интерфейсе. Попробуйте временно назначить адрес для интерфейса, прежде чем запускать запрос наbootpc
. Это может помочь в установлении первоначальной связи.
Заключение
Ваша задача — справиться с проблемой взаимодействия между bootpd
и bootpc
в контексте современного ядра Linux. Это может требовать как доработок в конфигурации приложений, так и модификаций системных параметров. Учитывая, что ваша проблема затрагивает важные функциональные аспекты для осуществления сервисов на базе Bootp в рамках вашей инфраструктуры, тестирование различных подходов и соглашений может стать основой для успешного достижения результата. Важно оставаться на связи с сообществом разработки и поддерживать адаптацию к новым версиям программного обеспечения и ядра, чтобы минимизировать возможные проблемы в будущем.