Использование автоматического назначения IP-адресов способно упростить жизнь абонентам сети. Безусловно, при изоляции абонента на отдельном порту управляемого коммутатора, целесообразность использования dhcp настолько очевидна, что даже бессмысленно её обсуждать. При наличии так называемых «неуправляемых» сегментов, построенных на неуправляемых коммутаторах, существует целый ряд трудностей. В этой статье рассмотрим одну из них — возможность появления в сети «левых» dhcp-серверов. В качестве такого сервера может выступать wi-fi маршрутизатор в режиме моста, ethernet-маршрутизатор, включенный в сети со стороны LAN либо откровенно «вражеский» сервер злоумышленников. В любом случае надо научится быстро и грамотно ликвидировать возможный вред от левых серверов без ущерба для работы сети, в частности не мешая основному dhcp-серверу.

На сегодняшний день наиболее действенным способом борьбы является использование специальной программы dhcdrop. Однако при этом возникает ряд «подводных камней». В статье я сформулирую тот максимум, который можно выжать сейчас и обозначу проблемы, которые еще только требуют решения.

Итак, dhcdrop на первый взгляд предоставляет много различных опций, однако, все ли они полезны? Рассмотрим по порядку

  • -h — вывод справки, без комментариев
  • -D — список доступных сетевых интерфейсов в формате номер:имя список IP-адресов. Особой пользы нет
  • -y — это полезная опция, поскольку позволяет автоматически соглашаться с предложениями «давить» найденные сервера
  • -r — запрет случайной генерации mac-адреса в теле DHCP-запроса. Это полезная опция, почему, расскажу позже
  • -b — использовать в DHCP пакетах флаг BROADCAST, особого смысла нет
  • -a — ожидать ответ на 68 порту, врядли может быть полезно в нашем деле
  • -A — ожидать ответ на 67 порту,
  • -f — режим флуда запросами DHCPDISCOVER, причем при опции -r все пакеты содержат одинаковый mac-адрес, такое ограничение практически делает его бесполезным
  • -R — послать пакет DHCPRELEASE с MAC-адресом заданным параметром и IP-адресом, заданной опцией -F серверу, указанному опцией -s, для целей борьбы мало полезно
  • -q — не выводить сообщения, также не очень полезная опция
  • -m — число попыток получения ответа от DHCP-сервера, это хорошая, нужная опция
  • -c — максимальное число получаемых адресов (по умолчанию 255), в принципе значения по умолчанию практически всегда хватает, но иногда бывает полезно и указать больше
  • -n — указания DHCP-опции ‘HostName’ (по умолчанию ‘DHCP-dropper‘), в принципе можно поменять, но смысла особого в нашем случае нет
  • -N — указания DHCP-опции ‘Vendor-Class’ (по умолчанию ‘DHCP-dropper’), в принципе можно поменять, но смысла особого в нашем случае также нет
  • -p — указать порт клиента (по умолчанию 68), менять не надо
  • -P — указать порт сервера (по умолчанию 68), менять не надо
  • -w — указывает задержку времени между перезапусками процесса в аргессивном режиме с опцией -L
  • -T — указывает задержку в ожидании ответа (по умолчанию 3 секунды), можно изменить на 5
  • -M — максимальное число хостов, сканируемых в агрессивном режиме
  • -l — указание MAC-адреса «легального» DHCP-сервера, т.е. такого, которому не будут отправляются запросы адресов. Однако, пакеты DHCPDISCOVER «легальный» сервер получать будет, а следовательно будет предлагать IP-адреса из пула, а также будет заносить запросы в лог
  • -L — «легальная» сеть для интерфейса. Если таковую (таковые) задать, то программа использует агрессивный режим, при котором производится сканирование диапазона адресов DHCP-сервера и для каждого адреса из «нелегальной» сети посылается пакет DHCPRELEASE серверу после перезапуска процесса. Очень сомнительная опция. Начнем с того, что «левый» DHCP-сервер может выдавать адреса из легального диапазона, с чем я столкнулся на практике. Авторы программы видать не подумали о таком варианте, а давить то как-то надо..
  • -S — arp-сканирование указанной сети, зачем не очень понятно
  • -F — указание IP-адрес источника при сканировании (опции -R -S)
  • -s — указание IP-адреса DHCP-сервера (опция -R)
  • -c — количество потоков при флуде (опция -f)
  • -i — указание интерфейса

Отметим несколько ньюансов:

  • в режиме флуда программа не выбирает адреса из пула сервера, она просто, в переносном смысле, «загаживает» сеть паразитным трафиком, причем «дергается» и легальный сервер
  • если запустить программу с числом запросов 1200 (например на час), то обнаруженный сервер будет подавлен только один раз. Особенностью встроенных в аппаратные роутеры DHCP-серверов является их автоматическое очищение пула адресов и восстановление работоспособности буквально в течении нескольких минут, очевидно, что нужно часто перезапускать программу

Таким образом я рекомендую запуск в таком виде:

/usr/local/sbin/dhcdrop -y -r -m 255 fe:ff:ff:ff:ff:00 -i vlan40

Т.е. определяются MAC-адреса в теле запроса из диапазона fe:ff:ff:ff:ff:00-fe:ff:ff:ff:ff:ff. На хосте с «легальным» DHCP-сервером надо добавить следующее правило ipfw

deny udp from 0.0.0.0 to 255.255.255.255 dst-port 67 MAC any fe:ff:ff:ff:ff:00/40 mac-type 0x0800

Таким образом фильтруются любые DHCP-запросы от диапазона MAC-адресов, используемого для борьбы с «нелегалами». К счастью, в аппаратных роутерах так называемый «пакетный фильтр» — упрощенная версия маргинального iptable — не позволяет зафильтровать диапазон MAC-адресов.

Однако проблема восстановления работоспособности нелегальных серверов так и не решена. Перезапуск dhcdrop по cron каждую минуту не дает особых результатов.

В принципе «отцу русской автоматической раздачи адресов» поможет (но не спасет) скрипт

#!/usr/bin/perl
my @ifaces = ('vlan41','vlan42','vlan43');
while (1) {
@procs = `/bin/ps -ax | /usr/bin/grep 'dhcdrop' | /usr/bin/grep -v 'grep'`;
foreach $proc (@procs) {
$proc =~ /^\s*(\d+)\s/;
system("/bin/kill -9 $1");
}
sleep(5);
foreach my $iface (@ifaces) {
my $pid=`/bin/ps -ax|/usr/bin/grep 'dhcdrop -i $iface'|/usr/bin/grep -v grep | /usr/bin/awk '{print \$1}'`;
($pid eq '') {
system("/bin/date >> /var/log/dhcdrop/$iface &");
system("/usr/local/sbin/dhcdrop -y -r -m 255 fe:ff:ff:ff:ff:00 -i $iface >> /var/log/dhcdrop/$iface &");
}
}
sleep(50);
}
__END__

Скрипт запускается в фоновом режиме. Примерно каждую минуту происходит перезапуск dhcdrop на всех интерфейсах. Однако этого мало. Предположим, что вы четко установили наличие постоянно включенного нелегального DHCP-сервера, желательно организовать для него «целевое давление». Т.е. надо посылать пакеты DHCPREQUEST конкретному серверу, причем постоянно. Вот именно этого функционала так не хватает программе.