DHCP через RADIUS из PostgreSQL

Устаревшая версия!

Внимание: данная версия является устаревшей, обновление смотрите здесь.

Мотивация

При использовании в локальной сети протокола DHCP для выдачи конфигурационной информации клиентам, очень часто используется ISC DHCP, так как он удовлетворяет всем требованиям в случае, если конфигурация DHCP статична, например отсутствует привязка IP адресов к MAC адресам клиентов, либо новые клиенты появляются редко, либо клиенты редко изменяют MAC адреса (т.е. редко меняют оборудование). В противном случае возникает необходимость очень часто изменять текстовый файл конфигурации и перезапускать сервер, что может оказаться мягко говоря не очень удобно, и уж точно - совсем не интересно. В данной статье освещается один из вариантов решения данной проблемы при помощи написания патча для dhcrelay входящего в дистрибутив ISC DHCP. Стоит отметить, что в более поздних версиях сервера появилась возможность подключения его к внешним хранилищам (LDAP), однако вариант реализуемый патчем более универсален, потому что можно хранить базу DHCP практически в любой СУБД, которые поддерживаются сервером RADIUS, т.е. практически в любой из распространённых сегодня СУБД с поддержкой процедурного программирования.

Принцип работы

Обычный DHCP-relay (DHCP агент пересылки) выполняет пересылку DHCP запросов от клиентов к заданному серверу и обратно, выполняя минимальную обработку DHCP пакетов: получив широковещательный пакет от клиента запросившего конфигурационные данные, добавляет информацию об агенте пересылки (т.е. свой IP адрес), затем пересылает пакет по unicast-адресу DHCP сервера. Благодаря этому, код dhcrelay достаточно прост и позволяет без особых затруднений вносить изменения. В приведённом патче в него добавлены функции, позволяющие преобразовывать DHCP запросы от клиентов в пакеты RADIUS-Access-Request и отправлять их к RADIUS серверу, а так же производить обратные действия - преобразовывать полученные ответы RADIUS сервера в DHCP сообщения и отправлять их клиентам.

Возможности модифицированного dhcrelay

Поддерживаемые платформы: Linux, FreeBSD.
В ближайшее время будет выложен патч для dhcpd 3.0.7 обладающий гораздо бОльшим функционалом и возможностями настройки.
В патче реализованы следующие механизмы:

  1. Кэширование DHCP информации. Запрос к RADIUS серверу, а соответственно и БД, посылается только при получении DHCPDISCOVER от клиента, либо по истечении времени жизни узла DHCP кэша, что в несколько раз снижает нагрузку на сервер БД.
  2. Механизм предотвращения перегрузки сервера БД чрезмерно частыми DHCP запросами, например: флудом DHCPDISCOVER запросов, возникающим в случае образования "петли" в сегменте сети. Ограничена частота поступления запросов, как от отдельных клиентов, так и суммарная от всех клиентов. В случае превышения пороговых значений, новые DHCP запросы игнорируются.
  3. Резервирование используемых RADIUS серверов. В случае отказа основного (заданного первым) сервера, и при наличии резервного (их может быть несколько), dhcrelay переключается на резервный, переодически совершая попытки переключиться на основной сервер. Переключение резервных серверов закольцовано, т.е. в случае падения используемого резервного сервера dhcrelay переключается на следующий, при достижении последнего - переключается на первый по списку.
  4. Механизм обновления статической привязки IP адресов к MAC адресам в ARP таблице хоста, на котором запущен dhcrelay (например этот хост работает маршрутизатором в сети и осуществляет авторизацию клиентов по MAC адресу), работающий при необходимости.

Все приведённые механизмы имеют возможность настройки при запуске программы.

Поддерживаемые DHCP опции

На данный момент патч для dhcrelay может обрабатывать и передавать клиентам небольшое количество самых необходимых DHCP опций:

  1. IP адрес клиента (поле Yiadd).
  2. IP адрес агента пересылки (поле Giaddr).
  3. IP адреса DNS серверов.
  4. Шлюз по умолчанию.
  5. Время в течение которого разрешено использовать набор конфигурационных данных.
  6. Маска подсети клиента.
  7. Идентификатор сервера - основной IP адрес DHCP сервера.
  8. Имя домена (доменный суффикс) клиента.
  9. Renewing Time - время спустя которое DHCP клиент пытается продлить срок действия конфигурационного набора на сервере который выдал этот набор данных. Обычно равняется 0.5 времени аренды.
  10. Rebinding Time - время спустя которое клиент пытается продлить аренду набора данных на любом DHCP сервере. Обычно равняется 0.875 времени аренды.
  11. Безклассовая статическая маршрутизация для клиентов Microsoft (опция 249).

Все опции кроме первых 2х находятся в поле Options DHCP пакета.

О возможностях расширения списка опций смотрите ниже, в разделе "Планируемые доработки".

Необходимое программное обеспеченье

Для организации работы DHCP через модифицированный dhcrelay потребуется следующий софт:

  1. RADIUS сервер. В примерах использован FreeRADIUS
  2. Исходные коды ISC DHCP версии 3.0.5
  3. Поддерживающая процедурное программирование СУБД, с которой способен работать выбраный RADIUS сервер. В примере использована PostgreSQL.

NOTE: На данный момент патч применим только для ОС Linux.

Настройка RADIUS

Предполагается что FreeRADIUS уже установлен, если это не так, то рекомендую обратиться к руководству по его установке в вашей ОС.
В файл dictionary находящийся в конфигурационном каталоге FreeRADIUS нужно добавить новые аттрибуты:

ATTRIBUTE   Default-GW          224      ipaddr
ATTRIBUTE   You-Address         225      ipaddr
ATTRIBUTE   GIAddr              226      ipaddr
ATTRIBUTE   Lease-Time          227      integer
ATTRIBUTE   Client-MAC          228      string
ATTRIBUTE   DNS-1               229      ipaddr
ATTRIBUTE   DNS-2               230      ipaddr
ATTRIBUTE   NetMask             231      ipaddr
ATTRIBUTE   Server-ID           232      ipaddr
ATTRIBUTE   Domain-Name         233      string
ATTRIBUTE   Routes              234      string
ATTRIBUTE   If-ID               235      integer
ATTRIBUTE   No-Cache            236      string
ATTRIBUTE   Renewing-Time       237      integer
ATTRIBUTE   Rebinding-Time      238      integer

Для FreeRADIUS версий 2.X:

  1. В файле sql.conf, указать адрес сервера, тип используемой СУБД - "postgresql", имя базы данных - "dhcp", имя пользователя - "radius". Присвоить следующие значения переменным: authcheck_table = "dhcpcheck"; authreply_table = "dhcpreply_full".
  2. В файле "sites-available/default" в секции authorize раскоментировать (либо добавить) строчку содержащую директиву sql и закоментировать все остальные.
  3. В файле sql/postgresql/dialup.conf запрос group_membership_query нужно закоментировать; заменить SQL запросы authorize_check_query и authorize_reply_query на:
authorize_check_query = "SELECT id, UserName, Attribute, Value, ':=' AS Op \
    FROM ${authcheck_table} \
    WHERE id = get_id('%{SQL-User-Name}', %{NAS-Port}) \
    ORDER BY id"

authorize_reply_query = "SELECT id, client_mac, Attribute, Value, ':=' AS Op \
    FROM ${authreply_table} \
    WHERE client_mac = '%{SQL-User-Name}' AND interface_id = %{NAS-Port} \
    UNION \
    SELECT id, NULL AS client_mac, Attribute, Value, ':=' AS Op \
    FROM if_table \
    WHERE int_subnet = \
        ( \
            SELECT int_subnet FROM dhcpreply_full \
                WHERE client_mac = '%{SQL-User-Name}' \
                AND interface_id = %{NAS-Port} \
                AND attribute = 'You-Address' \
            LIMIT 1 \
        ) \
    ORDER BY id"

Для FreeRADIUS версий 1.X:

  1. В файле radiusd.conf нужно задать использование СУБД PostgreSQL при помощи строки: $INCLUDE ${confdir}/postgresql.conf (она обычно закоментированна). В секции authorize закоментировать все строчки и раскоментировать (либо добавить) строку содержащую директиву sql.
  2. В файле postgresql.conf задать адрес сервера, имя БД - "dhcp", имя пользователя - "radius".
  3. В файле postgresql.conf необходимо выполнить те же действия, что указаны в пункте 3 для FreeRADIUS 2.X.

Сборка dhcrelay

Пропатчим и соберём dhcrelay:

$ tar -xf dhcp-3.0.5.tar.gz
$ patch -p0 < radius2dhcp-3.0.5.patch
patching file dhcp-3.0.5/relay/dhcrelay.c
patching file dhcp-3.0.5/relay/rad2dhcp.h
$ cd dhcp-3.0.5
$ ./configure
$ make

Если всё прошло удачно, то в каталоге work.linux-2.2/relay/ появится исполняемый файл dhcrelay. Для удобства управления и настройки агента пересылки можно использовать bash-скрипт dhcp-relay и конфигурационный файл к нему dhcp-relay.inc. Разумеется, что перед запуском эти файлы нужно немного отредактировать - указать настройки в файле dhcp-relay.inc и расположение этого файла в самом скрипте dhcp-relay.

Создание базы данных

Для создания DHCP базы данных нужно выполнить скрипт create_dhcp_db.sql от пользователя postgresql.

$ psql -f create_dhcp_db.sql

В результате выполнения скрипта будут созданы пользователь "radius", база данных "dhcp", необходимые таблицы, индексы и представления, а также функция get_id().
get_id() вызывается сервером RADIUS из запроса authorize_check_query при обработке авторизации клиента, т.е. при попытке получить DHCP клиентом конфигурационную информацию. В качестве параметров ей передаются: строковое представление MAC адреса клиента (байты разделены двоеточием ":") запросившего конфигурационную информацию - RADIUS атрибут UserName, и IP адрес интерфейса на котором агент пересылки получил DHCP запрос от клиента, представленный как 4хбайтовое беззнаковое число - RADIUS атрибут NAS-Port. Использование функции необходимо в случае наличия пула динамических IP адресов не привязанных к конкретным MAC адресам. Если в сети все IP адреса жёстко привязаны к MAC адресам клиентов, то в запросе authorize_check_query можно использовать непосредственное сопоставление поля username MAC адресу клиента, и поля interface_id IP адресу интерфейса, на котором получен DHCP запрос.

Заполнение базы данных

Для того что бы полученная система начала работать, необходимо заполнить базу данных DHCP информацией конфигурации обслуживаемых подсетей и хостов. С подробностями обработки запросов добавления данных в БД можно ознакомиться изучив скрипты:

  • add-subnet.pl - скрипт вносящий информацию об обслуживаемой подсети.
  • add-client.pl - скрипт добавляющий IP адрес имеющий жёсткую привязку к MAC адресу конкретного DHCP клиента.
  • add-tmp-client.pl - скрипт добавляющий IP адрес не имеющий привязки к MAC адресу DHCP клиента.

Запустив их без параметров можно получить информацию о принимаемых аргументах:

$ ./add-subnet.pl
Usage: ./add-subnet.pl Default-GW GIAddr DNS-1 DNS-2 NetMask 
	Server-ID Domain-Name Lease-Time Client-Subnet
$ ./add-client.pl
Usage: ./add-client.pl Cient-IP MAC-address Server-IP Client-Subnet
$ ./add-tmp-client.pl
Usage: ./add-tmp-client.pl Cient-IP Server-IP Client-Subnet

Разумеется что данные скрипты не предназначены для постоянного использования и приведены только с целью показать пример работы с БД. Интерфейс доступа к распространённым СУБД поддерживается практически всеми средами программирования и разработки и оставляется на ваше усмотрение. Более подробная информация о использовании данных скриптов представлена ниже, в примере настройки и использования системы. Общий принцип заполнения БД при добавлении в неё информации об обслуживаемых dhcrelay хостах и подсетях приведён в разделе "Структура данных БД".

Новые параметры dhcrelay

Вся конфигурация dhcrelay задаётся из комадной строки. Если запустить программу без параметров, то будет выведен список возможных ключей. Обязательные ключи и параметры заключены в угловые скобки, необязательные - в квадратные. Кроме стандартных параметров в модифицированной патчем версии добавлено ещё несколько параметров:

  • -s <secret-string> - ключевое слово для доступа RADIUS клиента к RADIUS серверу. В данном случае dhcrelay выступает в роли клиента. Должно быть равным ключевому слову для данного RADIUS клиента в файле clients.conf (для FreeRADIUS).
  • -T <seconds> - задержка перед попыткой переключиться на основной RADIUS сервер, если до этого было совершено переключение на резервный.
  • -P <password-string> - пароль аутентифицируемого пользователя, т.е. DHCP клиента. В данном случае это поле не имеет практически ни какого смысла и потому задаётся через параметр одинаковым для всех DHCP клиентов.
  • -R <port> - порт RADIUS сервера. По умолчанию: 1812
  • -f <queries-frequency> - максимально допустимое число DHCP запросов от одного клиента в секунду. По умолчанию: 4
  • -t <seconds> - время в течение которого сохраняется узел DHCP кэша. По умолчанию: 86400 секунд (сутки).
  • -Q <queries-frequency> - максимально допустимое число запросов от всех DHCP клиентов в секунду. По умолчанию: 10
  • -u - обновлять ARP таблицу ядра при изменении MAC адреса для зерегистрированного IP адреса.
  • -h - напечатать справку по ключам добавленным патчем.

ВНИМАНИЕ: не забудьте добавить IP адрес хоста на котором будет запущен модифицированный dhcrelay в файл clients.conf сервера RADIUS!

Пример настройки и использования

В качестве примера рассмотрим маленькую тестовую сеть, все DHCP клиенты которой находятся в одном физическом (широковещательном) сегменте и разделяются на две подсети с маской 24 бита (255.255.255.0). В подсетях используются IP адреса из приватного диапазона: 10.7.7.0/24 и 10.7.70.0/24. RADIUS и PostgreSQL сервера расположены в другой физической подсети, на хосте с IP адресом 192.168.2.128. Конфигурация обоих серверов соответствует приведённой выше
Оговорюсь что связка модифицированного dhcrelay + RADIUS + PostgreSQL испытана и успешно работает в реальной сети с большим числом подсетей и количеством DHCP клиентов превышающим 20000.

В приведённых примерах предполагается что сервер PostgreSQL находится на одном хосте с выполняемыми скриптами add-subnet.pl, add-client.pl и add-tmp-client.pl, расположенными в текущем каталоге.

Сначала внесём информацию о обслуживаемых подсетях, в целях наглядности все запросы к БД выводятся на экран перед выполнением.
Добавляем подсеть 10.7.7.0/24:

$ ./add-subnet.pl 10.7.7.1 10.7.7.77 10.7.7.1 10.7.3.40 \
	255.255.255.0 10.7.7.77 local 7200 10.7.7.0 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'Rebinding-Time', '6480', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'If-ID', '168232781', 168232704) 
OK QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'Domain-Name', 'local', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'GIAddr', '10.7.7.77', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'Default-GW', '10.7.7.1', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'Lease-Time', '7200', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'Renewing-Time', '6300', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'Server-ID', '10.7.7.77', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'Routes', '0a070701080a0cac1010c0a8', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'DNS-1', '10.7.7.1', 168232704) 
OK QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'DNS-2', '10.7.3.40', 168232704) 
OK 
QUERY: INSERT INTO if_table (interface_id, attribute, value, int_subnet) 
	values(168232781, 'NetMask', '255.255.255.0', 168232704) 
OK 

Коментарии к выводу скрипта: число 168232781 в поле interface_id является десятичным представлением IP адреса 10.7.7.77. В дальнейшем, RADIUS сервер производит выборку общей для всех клиентов данной подсети конфигурационной информации из таблицы if_table, производя сопоставление поля interface_id и значения NAS-Port переданного агентом пересылки вместе с MAC адресом DHCP клиента.
Число 168232704 является десятичным представлением IP адреса подсети 10.7.7.0. Это поле необходимо в случае наличия разных IP подсетей в одном физическом сегменте (при использовании IP aliasing). Например в описаном случае. Используется в запросе authorize_reply_query.

Описание переданных скрипту параметров:

  1. Default-GW (10.7.7.1) - шлюз по умолчанию для клиентов данной подсети.
  2. GIAddr (10.7.7.77) - первичный IP адрес интерфейса на котором модифицированный dhcrelay получает DHCP запросы от клиентов данной подсети.
  3. DNS-1 (10.7.7.1) - первичный DNS сервер
  4. DNS-2 (10.7.3.40) - вторичный DNS сервер
  5. NetMask (255.255.255.0) - маска подсети для DHCP клиентов.
  6. Server-ID (10.7.7.77) - идентификатор DHCP сервера. Обычно это поле содержит основной IP адрес DHCP сервера, а не агента пересылки, но в данном случае логичней указать IP адрес агента пересылки.
  7. Domain-Name (local) - доменый суффикс DHCP клиентов данной подсети.
  8. Lease-Time (7200) - время на которое клиенту выдаётся в аренду набор конфигурационных данных.
  9. Client-Subnet (10.7.7.0) - IP адрес данной подсети.

Для подсети 10.7.70.0/24:

$ ./add-subnet.pl 10.7.70.1 10.7.7.77 10.7.7.1 10.7.3.40 \
	255.255.255.0 10.7.7.77 local 7200 10.7.70.0

В данном случае вывод скрипта будет практически таким же как и при добавлении информации о подсети 10.7.7.0/24 за исключением параметров в которых упоминается IP адрес подсети 10.7.70.0/24

Добавим IP адрес имеющий жёсткую привязку к MAC адресу DHCP клиента:

$ ./add-client.pl 10.7.7.10 00:03:ff:2c:52:90 10.7.7.77 10.7.7.0 
QUERY: INSERT INTO dhcp_reply (interface_id, client_mac, 
		attribute, value, start_lease, int_subnet) 
	values(168232781, '00:03:ff:2c:52:90', 
			'You-Address', '10.7.7.10', null, 168232704); 
OK 
QUERY: INSERT INTO dhcp_reply (interface_id, client_mac, 
		attribute, value, start_lease, int_subnet) 
	values(168232781, '00:03:ff:2c:52:90', 
			'Client-MAC', '00:03:ff:2c:52:90', null, 168232704); 
OK

Данный IP адрес может быть выдан только клиенту имеющему указанный MAC адрес и пославшему запрос из указанной подсети. Определение подсети из которой DHCP клиент отправил запрос осуществляется RADIUS сервером через параметр NAS-Port Radius-Access-Request пакета, в котором агент пересылки указывает IP адрес интерфейса на котором получен DHCP запрос.
Описание переданных скрипту параметров:

  1. Cient-IP (10.7.7.10) - IP адрес выдаваемый DHCP клиенту.
  2. MAC-address (00:03:ff:2c:52:90) - MAC адрес к которому привязывается данный IP адрес.
  3. Server-IP (10.7.7.77) - первичный IP адрес интерфейса прослушиваемого dhcrelay.
  4. Client-Subnet (10.7.7.0) - IP адрес подсети DHCP клиента.

Добавим 2 IP адреса не имеющих жёсткой привязки к MAC адресу для подсети 10.7.70.0:

$ ./add-tmp-client.pl 10.7.70.10 10.7.7.77 10.7.70.0 
QUERY: INSERT INTO assigned_tmp_ips (interface_id, client_mac, 
		attribute, value, start_lease, int_subnet) 
	values (168232781, null, 'You-Address', '10.7.70.10', null, 168248832); 
OK 
$ ./add-tmp-client.pl 10.7.70.11 10.7.7.77 10.7.70.0 
QUERY: INSERT INTO assigned_tmp_ips (interface_id, client_mac, 
		attribute, value, start_lease, int_subnet) 
	values (168232781, null, 'You-Address', '10.7.70.11', null, 168248832); 
OK 

Эти адреса будут выдаваться любым DHCP клиентам на время заданное значением Lease-Time в информации о данной подсети, если БД не содержит IP адресов имеющих привязку к MAC адресу клиента запросившего конфигурацию.
Описание переданных скрипту параметров:

  1. Cient-IP (10.7.70.10) - IP адрес выдаваемый DHCP клиенту.
  2. Server-IP (10.7.7.77) - первичный IP адрес интерфейса прослушиваемого dhcrelay
  3. Client-Subnet (10.7.70.0) - IP адрес подсети DHCP клиента.

Минимально необходимая для работы системы информация внесена в БД, и если сервера PostgreSQL и RADIUS запущены, то - можно запускать dhcrelay и проверять его работу:

# dhcrelay -u -i eth1 -s dhcrelay -P dhcpuser -T 900 -d 192.168.2.128 
Коментарии к параметрам:
  • -u - при смене MAC адреса, или добавлении нового DHCP клиента с привязкой IP адреса к MAC будет произведено обновление ARP таблицы ОС. Аналогичное действию команды arp -s ip_addr mac_addr
  • -i eth1 - интерфейс прослушиваемый dhcrelay.
  • -s dhcrelay - пароль (shared secret) используемый dhcrelay при авторизации на RADIUS сервере.
  • -P dhcpuser - пароль аутентифицируемого через RADIUS пользователя. В RADIUS запросах посылаемых dhcrelay одинаков для всех DHCP клиентов.
  • -T 900 - таймаут спустя который производится попытка переключиться на основной сервер, если до этого было "падение" основного, и произошло переключение на резеврный.
  • -d - стандартный для dhcrelay ключ указывающий необходимость работы в режиме отладки, не переключаясь в режим демона.
  • 192.168.2.128 - IP адрес RADIUS сервера. Можно указать несколько адресов или доменных имён. В таком случае первый в списке будет являться основным, остальные резервными. В случае отказа основного сервера происходит переключение на следующий по списку резервный.

Ключ -d задан для наглядности - результаты обработки запросов DHCP клиента можно просмотреть в консоли не читая файла логов.

Запустим в тестовой сети 3х DHCP клиентов: первого зарегистрированного в нашей БД (MAC: 00:03:ff:2c:52:90) и 2х не зарегистрированных и посмотрим на вывод dhcrelay в консоли:

Convert DHCPDISCOVER 00:03:ff:2c:52:90/eth1 to RADIUS and forwarded to 192.168.2.128
Convert RADIUS-reply for 00:03:ff:2c:52:90 in DHCPOFFER and forwarded to 10.7.7.10
Received DHCPREQUEST (00:03:ff:2c:52:90/eth1) found in dhcrelay cache.
Creating DHCPACK for 00:03:ff:2c:52:90 and forwarded to 10.7.7.10

Первые 2 строчки достаточно очевидны. В 3й и 4й указывается, что DHCP информация для полученного DHCPREQUEST от клиента с адресом 00:03:ff:2c:52:90 на интерфейсе eth1, найдена в кэше dhcrelay и ответ будет сгенерирован из кэша. В дальнейшем, все ответы на запросы DHCPREQUEST от данного клиента будут создаваться из кэша пока не истечёт TTL узла кэша (по умолчанию - одни сутки), либо пока клиент не инициализирует цикл получения IP адреса с самого начала, т.е. с посылки запроса DHCPDISCOVER. На практике это выливается в существенное (в несколько раз) уменьшение загрузки сети, и главное - сервера базы данных, т.к. клиент (при условии что он не перезапускал процесс инициализации сети) в течение суток может несколько раз послать запрос DHCPREQUEST - в случае истечения времени аренды IP адреса. При этом запрос к БД будет отправлен только 1 раз - при получении DHCPDISCOVER, а затем - раз в сутки при истечении TTL узла кэша. При желании вы можете задать большее значение TTL и соответственно - уменьшить загрузку сервера БД.
Теперь попробуем получить IP адреса для 2х не зарегистрированных клиентов:

Convert DHCPDISCOVER 00:ef:9c:d5:67:a6/eth1 to RADIUS and forwarded to 192.168.2.128
Convert RADIUS-reply for 00:ef:9c:d5:67:a6 in DHCPOFFER and forwarded to 10.7.70.10
Convert DHCPREQUEST 00:ef:9c:d5:67:a6/eth1 to RADIUS and forwarded to 192.168.2.128
Convert RADIUS-reply for 00:ef:9c:d5:67:a6 in DHCPACK and forwarded to 10.7.70.10
Convert DHCPDISCOVER 00:e9:20:a3:26:4e/eth1 to RADIUS and forwarded to 192.168.2.128
Convert RADIUS-reply for 00:e9:20:a3:26:4e in DHCPOFFER and forwarded to 10.7.70.11
Convert DHCPREQUEST 00:e9:20:a3:26:4e/eth1 to RADIUS and forwarded to 192.168.2.128
Convert RADIUS-reply for 00:e9:20:a3:26:4e in DHCPACK and forwarded to 10.7.70.11

Клиентами были получены 2 IP адреса - 10.7.70.10 и 10.7.70.11. Стоит обратить внимание на отличие в поведении dhcrelay при получении пакета DHCPREQUEST: если MAC адрес клиента не зарегистрирован в БД, то кэширование информации DHCP не производится. Это связано с тем, что любой IP адрес не имеющий привязки к MAC адресу может быть выдан любому DHCP клиенту по истечении срока аренды. Если кэшировать информацию о незарегистрированных DHCP клиентах в dhcrelay то может сложиться следующая ситуация:
Не зарегистрированный клиент сделал запрос и получил некоторый IP-адрес со сроком аренды 2 часа (например), если закэшировать этот запрос в dhcrelay, то спустя почти 2 часа (в нашем случае Renewing Time задано равным 0.875 от времени аренды - Lease Time = 7200 секунд) при посылке клиентом пакета DHCPREQUEST для продления срока аренды адреса - он получит ответ из кэша, без отправки RADIUS запроса. Сервер БД не обновит информацию о том, что данный IP адрес продолжает использваться тем же клиентом. Как следтвие спустя 2 часа с момента начала аренды сервер БД сочтёт что данный IP адрес свободен и выдаст его следующему не зарегистрированному клиенту в той же подсети. В итоге это приведёт к конфликту IP адресов в сети.
Если же не кэшировать информацию о незарегистрированных клиентах, то при каждом DHCPREQUEST будет производиться посылка RADIUS запроса на сервер и как следствие - в БД будет производиться обновление информации о том что данныё IP адрес выдан в аренду и всё ещё используется. Это гарантирует невозможность выдачи данного IP адреса какому-либо другому клиенту.

Если в ходе проверки установлено что всё работает так как должно, то можно в дальнейшем, для удобства использования dhcrelay применять sh-скрипт dhcp-relay. Конфигурационная информация указывается в файле dhcp-relay.inc. Отредактируйте оба эти файла нужным образом: в dhcp-relay задайте правильный путь к dhcp-relay.inc, а в dhcp-relay.inc установите подходящие вам значения переменных.
Скрипт dhcp-relay имеет следующие параметры:

  • start - запуск dhcrelay
  • stop - остановка dhcrelay
  • restart - перезапуск dhcrelay
  • stat - выдача статистической информации в системный лог. Выполняется при получении dhcrelay сигнала с номером 64 (kill -64 dhcrelay). Напомню - в любом руководстве по функции signal() указано, что желательно воздержаться от выполнения операций ввода/вывода в процессе обработки сигнала. Данная функция была введена с целью отладки, но потом неоднократно применялась на практике без каких-либо побочных эффектов.
  • set_pri_serv - принудительно переключает dhcrelay на первичный сервер, т.е. на сервер заданый первым в списке серверов командной строки. Выполняется при получении dhcrelay сигнала с номером 63 (killall -63 dhcrelay).
  • set_next_serv - устанавливает текущим активным RADIUS сервер следующий в списке серверов полученном из командной строки. Если текущий сервер последний - активным устанавливается первый в списке. Смена сервера выполняется при получении сигнала номер 62 (kill -62 dhcrelay), либо автоматически в случае "падения" текущего сервера.

ВАЖНО! dhcrelay должен слушать не только интерфейс на котором приходят DHCP запросы, но и тот интерфейс, на который приходят RADIUS ответы. В приведённом выше примере это один и тот же физический интерфейс. Если же ответы RADIUS сервера приходят на другой интерфейс, то он так же должен быть добавлен стартовую строку. dhcrelay может слушать сразу несколько физических интерфейсов, каждый интерфейс должен предваряться ключём -i например: -i eth0 -i eth1 -i eth3 и т.д.

Структура данных БД

Для добавления DHCP клента с привязкой IP адреса к MAC адресу в таблицу dhcp_reply должны быть добавлены две записи определяемые следующими запросами:

INSERT INTO dhcp_reply 
	(interface_id, client_mac, attribute, value, start_lease, int_subnet)
	values	
	(INTERFACE_ID, CLIENT_MAC, 'You-Address', CLIENT_IP, null, CLIENT_SUBNET);
INSERT INTO dhcp_reply 
	(interface_id, client_mac, attribute, value, start_lease, int_subnet)
	values
	(INTERFACE_ID, CLIENT_MAC, 'Client-MAC', CLIENT_MAC, null, CLIENT_SUBNET);

Где:

  • INTERFACE_ID - представление IP адреса интерфейса на котором может быть получен DHCP запрос от данного клиента в виде 4хбайтного беззнакового числа (тип integer).
  • CLIENT_MAC - MAC адрес DHCP клиента (тип character varying(20) NOT NULL).
  • CLIENT_IP - IP адрес клиента (тип character varying(1000)).
  • CLIENT_SUBNET - представление IP адреса подсети клиента в виде 4хбайтного беззнакового числа (тип integer). Подсеть клиента может отличаться от подсети IP адреса интерфейса на котором может быть получен запрос если используется IP aliasing.

Назначение первого запроса на мой взгляд очевидно. Второй необходим т.к. в ответном пакете RADIUS нужно передать обратно MAC адрес DHCP клиента. Конечно можно обойтись и без него при помощи создания дополнительного представления (VIEW) в базе данных.

Для добавление DHCP клиента без привязки IP адреса к конкретному MAC адресу в таблицу assigned_tmp_ips нужно добавить одну запись:

INSERT INTO assigned_tmp_ips
	(interface_id, client_mac, attribute, value, start_lease, int_subnet)
	values  
	(INTERFACE_ID, null, 'You-Address', CLIENT_IP, null, CLIENT_SUBNET);

Выполнение второго запроса в данном случае не нужно, т.к. таблица asigned_tmp_ips динамически обновляется функцией get_id (функция создаётся в ходе выполнения скрипта create_dhcp_db.sql) и данный запрос выполняется внутри функции при получении запроса от DHCP клиента для которого не имеется IP адреса жёстко привязанного к его MAC адресу. Тип и назначение полей таблицы assigned_tmp_ips точно такие же как и в таблице dhcp_reply.

Для добавления информации о обслуживаемой подсети нужно внести 12 записей в таблицу if_table - по числу параметров описывающих конфигурацию подсети. Общий вид запроса:

INSERT INTO if_table 
	(interface_id, attribute, value, int_subnet)
	values
	(INTERFACE_ID, ATTRIBUTE_NAME, ATTRIBUTE_VALUE, SUBNET)

Где:

  • INTERFACE_ID - представление первичного IP адреса интерфейса прослушиваемого dhcrelay в данной подсети в виде 4хбайтного беззнакового числа .
  • ATTRIBUTE_NAME - имя RADIUS атрибута, оно же определяет тип DHCP опции значение которой указано в следующем поле.
  • ATTRIBUTE_VALUE - значение RADIUS атрибута и соответственно DHCP опции.
  • SUBNET - представление IP адреса подсети для один из параметров которой описывает данная запись в виде 4хбайтного беззнакового числа .

Атрибуты описывающие подсеть:

  • Default-GW - строковое представление IP адреса шлюза по умолчанию для данной подсети.
  • GIAddr - адрес агента пересылки, т.е. интерфейса на котором dhcrelay получает DHCP запросы от клиентов в данной подсети.
  • Lease-Time - время на которое DHCP клиентам выдаётся в аренду набор конфигурационных данных. Указывается в секундах.
  • DNS-1 - первичный DNS сервер.
  • DNS-2 - вторичный DNS сервер.
  • NetMask - строковое представление маски подсети.
  • Server-ID - идентификатор сервера. Обычно является основным IP адресом сервера.
  • Domain-Name - имя домена подсети.
  • Routes - статические безклассовые маршруты. DHCP опция с кодом 249 - используется Windows клиентами. Подробно формат этой опции описан в файле relay/dhcrelay.c после применения патча - коментарий к функции translate_249. Алгоритм создания строки-значения для данного атрибута можно увидеть в скрипте add-subnet.pl - функция option_249.
  • If-ID - IP адрес интерфейса на котором dhcrelay получает запросы от DHCP клиента в виде 4хбайтного беззнакового числа.
  • Renewing-Time - значение DHCP опции Renewing Time.
  • Rebinding-Time - значение DHCP опции Rebinding Time.

RADIUS типы этих атрибутов были описаны выше, в разделе Настройка RADIUS.

Сообщения об ошибках

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

  • WARN: Invalid autentificator in RADIUS. BOOTREPLY aborted. - обычно возникает в случае дублирования RADIUS запросов посылаемых dhcrelay. В случае большой активности DHCP клиентов данные сообщения могут появляються достаточно часто, что свидетельствует о высокой степени загруженности RADIUS сервера (или, скорее всего - сервера БД). Данные сообщения носят информационный характер и в случае не слишком большой частоты появления их можно игнорировать.
  • Сообщения свидетельствующие о наличии DHCP флуда в сегменте:
    ERROR: Exceed maximum DHCP queries per second - 350/sec (30/sec)
    ERROR: Drop DHCPDISCOVER from 00:8f:d9:a0:6d:48/eth0 !
    INFO: Can't processed DHCP packet.

    Возникает при превышении порогового значения максимально допустимого числа запросов в секунду (в приведённом случае - 30) от всех DHCP клиентов. Следствием этого будет блокировка преобразования DHCP запросов в RADIUS запросы во избежание перегрузки сервера БД. Блокироваными окажутся запросы от всех DHCP клиентов обслуживаемых данным процессом dhcrelay. Сообщения начнут передаваться на RADIUS сервер как только частота их поступления снизится до максимально допустимой.
    ERROR: Exceed maximum DHCP queries per second (163.2/sec) for host 00:2c:fa:5f:e5:40/eth0. Maximum: 4/sec. Drop request.
    INFO: Can't processed DHCP packet.

    Возникает при превышении максимально допустимого числа запросов в секунду от одного клиента. Приводит к блокировке преобразования сообщений только для данного клиента. Запросы от остальных DHCP клиентов будут обрабатываться в штатном режиме.

Планируемые доработки

  1. Добавление возможности использования конфигурационного файла для расширения списка DHCP опций обрабатываемых dhcrelay.
  2. Увеличение максимально допустимой длины RADIUS Shared secret. На данный момент - 16 символов.

Все возникшие пожелания и предложения можно (или даже нужно) сообщить в гостевую или на и статья будет скорректированна, если это будет уместно.




Вернуться в "Проекты"