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

FreeRADIUS as DHCP Server Set Static Routes trouble

Использую FreeRADIUS как DHCP сервер.

Хочу выдать клиенту статические маршруты через опцию 249

Пробовал по разному, но результат отрицательный:

 

Sending DHCP-Ack of id 592183de from 172.16.3.1:67 to 172.16.28.1:67
       DHCP-Opcode = Server-Message
       DHCP-Hardware-Type = Ethernet
       DHCP-Hardware-Address-Length = 6
       DHCP-Hop-Count = 0
       DHCP-Transaction-Id = 1495368670
       DHCP-Number-of-Seconds = 0
       DHCP-Flags = 0
       DHCP-Client-IP-Address = 0.0.0.0
       DHCP-Your-IP-Address = 192.168.28.161
       DHCP-Server-IP-Address = 192.168.3.1
       DHCP-Gateway-IP-Address = 172.16.28.1
       DHCP-Client-Hardware-Address = 00:01:a3:12:e2:94
       DHCP-Server-Host-Name = ""
       DHCP-Boot-Filename = ""
       DHCP-Router-Address = 192.168.28.1
       DHCP-Subnet-Mask = 255.255.255.0
       DHCP-Domain-Name-Server = 192.168.3.1
       DHCP-Domain-Name-Server = 192.168.3.3
       DHCP-NTP-Servers = 192.43.244.18
       DHCP-Vendor = 0x61726b617465
       DHCP-IP-Address-Lease-Time = 40
       DHCP-DHCP-Server-Identifier = 192.168.3.1
       DHCP-SMTP-Server-Address = 81.91.189.7
       DHCP-WWW-Server-Address = 192.168.3.5
       DHCP-MS-Static-Routes = "0x10c0a8c0a80607"
Finished request 1.

Опция отлично отправляется, но клиент расценивает этот пакет как невалидный и не принимает. Клиент сейчас в лице Windows 2003 Server.

В случае, если опция пустая - клиент принимает пакет.

 

В dictionary.dhcp указал её так:

ATTRIBUTE	DHCP-MS-Static-Routes			249	string

 

Пробовал по разному называть опцию, и DHCP-MS-Classless-Static-Route и MS-Classless-Static-Route, и MS-Static-Route - результат одинаковый.

 

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

 

Как именно должна называться эта опция, чтобы клиент в лице винды её нормально воспринимал? Или может быть я с типом опции намудрил?

Share this post


Link to post
Share on other sites

Как внутреннее название опции отражается в DHCP пакете? Правильно, никак.

Ценной информацией было бы, если бы вы показали дамп пакета.

К слову, есть еще же опции 33 и 121.

Share this post


Link to post
Share on other sites

10c0a8c0a80607

 

10 = 16

c0a8 = 192.168

c0a80607 = 192.168.6.7

Тут вроде всё правильно.

 

192.168.28.161/255.255.255.0

Скорее всего дропает потому что шлюз не попадает в подсеть клиента.

 

И "DHCP-Vendor = 0x61726b617465" - не хочу расшифровывать, там MSFT5.0 должно быть или вообще его не отдавать, оно вроде только для запросов серверу.

"DHCP-Gateway-IP-Address = 172.16.28.1" - хрень какая то, клиент такое точно не запрашивал %)

также как и ещё куча опций которыми вы в него кидаетесь.

 

 

# http://cpansearch.perl.org/src/SARENNER/Net-IPAddress-1.10/IPAddress.pm
#sub parseIPtoNumber { 
#return(unpack("N", pack("C4", split(/\./, $_[0])))); # C4 = CCCC
#}


# mask to bits
# http://milanweb.net/uni/old/scripting.html
sub subnetBits {
my $m = unpack("N", pack("C4", split(/\./, $_[0]))); # parseIPtoNumber

my $v = pack("L", $m);
my $bcnt = 0;
foreach (0..31) {
	if (vec($v, $_,1) == 1) {
		$bcnt++;
	}
}
return($bcnt);
}


# (121) Classless-Static-Route / (249) MSFT - Classless route
# by Rozhuk Ivan 2011
# RFC 3442
# based on:
# http://www.linuxconfig.net/index.php/linux-manual/network/203-transfer-of-static-routes-to-dhcp.html
# http://www.linux.by/wiki/index.php/FAQ_DHCP_routes
# Syntax: mk_classless_routes_bin_mask($net, $mask, $gw)
# example: mk_classless_routes_bin_mask('192.168.1.0', '255.255.255.0', '192.168.0.254')
sub mk_classless_routes_bin_mask {
#my $net = $_[0];
#my $mask = $_[1];
#my $gw = $_[2];

return(mk_classless_routes_bin_prefixlen($_[0], subnetBits($_[1]), $_[2]));
}

# Syntax: mk_classless_routes_bin_prefixlen($net, $prefixlen, $gw)
# example: mk_classless_routes_bin_prefixlen('192.168.1.0', 24, '192.168.0.254')
sub mk_classless_routes_bin_prefixlen {
#my $net = $_[0];
#my $prefixlen = $_[1];
#my $gw = $_[2];
my $str;

$str = pack('C', $_[1]);

if ($_[1] > 0) {
	my ($s1, $s2, $s3, $s4) = split(/\./, $_[0]);
	$str .= pack('C', $s1);
	$str .= pack('C', $s2) if ($_[1] > 8);
	$str .= pack('C', $s3) if ($_[1] > 16);
	$str .= pack('C', $s4) if ($_[1] > 24);
}

$str .= pack('CCCC', split(/\./, $_[2]));

return($str);
}

Это в бинарку пакует, если вам в хэкс то CCCC по тексту в pack нужно заменить на что то :)

 

Поиском по форуму можете найти пости Wingman с немного другой реализацией.

 

Если хотите отдавать маршрутизацию - смотрите что спрашивает клиент, если запрашивает 121 опцию - то отдавайте всё в ней, только если её нет и есть 249 то в неё это же самое пихайте.

249 - это микрософт зачем то придумал на заре ХР, толи 121 тогда не было в РФК толи выпендрится хотели, но содержимое/формат у них один. Разница в том, что опции 224-254 это вендор специфик, и если по грамотному то в 249 маршруты отдавать нужно только если вендор MSFT, а армия мыльниц может идти лесом.

И семёрка/2к8 запрашивают теперь 121 и 249.

Share this post


Link to post
Share on other sites

Вроде разобрался:

Возвращаю значение теперь вот так:

$RAD_REPLY{'DHCP-MS-Static-Routes'} = mk_classless_routes_bin_prefixlen('192.168.6.0', 24, '192.168.28.2');

По функции, указанной вами выше.

 

Однако это начало работать только тогда, когда в dictionary.dhcp указал её так:

ATTRIBUTE	DHCP-MS-Static-Routes			249	octets

Т.е. аналогично 121 опции.

 

DHCP-Gateway-IP-Address - это фрирадиус зачем-то указывает IP адрес DHCP-Relay в пакете, как отключить эту опцию - не нашёл.

Share this post


Link to post
Share on other sites

Может кто нибудь хорошо знающий перл разъяснить алгоритм в посте Ivan_83

Share this post


Link to post
Share on other sites

Что именно вы хотите узнать?

 

 

 

 

записываем первый бат результата: длинна префикса в битах

 

$str = pack('C', $_[1]);

 

 

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

if ($_[1] > 0) {

 

разбиваем IP адрес сети на части, чтобы позже сконвертировать строковое представление в число

my ($s1, $s2, $s3, $s4) = split(/\./, $_[0]);

 

Первый байт всегда записываем, ибо мы тут потому что как минимум 1 значащий бит есть

$str .= pack('C', $s1);

 

Если значащих байт в IP адресе сети больше 1 байта (8 бит) то записываем второй байт... и аналогично до 4байта

$str .= pack('C', $s2) if ($_[1] > 8);

$str .= pack('C', $s3) if ($_[1] > 16);

$str .= pack('C', $s4) if ($_[1] > 24);

}

 

 

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

$str .= pack('CCCC', split(/\./, $_[2]));

 

 

 

 

Тут везде подразумевается что изначально оно строка "127" - три байта, а после конвертирования оно 127 - число, 1 байт

 

 

 

Share this post


Link to post
Share on other sites

Перевел один из сегментов на DHCP на основе FreeRADIUS. Уже месяц у меня работает, старался реализовать полностью следуя RFC. Самое сложное было с динамикой. Даже удивительно что не падает и не тормозит :)

 

Кстати тут писали, что бывает и клиенты и сервера забивают на список запрошенных параметров и сервера отвечают как хотят, а клиенты это кушают. У меня клиенты физики, ОС разные, но пока такой проблемы я не увидел.

 

Еще по RFC в classless так же должен входить и дефолт! Столкнулся с этим на OpenSUSE 11.x. Виндам всем пофигу.

Edited by SokolovS

Share this post


Link to post
Share on other sites

В рфк делается упор на состояние данных клиента и его сохранение, на практике, особенно с фрирадиусом это не актуально и не реализуемо. Достаточно тупо лупить ответами с нужным адресом и режектить запросы с остальным, ещё я игнорил запросы от ррас.

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