DHCPD 2: различия между версиями
Sirmax (обсуждение | вклад) (Новая страница: «=DHCPD= Заметки по настройке isc dhcpd») |
Sirmax (обсуждение | вклад) |
||
(не показано 15 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
+ | [[Категория:DHCP]] |
||
+ | [[Категория:DHCP_Option_82]] |
||
+ | [[Категория:Switch]] |
||
+ | |||
=DHCPD= |
=DHCPD= |
||
Заметки по настройке isc dhcpd |
Заметки по настройке isc dhcpd |
||
+ | |||
+ | =Скрипт запуска (тестовый)= |
||
+ | Запуск в нейспейсе |
||
+ | <PRE> |
||
+ | #!/bin/bash. |
||
+ | |||
+ | rm ./dhcpd.leases2 ./dhcpd.leases2~ |
||
+ | touch ./dhcpd.leases2 |
||
+ | |||
+ | |||
+ | ip netns exec DHCP /usr/sbin/dhcpd \ |
||
+ | -cf ./dhcpd.conf \ |
||
+ | -lf ./dhcpd.leases2 \ |
||
+ | -pf ./dhcpd.pid \ |
||
+ | -f \ |
||
+ | -d \ |
||
+ | -tf ./trace-output-file \ |
||
+ | dhcp_to_main_ns |
||
+ | </PRE> |
||
+ | |||
+ | =Примеры работы с dhcp-eval= |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | * https://forum.lissyara.su/soft-f3/dhcpd-conf-funkciya-execute-t45488.html |
||
+ | |||
+ | =Прежде чем начать - логгирование= |
||
+ | Уточнить! |
||
+ | Странно но внятный лог можно получить только при выдаче адреса - те если сервер адрес не выдал то (почему?!) конструкции вида |
||
+ | <PRE> |
||
+ | log(info, concat("Client ",binary-to-ascii(16, 8, ":", substring(hardware, 0, 4)))); |
||
+ | </PRE> |
||
+ | Не срабатывают |
||
+ | |||
+ | По этой причине задача номер один при отладке сервера - сделать конфиг который всегда выдает адреса (но не обязательно маршрутизируемые) что бы видеть что прислал клиент, что добавил свитч и/или релей и тд. |
||
+ | |||
+ | <BR> |
||
+ | Мой минимальный конфиг такой |
||
+ | <PRE> |
||
+ | ddns-update-style none; |
||
+ | default-lease-time 36000; |
||
+ | max-lease-time 72000; |
||
+ | authoritative; |
||
+ | log-facility local6; |
||
+ | |||
+ | log(info, |
||
+ | concat( |
||
+ | "log start\n", |
||
+ | "-->", binary-to-ascii(10, 8, ".", packet(0, 1000)), |
||
+ | "\n", |
||
+ | "-->", binary-to-ascii(10, 8, ".", packet(0, 1000)), |
||
+ | "\n", |
||
+ | suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,0,1))),2), ":", |
||
+ | suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":", |
||
+ | suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":", |
||
+ | suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":", |
||
+ | suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":", |
||
+ | suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":", |
||
+ | suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2), |
||
+ | "\n", |
||
+ | "log end\n" |
||
+ | |||
+ | ) |
||
+ | ); |
||
+ | |||
+ | |||
+ | class "any" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 0, 1)) = "1"); } |
||
+ | #class "b8" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 1, 1)) = "b8"); } |
||
+ | class "b9" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 1, 1)) = "b9"); } |
||
+ | |||
+ | # b8:27:eb:24:8d:f2 |
||
+ | |||
+ | class "never_match" { match if ( binary-to-ascii(10, 16, "", substring(option agent.circuit-id, 2, 2)) = "4096" );} |
||
+ | |||
+ | |||
+ | |||
+ | shared-network "networks" |
||
+ | { |
||
+ | subnet 172.31.99.0 netmask 255.255.255.0 { } |
||
+ | subnet 10.32.99.0 netmask 255.255.255.0 { } |
||
+ | subnet 10.30.0.1 netmask 255.255.255.255 { } |
||
+ | |||
+ | |||
+ | |||
+ | subnet 10.5.0.0 netmask 255.255.255.0 { |
||
+ | option subnet-mask 255.255.255.0; |
||
+ | option broadcast-address 10.5.0.255; |
||
+ | option routers 10.4.0.1; |
||
+ | pool { |
||
+ | range 10.5.0.2 10.5.0.253; |
||
+ | default-lease-time 10; |
||
+ | max-lease-time 10; |
||
+ | deny members of "never_match"; |
||
+ | deny members of "b9"; |
||
+ | allow members of "any"; |
||
+ | |||
+ | } |
||
+ | } |
||
+ | } |
||
+ | </PRE> |
||
+ | |||
+ | Тут определены 3 класса - any, под который должен попадать любой запрос (1 в нулевом байте означает тип ether) |
||
+ | <PRE> |
||
+ | class "any" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 0, 1)) = "1"); } |
||
+ | </PRE> |
||
+ | Класс для клиентов с b9 в первом байте МАК-адреса |
||
+ | <PRE> |
||
+ | class "b9" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 1, 1)) = "b9"); } |
||
+ | </PRE> |
||
+ | Класс который никогда не сработает (VLAN ID = 4096) - он нужен при автоненерации в качестве заглушки для случая если в какой-то момент нет ни одного клиента в сабнете |
||
+ | <PRE> |
||
+ | class "never_match" { match if ( binary-to-ascii(10, 16, "", substring(option agent.circuit-id, 2, 2)) = "4096" );} |
||
+ | </PRE> |
||
+ | |||
+ | Далее |
||
+ | <PRE> |
||
+ | deny members of "never_match"; |
||
+ | deny members of "b9"; |
||
+ | allow members of "any"; |
||
+ | </PRE> |
||
+ | * Явно запретить известного клиента b9 |
||
+ | * Явно разрешить всех |
||
+ | |||
+ | =Порядок выдачи адресов= |
||
+ | * Если есть ТОЛЬКО ALLOW то адреса получат только клиенты которые соответвуюют правилам (а остальные очевидно нет) |
||
+ | * Если есть ТОЛЬКО DENY то получат только те кто не попадет ни под одно запрещающее условие (т е в конеце неявный permit) |
||
+ | В примере выше секция "для всех" работает и в такой конфигурации |
||
+ | <PRE> |
||
+ | pool { |
||
+ | range 10.5.0.2 10.5.0.253; |
||
+ | default-lease-time 10; |
||
+ | max-lease-time 10; |
||
+ | deny members of "never_match"; |
||
+ | } |
||
+ | </PRE> |
||
+ | |||
+ | * Если есть И ALLOW и DENY правила то получат только те клиенты которые есть в ALLOW но нет в DENY |
||
+ | <BR> |
||
+ | Последний пункт требует пояснений |
||
+ | <BR> |
||
+ | Конструкция где класс any соответвует всем ether клиентам, а b8 - клиентам с маком начинающимся на b8 говорит "все кроме b8" - хотя b8 так же попадает под класс "все клиенты" |
||
+ | Другими словами проверяются все DENY правила и если сработало хоть одно то клиент не получит адрес из пула |
||
+ | <PRE> |
||
+ | allow members of "any"; |
||
+ | deny members of "b8"; |
||
+ | </PRE> |
||
+ | ==Порядок выдачи адресов для клиентов попадающих под несколько условий== |
||
+ | Случачай когда клиент попадает по всем условиям в несколько пулов |
||
+ | <BR> |
||
+ | Пример |
||
+ | |||
+ | <PRE> |
||
+ | subnet 10.3.0.0 netmask 255.255.255.0 { |
||
+ | option subnet-mask 255.255.255.0; |
||
+ | option broadcast-address 10.4.0.255; |
||
+ | option routers 10.3.0.1; |
||
+ | pool { |
||
+ | range 10.3.0.2 10.3.0.253; |
||
+ | default-lease-time 10; |
||
+ | max-lease-time 10; |
||
+ | deny members of "never_match"; |
||
+ | allow members of "b8"; |
||
+ | } |
||
+ | } |
||
+ | |||
+ | |||
+ | subnet 10.2.0.0 netmask 255.255.255.0 { |
||
+ | option subnet-mask 255.255.255.0; |
||
+ | option broadcast-address 10.4.0.255; |
||
+ | option routers 10.2.0.1; |
||
+ | pool { |
||
+ | range 10.2.0.2 10.2.0.253; |
||
+ | default-lease-time 10; |
||
+ | max-lease-time 10; |
||
+ | deny members of "never_match"; |
||
+ | allow members of "any"; |
||
+ | } |
||
+ | } |
||
+ | </PRE> |
||
+ | В примере выше клиент попадает под оба пула - но получит адрес ИЗ ПЕРВОГО |
||
+ | <BR> |
||
+ | Если в конфиге поменять пулы местами то клиент опять получит адрес из ПЕРВОГО - того что выше в конфиге, (но подробное тестирование не проводилось и я б рекомендовал не закладываться на такое поведение - а явно оставлять только один возможный вариант) |
||
+ | |||
+ | =Порядок выдачи адресов= |
||
+ | Задача |
||
+ | <BR> |
||
+ | Есть 4 группы клиентов |
||
+ | * известные с положительным балансом (с правильным option 82 и условием в базе) |
||
+ | * известные с отрицательным балансом (с правильным option 82 и условием в базе) |
||
+ | * неизвестные (нет в базе но есть opt82 - по сути только включенные) |
||
+ | * неправильные (нет opt82 или он не соответвует ожидаемому - по сути, ошибка настройки сети) |
||
+ | |||
+ | |||
+ | |||
+ | = |
||
+ | # RFC 3046 DHCP Relay Agent Information Option logging |
||
+ | # author: pol |
||
+ | if exists agent.remote-id and exists agent.circuit-id { |
||
+ | log(info,concat("DHCPCIRCUIT for lease of ",binary-to-ascii(10,8,".",leased-address), |
||
+ | " is connected to interface ",binary-to-ascii(10,8,"/",suffix(option agent.circuit-id,2)), |
||
+ | ", VLAN ",binary-to-ascii(10,16,"",substring(option agent.circuit-id,2,2)), |
||
+ | " on switch ",binary-to-ascii(16,8,":",substring(option agent.remote-id,2,6)) |
||
+ | )); |
||
+ | log(info,concat("DHCPOPT82 for lease of ",binary-to-ascii(10,8,".",leased-address), |
||
+ | " raw option-82 info is CID: ",binary-to-ascii(10,8,".",option agent.circuit-id), |
||
+ | " AID: ",binary-to-ascii(16,8,".",option agent.remote-id) |
||
+ | )); |
||
+ | } elsif exists agent.remote-id { |
||
+ | log(info,concat("DHCPAGENT for lease of ",binary-to-ascii(10,8,".",leased-address), |
||
+ | " on agent ",binary-to-ascii(16,8,":",substring(option agent.remote-id, 2, 6)) |
||
+ | )); |
||
+ | } elsif exists agent.circuit-id { |
||
+ | log(info,concat("DHCPCIRCUITID on ", |
||
+ | suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,1,1))),2),":", |
||
+ | suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,2,1))),2),":", |
||
+ | suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,3,1))),2),":", |
||
+ | suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,4,1))),2),":", |
||
+ | suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,5,1))),2),":", |
||
+ | suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,6,1))),2), |
||
+ | " to ",binary-to-ascii(10,8,".",leased-address), |
||
+ | " via ",option agent.circuit-id |
||
+ | )); |
||
+ | } |
||
+ | |||
+ | =Ссылки= |
||
+ | * https://serverfault.com/questions/778719/dhcpd-class-match-on-hostname-or-mac-address |
Текущая версия на 14:39, 5 апреля 2021
DHCPD
Заметки по настройке isc dhcpd
Скрипт запуска (тестовый)
Запуск в нейспейсе
#!/bin/bash. rm ./dhcpd.leases2 ./dhcpd.leases2~ touch ./dhcpd.leases2 ip netns exec DHCP /usr/sbin/dhcpd \ -cf ./dhcpd.conf \ -lf ./dhcpd.leases2 \ -pf ./dhcpd.pid \ -f \ -d \ -tf ./trace-output-file \ dhcp_to_main_ns
Примеры работы с dhcp-eval
Прежде чем начать - логгирование
Уточнить! Странно но внятный лог можно получить только при выдаче адреса - те если сервер адрес не выдал то (почему?!) конструкции вида
log(info, concat("Client ",binary-to-ascii(16, 8, ":", substring(hardware, 0, 4))));
Не срабатывают
По этой причине задача номер один при отладке сервера - сделать конфиг который всегда выдает адреса (но не обязательно маршрутизируемые) что бы видеть что прислал клиент, что добавил свитч и/или релей и тд.
Мой минимальный конфиг такой
ddns-update-style none; default-lease-time 36000; max-lease-time 72000; authoritative; log-facility local6; log(info, concat( "log start\n", "-->", binary-to-ascii(10, 8, ".", packet(0, 1000)), "\n", "-->", binary-to-ascii(10, 8, ".", packet(0, 1000)), "\n", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,0,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":", suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2), "\n", "log end\n" ) ); class "any" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 0, 1)) = "1"); } #class "b8" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 1, 1)) = "b8"); } class "b9" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 1, 1)) = "b9"); } # b8:27:eb:24:8d:f2 class "never_match" { match if ( binary-to-ascii(10, 16, "", substring(option agent.circuit-id, 2, 2)) = "4096" );} shared-network "networks" { subnet 172.31.99.0 netmask 255.255.255.0 { } subnet 10.32.99.0 netmask 255.255.255.0 { } subnet 10.30.0.1 netmask 255.255.255.255 { } subnet 10.5.0.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 10.5.0.255; option routers 10.4.0.1; pool { range 10.5.0.2 10.5.0.253; default-lease-time 10; max-lease-time 10; deny members of "never_match"; deny members of "b9"; allow members of "any"; } } }
Тут определены 3 класса - any, под который должен попадать любой запрос (1 в нулевом байте означает тип ether)
class "any" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 0, 1)) = "1"); }
Класс для клиентов с b9 в первом байте МАК-адреса
class "b9" { match if (binary-to-ascii(16, 8, ":", substring(hardware, 1, 1)) = "b9"); }
Класс который никогда не сработает (VLAN ID = 4096) - он нужен при автоненерации в качестве заглушки для случая если в какой-то момент нет ни одного клиента в сабнете
class "never_match" { match if ( binary-to-ascii(10, 16, "", substring(option agent.circuit-id, 2, 2)) = "4096" );}
Далее
deny members of "never_match"; deny members of "b9"; allow members of "any";
- Явно запретить известного клиента b9
- Явно разрешить всех
Порядок выдачи адресов
- Если есть ТОЛЬКО ALLOW то адреса получат только клиенты которые соответвуюют правилам (а остальные очевидно нет)
- Если есть ТОЛЬКО DENY то получат только те кто не попадет ни под одно запрещающее условие (т е в конеце неявный permit)
В примере выше секция "для всех" работает и в такой конфигурации
pool { range 10.5.0.2 10.5.0.253; default-lease-time 10; max-lease-time 10; deny members of "never_match"; }
- Если есть И ALLOW и DENY правила то получат только те клиенты которые есть в ALLOW но нет в DENY
Последний пункт требует пояснений
Конструкция где класс any соответвует всем ether клиентам, а b8 - клиентам с маком начинающимся на b8 говорит "все кроме b8" - хотя b8 так же попадает под класс "все клиенты"
Другими словами проверяются все DENY правила и если сработало хоть одно то клиент не получит адрес из пула
allow members of "any"; deny members of "b8";
Порядок выдачи адресов для клиентов попадающих под несколько условий
Случачай когда клиент попадает по всем условиям в несколько пулов
Пример
subnet 10.3.0.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 10.4.0.255; option routers 10.3.0.1; pool { range 10.3.0.2 10.3.0.253; default-lease-time 10; max-lease-time 10; deny members of "never_match"; allow members of "b8"; } } subnet 10.2.0.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 10.4.0.255; option routers 10.2.0.1; pool { range 10.2.0.2 10.2.0.253; default-lease-time 10; max-lease-time 10; deny members of "never_match"; allow members of "any"; } }
В примере выше клиент попадает под оба пула - но получит адрес ИЗ ПЕРВОГО
Если в конфиге поменять пулы местами то клиент опять получит адрес из ПЕРВОГО - того что выше в конфиге, (но подробное тестирование не проводилось и я б рекомендовал не закладываться на такое поведение - а явно оставлять только один возможный вариант)
Порядок выдачи адресов
Задача
Есть 4 группы клиентов
- известные с положительным балансом (с правильным option 82 и условием в базе)
- известные с отрицательным балансом (с правильным option 82 и условием в базе)
- неизвестные (нет в базе но есть opt82 - по сути только включенные)
- неправильные (нет opt82 или он не соответвует ожидаемому - по сути, ошибка настройки сети)
=
- RFC 3046 DHCP Relay Agent Information Option logging
- author: pol
if exists agent.remote-id and exists agent.circuit-id {
log(info,concat("DHCPCIRCUIT for lease of ",binary-to-ascii(10,8,".",leased-address), " is connected to interface ",binary-to-ascii(10,8,"/",suffix(option agent.circuit-id,2)), ", VLAN ",binary-to-ascii(10,16,"",substring(option agent.circuit-id,2,2)), " on switch ",binary-to-ascii(16,8,":",substring(option agent.remote-id,2,6)) )); log(info,concat("DHCPOPT82 for lease of ",binary-to-ascii(10,8,".",leased-address), " raw option-82 info is CID: ",binary-to-ascii(10,8,".",option agent.circuit-id), " AID: ",binary-to-ascii(16,8,".",option agent.remote-id) ));
} elsif exists agent.remote-id {
log(info,concat("DHCPAGENT for lease of ",binary-to-ascii(10,8,".",leased-address), " on agent ",binary-to-ascii(16,8,":",substring(option agent.remote-id, 2, 6)) ));
} elsif exists agent.circuit-id {
log(info,concat("DHCPCIRCUITID on ", suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,1,1))),2),":", suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,2,1))),2),":", suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,3,1))),2),":", suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,4,1))),2),":", suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,5,1))),2),":", suffix(concat("0",binary-to-ascii(16,8,"",substring(hardware,6,1))),2), " to ",binary-to-ascii(10,8,".",leased-address), " via ",option agent.circuit-id ));
}