Jump to content
Калькуляторы

DHCP + SQL БД. Сабж при помощи патча к dhcpd.

Предлагаю всем желающим поучаствовать в тестировании патча. В качестве связующего звена между DHCP сервером и SQL БД используется протокол RADIUS.

 

Реализованы следующие полезные фичи:

 

1. Вся конфигурация DHCP находится в SQL БД и может быть динамически изменена без перезапуска dhcpd или FreeRADIUS. Это так же относится к логике обработки DHCP запросов сервером БД.

2. Кэширование DHCP информации. На практике в несколько раз снижает нагрузку на сервер БД.

3. Механизм предотвращения перегрузки сервера БД чрезмерно частыми запросами, например: флудом DHCPDISCOVER, возникающим при образования "петли" в сегменте сети, либо в результате действий злоумышленника. Ограничивается частота поступления запросов, как от отдельных клиентов, так и суммарная от всех клиентов.

4. Резервирование используемых RADIUS серверов.

5. Механизм обновления статической привязки IP адресов к MAC адресам в ARP таблице хоста, на котором запущен dhcpd.

6. Возможность отправки произвольных DHCP опций из клиентских запросов на сервер RADIUS. Например опции 82, типа запроса, запрашиваемого адреса и т.д.

 

В принципе код патча достаточно стабилен (падений и утечек зафиксированно не было), тестирование необходимо в основном для добавления/корректировки фич.

 

Сам патч, подробности настройки и использования здесь: http://www.netpatch.ru/dhcp2radius.html

Edited by RomanCh

Share this post


Link to post
Share on other sites

интересная штука

 

Share this post


Link to post
Share on other sites

Очень интересное решение. Мы написали свой dhcp-сервер с хранением в своей БД, синхронизирующейся с MySQL.

Share this post


Link to post
Share on other sites

В данном случае решение более универсально - можно прицепить к любой БД поддерживаемой FreeRADIUS.

Share this post


Link to post
Share on other sites
Спасибо. Будем пробовать.
Если что не ясно, не так работает как должно или просто чего-то явно не хватает - сообщайте. Постараемся решить.

 

И ещё - пример дан для PostgreSQL. Приветствуются рабочие конфиги для других СУБД.

Share this post


Link to post
Share on other sites

Проблема с дхцп, не хочет слушать лупбек. Но это не проблема патча, а самого дхцп сервера.

FreeBSD 7.0-STABLE

ifconfig lo0
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        inet 127.0.0.1 netmask 0xff000000
        inet6 ::1 prefixlen 128

dhcpd -d lo0
Internet Systems Consortium DHCP Server V3.0.7
Copyright 2004-2008 Internet Systems Consortium.
Patched by Chebotarev Roman. Home page: http://www.netpatch.ru/dhcp2radius.html
Patch version info: RADIUS to DHCP patch (dhcp2radius) v 0.1 2009.06.15
All rights reserved.
For info, please visit http://www.isc.org/sw/dhcp/
PATCH: dhcp2radius ability is enabled.
Wrote 0 leases to leases file.
lo0: not found

Если запустить без lo0 то дхцп не видит ответы от радиуса (как и описано на сайте)

Если радиус вынесен на другом сервере, то дхцп видит его ответы.

В общем вопрос такой как заставить дхцп слушать на лупбеке (гугление не особо помогло)?

Edited by skor78

Share this post


Link to post
Share on other sites

Нечто непонятное. У меня на lo0 всё вроде бы работает. Правда я FreeRADIUS не запускал на нём, но смотрел дампом - пакеты ходят и запускается тоже без проблем. Есть одно но - запускал в виртуалке, но по идее в это вообще ни как не должно быть связано т.к. lo0 сам по себе виртуален. Версия 7.2-RELEASE, ядро дефолтное. Если до завтра сами не решите в чём проблема, попробую разобраться что за безобразие. Если решите - поделитесь секретом :-)

Edited by RomanCh

Share this post


Link to post
Share on other sites

skor78 кажется проблема обрисовалась. У меня такая же ошибка если собирать из сорцев которые ставятся через порты. Если брать оригинальные с ISC - работает.

Если у вас так же - попробуйте пока поработать с оригинальными сорцами, а я постараюсь разобраться что там напатчили в портах.

Share this post


Link to post
Share on other sites

Похоже работу с лупбеком специлально убрали зачем-то...

/usr/ports/net/isc-dhcp30-server/files/patch-common::discover.c

...

-               /* Skip non broadcast interfaces (plus loopback and
-                  point-to-point in case an OS incorrectly marks them
-                  as broadcast). Also skip down interfaces unless we're
+               /* See if this is the sort of interface we want to
+                  deal with.  Skip loopback, point-to-point and down
+                  interfaces, except don't skip down interfaces if we're
                   trying to get a list of configurable interfaces. */
-               if (((!(ifr.ifr_flags & IFF_BROADCAST) ||
-                     ifr.ifr_flags & IFF_LOOPBACK ||
-                     ifr.ifr_flags & IFF_POINTOPOINT) && !tmp) ||
-                   (!(ifr.ifr_flags & IFF_UP) &&
+               if ((ifa->ifa_flags & IFF_LOOPBACK) ||
+                    (ifa->ifa_flags & IFF_POINTOPOINT) ||
+                    (!(ifa->ifa_flags & IFF_UP) &&
                     state != DISCOVER_UNCONFIGURED))
                        continue;
...

Share this post


Link to post
Share on other sites

Посмотрел еще исходники. По идее ДХЦП изначально не должен был работать в лупбеками. И то что раньше он работал получается бага?

Share this post


Link to post
Share on other sites

Посмотрел еще исходники. По идее ДХЦП изначально не должен был работать в лупбеками. И то что раньше он работал получается бага?

Я сегодня тоже пришёл к тому же выводу. Забавно но факт. Впрочем удивительного мало, учитывая то что функция в которой происходит проверка интерфейсов занимает "всего" 600 строчек монолитного кода. Думаю теперь как грамотно сделать патч что бы он работал после применения патчей от FreeBSD. Вероятно придётся делать отдельную версию.

Share this post


Link to post
Share on other sites

Такой вопрос:

Ответы от радиуса при запросах DHCPDISCOVER и DHCPREQUEST должны быть одинаковые и содержать в ответе одни и те-же атрибуты?

Share this post


Link to post
Share on other sites
Такой вопрос:

Ответы от радиуса при запросах DHCPDISCOVER и DHCPREQUEST должны быть одинаковые и содержать в ответе одни и те-же атрибуты?

Вероятно вы про наличие атрибута указывающего тип ответа (OFFER/ACK/NAK) - если да, то его слать не надо. dhcpd сам решает исходя из ситуации какой тип пакета отправить. Обусловленно это как минимум кэшированием - если оно включено то на RADIUS сервер отсылается только один запрос.

А вообще, исходя из протокола DHCP - ответы сервера должны содержать одинаковый набор конфигурационных данных в OFFER & ACK. Хотя для преобразования их в DHCP из RADIUS это не принципиально. Главное что бы совпадали обязательные атрибуты (они указаны в описании).

Share this post


Link to post
Share on other sites

файл common/dhcp2radius.c

Строка 1404

if(cur_xid -> request_info.client_addr.s_addr & subnet_mask != out_packet -> yiaddr.s_addr & subnet_mask)

Заменил на

if((cur_xid -> request_info.client_addr.s_addr & subnet_mask) != (out_packet -> yiaddr.s_addr & subnet_mask))

иначе на DHCPREQUEST (при обновлении адреса) упорно выдвало

Ignore DHCPREQUEST because the IP address of the client (x.x.x.x) is incorrect.

Edited by skor78

Share this post


Link to post
Share on other sites

Да, видимо накладочка с приоритетами операций вышла. В данном случае скобки не являются избыточными. Пофиксю.

Share this post


Link to post
Share on other sites

Как обстоит дело с синхронизацией и удалением протухших привязок в базе если один из компонентов (dhcpd, radius, БД) или все вместе были не доступны некоторое время?

Share this post


Link to post
Share on other sites
Как обстоит дело с синхронизацией и удалением протухших привязок в базе если один из компонентов (dhcpd, radius, БД) или все вместе были не доступны некоторое время?
Если вы про динамически выдаваемые адреса, то это всё рулится SQL-скриптом работающим на сервере СУБД. В примере - при каждом запросе выполняется функция get_id() которая очищает все устаревшие записи перед тем как пытаться выдать динамический адрес. Разумеется ни кто не запрещает вам самостоятельно реализовать более удобный вариант.

 

1. Если не работал dhcpd - понятно что для конечного юзера "ничего не работает". Запросы в radius не идут и соответственно говорить о обновлении информации и удаления старых аренд даже нет смысла.

2. Если не работал radius и не было резервного - некоторое время dhcpd продержится на кэше (если кэш включён). Но новые юзеры получать адреса уже не смогут, что логично. При поднятии radius сервера первый же запрос убьёт все устаревшие аренды в БД.

3. Если не работал сервер БД - в общем-то то же самое что и пункт 2. Если конечно в ходе поднятия БД вы сами не уничтожите

 

В отношении статических привязок MAC->IP: всё зависит от вашей реализации управления БД. В случае смены MAC адреса в БД и включённом кэшировании на dhcpd клиенту нужно будет перезапустить инициализацию сети (выключить/включить сетевое подключение если винда).

Share this post


Link to post
Share on other sites
skor78 пофиксил проблему с приоритетом операций в условии и ещё кой-чего, пока патч в ссылках на сайте не опубликовал, возьмите на тест по прямой ссылке: http://www.netpatch.ru/projects/dhcp2radiu...1.patch.tar.bz2
Edited by RomanCh

Share this post


Link to post
Share on other sites

Сейча вроде нормально.

Пофиксилась и еще одна бага:

если в lease файле нет записи о хосте и кеш выключен, то новый клиент не может получить адрес.

DHCPDISCOVER/DHCPOFFER проходит нормально а на первый DHCPREQUEST выдавало Ignore DHCPREQUEST ...

т.к. при в первом DHCPREQUEST клиент ставил yiaddr = 0.0.0.0 и это не проходило через проверку.

 

Кстати, если управление адресами будет вестись в БД через радиус, то запросы DHCPRELEASE тоже наверно стоит передавать в сторону радиуса.

Share this post


Link to post
Share on other sites
Сейча вроде нормально.

Пофиксилась и еще одна бага:

если в lease файле нет записи о хосте и кеш выключен, то новый клиент не может получить адрес.

DHCPDISCOVER/DHCPOFFER проходит нормально а на первый DHCPREQUEST выдавало Ignore DHCPREQUEST ...

т.к. при в первом DHCPREQUEST клиент ставил yiaddr = 0.0.0.0 и это не проходило через проверку.

Да, в частности про это и писал подразумевая "кое-что" :-)
Кстати, если управление адресами будет вестись в БД через радиус, то запросы DHCPRELEASE тоже наверно стоит передавать в сторону радиуса.
Думал об этом. В любом случае для этого надо создать отдельную опцию в конфиге, но - метаюсь над двумя вариантами:

1. Сделать режим в котором вообще все сообщения будут передаваться к RADIUS. Возникает вопрос - что тогда делать например с DHCPINFORM?

2. Сделать как вы предлагаете - только отправку DHCPRELEASE.

 

И главный вопрос который нужно решить - что же всё-таки делать с багофичей из-за которой работает loopback в стандартной поставке?

Share this post


Link to post
Share on other sites
А если через radclient?
Это к чему, к теме о багофиче с loopback? Если да, то честно говоря страшно мне в код ISC что-либо дополнительное вживлять, хотя задумывался об этом. + это потянет дополнительные либы в систему, что тоже теоритически может возыметь ряд побочных эффектов зависимых от версий либ. Следовательно на порядок усложняется тестирование и отладка.

Как вариант - создавать самому socket отдельно для RADIUS сервера. Но честно говоря тогда уж получается проще с нуля писать весь проект, чем пытаться что-то вживить в код ISC. Вы посмотрите на него внимательно - они сами в нём запутались неоднократно. Я пока этот патч прикручивал - сам кучу багов нашёл, хотя цели их искать вовсе не было.

 

С другой стороны - может действительно отдельный проект сделать? :-) Но понятно что это не в два дня сделается.

Share this post


Link to post
Share on other sites

заточенный под провайдинг дхцп это было бы круто :)

Share this post


Link to post
Share on other sites

Немного поковырявшись заставли работать с радиусом на 127.0.0.1 с использованием USE_SOCKETS (как следствие дхцп сможет жить только на 1 интерфейсе)

cd /usr/ports/net/isc-dhcp30-server

make config (ставим галочки DHCP_JAIL и DHCP_SOCKETS, при желании можно jail не включать, а руками указать USE_SOCKETS при компиляции)

make patch

cd work

patch -p0 < path/to/file (radius-патч)

потом в файле /usr/ports/net/isc-dhcp30-server/work/dhcp-3.0.7/common/dhcp2radius.c меняем 122 строчку

вместо

&& can_unicast_without_arp (out) )

пишем

)

дальше make install как обычно

Edited by skor78

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this