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

DHCP server with SQL support on Perl DHCP сервер с базой SQL на Perl, с опцией 82, маршрутами и прочим

Документация: http://www.netlab.linkpc.net/wiki/ru:software:perl:dhcp_server

Скачать: http://netlab.linkpc.net/download/software/perl/dhcp_srv/dhcpd.pl

DHCP снифер для винды: http://www.netlab.li...n:net:dhcp_tool

 

Предлагаю обсуждать, предлагать фичи и патчи.

 

Сейчас есть готовый скелет, который будучи заряжен правильными SQL запросами вполне себе работает:

- отдаёт адреса и параметры взятые с базы через релей агентов (но не на прямые запросы), пишет в базу лог,

- обновляет в базе лизы

- многопоточный

- умеет миррорить запросы и ответы на указанный IP

- работать демоном (стартовый скрипт не написал, пишется шаблонно)

- несколько уровней вывода отладочной инфы: 1 - от кого, кому, время обработки, 2 - тоже что и 1 и декодинг содержимого пакетов

 

Кто немного знает перл и умеет писать запросы сможет быстро адаптировать под себя.

Все данные: статические и SQL запросы являющиеся приватными удалены.

 

 

КодUsage: dhcpd [options]

-b <ip> ip address to bind (def: 0.0.0.0)

-sp <port> port bind (def: 67)

-cp <port> port to send reply directly to client (def: 68)

-id <ip> ip addr DHCP server ID, REQUIRED!, MUST be real IP of server

-m <ip> ip address to mirror all packets on 67 port

-t <threads> number of thread, recomended: CPU cores * 2, (default 4)

-dbs database data source: DriverName:database=database_name;host=hostname;port=port

-dbl data base login

-dbp data base password

-P <path> name of PID-file for spawned process

-v <level> print debug info, levels: 1, 2 (def: off)

-d daemon mode

 

Соответственно, чтобы напустится нужно:

- дописать запросы, местами можно и закоментить (release, decline)

- перл с потоками + пакеты/порты указанные в комментах в начале скрипта

 

запускаю обычно: dhcpd.pl -id 192.168.0.1 -m 192.168.0.2 -t 2 -v 1

192.168.0.1 - адрес дхцп сервера (настроенный в релеях) к которому должны обращаться клиенты

192.168.0.2 - адрес куда миррорятся все пакеты, смотрю их под виндой этим: DHCPTool

2 - потока

1 - выводить минимум инфы о запросах: от кого получено, кому отправлено, сколько времени заняло

(для собственного удобства у меня все параметры: логин, пароль, адрес - для подключения к базе прописаны в скрипте)

 

Биндить лучше на 0.0.0.0, потому как если забиндить на конкретный IP то ответы будут уходить только с него, в случае нескольких адаптеров/алиасов остальные задействованны не будут. В таких случаях сервер будет получать, обрабатывать запрос но ответ уходить не будет.

Edited by Ivan_83

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites

Обновил скрипт.

 

 

Немного логики, тем кто захочет писать запросы.

 

1. приходит запрос, в запросе есть:

82.Vlan ID

82.Unit ID (номер коммутатора в стёке)

82.Port ID

82.Chassis ID (мак коммутатора)

giaddr (relay agent IP)

DHCP Client ID - а это вообще генерирует клиент

 

опция 82 и giaddr могут не приходить при попытке продления клиентом времени аренды, тк клиент уже имеет IP адрес и пытается слать запрос напрямую серверу. Зависит от коммутатора, его настроек и его глючности.

Соответственно клиент потеряет аренду если не получит от него запроса на продление, и клиент начнёт по новой получать адрес.

 

Из этого многообразия нужно определить что будем использовать для идентификации клиента и сети клиента.

RFC2141 говорит что мы должны полагаться на DHCP Client ID, если её нет то на аппаратный адрес, при идентификации клиента.

 

 

2. На основании выбранного идентификатора из п1 ищем в базе настройки для сети:

[scope id] - некоторая информация по которой будем искать из п1 (к примеру: 82.vlan id)

DHCP enabled

Lease time

Renew time

Rebind Time

Subnet mask

Routers (default gateways)

Domain Name servers

Static routes

Classless routes (можно держать net_id и по нему делать выборку с др таблицы)

Domain name

...

 

 

3. Лиза клиента

[client id] (тут может быть, к примеру: 82.vlan id + 82.port id или DHCP Client ID, те кто привязывает адрес к порту должны либо настраивать коммутаторы чтобы опция82 добавлялась всегда, либо организовывать логику с учётом того что после получения адреса, клиент запрос для продления аренды будет слать на прямую серверу и он не всегда релееится - те приходит без опции 82)

End Lease Time

IP

...

параметры из п2 можно продублировать здесь и считать их главнее

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

 

 

Это минимальная примерная логика обычных дхцп серверов.

Share this post


Link to post
Share on other sites

Почему скл-запросы убрали? Можно было бы вместе скрипт дальше разрабатывать. А сейчас это равносильно написанию по-новому...

Share this post


Link to post
Share on other sites

По новому - это вы преувеличиваете.

Здесь остаётся только дописать запросы к базе и подправить под себя их распихивание по параметрам ответа, вся обвязка есть и работает.

 

Запросы были под самописный биллинг, более того там есть некоторая специфика выдачи адресов, потому эти запросы общественности совершенно бесполезны.

Остался один запрос: для маршрутов ибо оно универсально. Притом, те у кого используюется prefixlen вместо subnetmask получат небольшой прирост, а в коде достаточно заменить название функции.

Если посмотрите предыдущий пост, то там описаны примерные таблицы под "традиционную" работу дхцп сервера.

Позже я напишу запросы/базу по схеме из моего предыдущего поста.

Так же попробую сделать кеш запросов и может быть работу без релей агентов - тогда будет полноценный дхцп сервер.

 

Сейчас ведётся работа на гостевыми подсетями, когда заработает - я опишу логику здесь.

 

 

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

Share this post


Link to post
Share on other sites

Ivan_83, если Вы его "допилите" вам будут безмерно благодарны сотни администраторов сетей, так как нормального решения DHCP+MySQL на сег. день не существует.

 

Может, нужна помощь? Готов взять на тестирование.

Edited by aivanzipper

Share this post


Link to post
Share on other sites

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

 

Работа без релей агентов вряд ли понадобится.

 

в функции db_data_to_reply опечатка

    if (index($_[1], DHO_DOMAIN_NAME) != -1) {
        $_[1]->addOptionValue(DHO_DOMAIN_NAME, $_[0]->{domain});
    }

$_[2]->addOptionValue Если вдруг кому неочевидно )

Edited by dwemer

Share this post


Link to post
Share on other sites

Фрирадиус я тоже пробовал.

 

Впечатления от него не очень, не для этого он:

- анлэнг на котором почти ничего нельзя сделать

- иногда падал в корку

- менее гибко при использовании перл орбработчика, чем сразу на перле

- под фряху тоже не умел биндится на интерфейс: те работал как мой скрипт - на обычном юдп сокете.

 

Были и плюсы:

- быстро отфутболивал левые запросы

- по отдельным параметрам запроса можно было фильтровать в анлэнге до перла, это тоже быстро

- можно было в простых случаях слать простые запросы в базу без перла (типа освобождение лизы - пометить что свободна)

 

 

$_[2]->addOptionValue Если вдруг кому неочевидно )
Заметил по ругани в выводе :)

 

db_data_to_reply - сейчас с зачатками гостевых подсетей, а вообще видимо уже менятся её вызов не будет.

Надеюсь что для обновления скрипта будет достаточно только копировать свои функции-обёртки к базе в самом низу скрипта.

 

Качните заного, только что обновил.

Share this post


Link to post
Share on other sites
Ivan_83, если Вы его "допилите" вам будут безмерно благодарны сотни администраторов сетей, так как нормального решения DHCP+MySQL на сег. день не существует.
dhcpsql есть давно, и соседний топик про тоже самое только с нуля.

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

 

 

Может, нужна помощь? Готов взять на тестирование.
Если только тыкать меня где я в перле не прав или можно было лучше/оптимальнее.

Тестируйте, пишите под себя запросы, можно и сразу веб интерфейс админки и будет счастье.

 

И чисто теоритически:

можно написать запросы в базу что бы прилетало в ответе: код опции - содержимое, и динамически это в скрипте упаковывать, а так же перенести часть логики в базу, тогда можно будет всё конфигурить только с базы, не трогая код что бы добавить опцию или что бы кому то отдавать по 82 опции а кому то просто по маку а кому то вообще статику.

После этого можно будет переписать на си и навесить рюшек.

Share this post


Link to post
Share on other sites

Позволю себе вмешаться.

 

Ivan_83, если Вы его "допилите" вам будут безмерно благодарны сотни администраторов сетей, так как нормального решения DHCP+MySQL на сег. день не существует.
dhcpsql есть давно, и соседний топик про тоже самое только с нуля.

Не лукавьте. Вы сами пробовали dhcpsql который "есть давно"? Помнится я пытался его когда-то запустить:

1. Конфигурабельности - 0. Даже configure не задумано. И настроить гибко на работу с базой тоже вроде не тривиально (давно было, но хороших впечатлений не осталось).

2. Работает только с MySQL.

3. Сборка в FreeBSD:

$ make
"Makefile", line 32: Need an operator
**** много таких строчек ****
make: fatal errors encountered -- cannot continue

Так что это - не "тоже самое только с нуля".

 

А нет потому что у всех потребности разные, и упихать в бинарник такую гибкость чтобы всем стало хорошо - сложно.
Ну... Мы об этом уже говорили.

 

можно написать запросы в базу что бы прилетало в ответе: код опции - содержимое, и динамически это в скрипте упаковывать, а так же перенести часть логики в базу, тогда можно будет всё конфигурить только с базы, не трогая код что бы добавить опцию или что бы кому то отдавать по 82 опции а кому то просто по маку а кому то вообще статику.
Мне кажется, или где-то я это уже видел?.. ;)

Share this post


Link to post
Share on other sites
Не лукавьте. Вы сами пробовали dhcpsql который "есть давно"? Помнится я пытался его когда-то запустить:
Мне хватило взгляда на исходники что бы понять что это как минимум заброшено и не так гибко как фрирадиус+перл, которые на тот момент у меня уже как то работали.

 

 

Мне кажется, или где-то я это уже видел?.. ;)
хз

 

Идея выбирать с базы номера опций, вместо названий пришла пока писал и дозрела до момента написания этого сообщения.

 

Заменить кучу конструкций вида:

    if (index($_[1], DHO_SUBNET_MASK()) != -1 && defined($_[0]->{mask})) {
        $_[2]->addOptionValue(DHO_SUBNET_MASK(), $_[0]->{mask});
    }

 

 

на что то типа:

for (my $i = 0; $i < length($_[1]); $i++) {
    $optcode = $_[1][$i];
    if (defined($_[0]->{$optcode})) {
        $_[2]->addOptionValue($optcode, $_[0]->{$optcode});
    }
}

Share this post


Link to post
Share on other sites

Идея выбирать с базы номера опций, вместо названий пришла пока писал и дозрела до момента написания этого сообщения.

Может и так. Просто "в соседнем топике" обсуждается сервер который именно так и делает (+ выборка типа данных) ;) Думаю вы уже заметили, коли достаточно бдительно смотрели в код.

Share this post


Link to post
Share on other sites
Может и так. Просто "в соседнем топике" обсуждается сервер который именно так и делает (+ выборка типа данных) ;) Думаю вы уже заметили, коли достаточно бдительно смотрели в код.
Смотрел на то что знаю: сеть и кеш :)

 

Для себя выделил такие типы и флаги в DHCPTool:

#define DHCP_OPTP_T_NONE        0
#define DHCP_OPTP_T_SUBOPTS        1
#define DHCP_OPTP_T_BOOL        2
#define DHCP_OPTP_T_1BYTE        3
#define DHCP_OPTP_T_2BYTE        4
#define DHCP_OPTP_T_2TIME        5
#define DHCP_OPTP_T_4BYTE        6
#define DHCP_OPTP_T_4TIME        7
#define DHCP_OPTP_T_IPADDR        8
#define DHCP_OPTP_T_IPIPADDR    9
#define DHCP_OPTP_T_STR            10
#define DHCP_OPTP_T_STRUTF8        11
#define DHCP_OPTP_T_STRRR        12    // DNS string format
#define DHCP_OPTP_T_BYTES        13
#define DHCP_OPTP_T_ADV            14    // option have specific format
#define DHCP_OPTP_T_PAD            254
#define DHCP_OPTP_T_END            255


#define DHCP_OPTP_F_NONE        0
#define DHCP_OPTP_F_NOLEN        1
#define DHCP_OPTP_F_FIXEDLEN    2
#define DHCP_OPTP_F_MINLEN        4
#define DHCP_OPTP_F_ARRAY        8
// in case (FIXEDLEN + ARRAY), Len = sizeof 1 element

 

Применительно к серверу DHCP_OPTP_T_IPIPADDR не имеет смысла тк это фактически DHCP_OPTP_T_IPADDR + DHCP_OPTP_F_ARRAY

а для отображения опции 33 и 21 (Policy filter (dst net/mask)) удобнее.

DHCP_OPTP_T_*TIME тоже для удобства декондинга при отображении.

И много опций с DHCP_OPTP_T_ADV получилось, для которых уникальная обработка.

Share this post


Link to post
Share on other sites
Срок регистрации домена rozhuk.org.ru закончился

 

Услуга по регистрации доменного имени rozhuk.org.ru временно не предоставляется.

 

Продлить домен

 

Если администратор домена не продлит регистрацию, домен освободится.

Непорядок.

Share this post


Link to post
Share on other sites

большое спасибо, отличная работа. чуть подправил под себя.

кому интересно вот ссылки.

сам сервер dhcpd.pl

чуть опишу что сделал может кому пригодится

таблица my $table="dhcp_mac_ip";

всего 2 поля mac и ip но в формате bigint, при чем поле mac делаем уникальным.

все это подтачивалось под провайдера с 500 сетями в таблице маршрутизации.

да и кстати один нюанс, таблиц с сетью, броадкастом, рутером в данной реализации не нужно, все расчитывается динамически исходя из 2 обязательных факторов:

1. default route для всех ip является первая ip в сети(к примеру в сети 10.3.7.128/25 шлюзом будет 10.3.7.129)

2. все сети есть в таблице маршрутизации самого сервера.

таблица лога у меня такая

(`created`,`client_mac`,`client_ip`,`gateway_ip`,`client_ident`,`requested_ip`,`hostname`,`message_type`) поле client_mac уникальное.

в итоге очень напоминает вид ip->dhcpserver->leases у микротиков.

еще мелкие файлики для работы с базой

db_list.pl

live.pl

add.pl

и файлики которые помогут выбрать ip mac пары из dhcpd.conf

comments

par.pl

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

если кто сможет красиво и удобно доработать буду только рад.

Edited by maxxch

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Хочу сказать спасибо за программулину! Очень помогла!

У меня работает с opt82.

 

Только ни как не могу заставить в логи читабельно писать getOptionRaw(DHO_HOST_NAME()) (или getOptionValue(DHO_HOST_NAME())) русские названия.

 

Может кто знает?

Share this post


Link to post
Share on other sites

кусок логов с русскими буквами выложите в виде файла

Share this post


Link to post
Share on other sites

кусок логов с русскими буквами выложите в виде файла

 

tail -n 1000 /var/log/dhcpsql.log | grep -a HOST > ~versen/WORK/dhcpsql.log.txt

dhcpsql.log.txt

Share this post


Link to post
Share on other sites

тут похоже уже сделана какая-то перокидоровка с потерей информации. Сделайте дамп tcpdump'ом, посмотрите хотя бы в какой кодировке приходят такие запросы

Share this post


Link to post
Share on other sites

тут похоже уже сделана какая-то перокидоровка с потерей информации. Сделайте дамп tcpdump'ом, посмотрите хотя бы в какой кодировке приходят такие запросы

Да, это я уже пробовал encode("cp1251",$dhcpreq->getOptionRaw(DHO_HOST_NAME())).. забыл убрать.

Также пробовал koi8-r и utf8. Результат тот же..

 

Как посмотреть кодировку с помощью tcpdump?

 

Смотрю

tcpdump -ni vlan10 -X -s 310 port 67 or port 68

Непонятно..

 

Вот так без encode:

dhcpsql.log.2.txt

Share this post


Link to post
Share on other sites

$ cat dhcpsql.log | iconv -f cp866 -t utf8

[31/May/2011 19:40:04] 810281452 DHCPTYPE = 3;HOST_NAME = жоппа

[31/May/2011 19:40:17] 3329464208 DHCPTYPE = 8;HOST_NAME = Маша-ПК

 

 

Привет от 640Кб памяти

Share this post


Link to post
Share on other sites

$ cat dhcpsql.log | iconv -f cp866 -t utf8

[31/May/2011 19:40:04] 810281452 DHCPTYPE = 3;HOST_NAME = жоппа

[31/May/2011 19:40:17] 3329464208 DHCPTYPE = 8;HOST_NAME = Маша-ПК

 

 

Привет от 640Кб памяти

 

Ооо.. Большое спасибо!

А то что это cp866 как определяется? Только перебором?

Edited by versen

Share this post


Link to post
Share on other sites

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

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