Mikrotik DHCP Routes options 121 and 249: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
| (не показано 17 промежуточных версий этого же участника) | |||
| Строка 29: | Строка 29: | ||
Согласно этого же документа схема маршрута будет выглядеть так: |
Согласно этого же документа схема маршрута будет выглядеть так: |
||
<PRE> |
<PRE> |
||
| − | Code Len Destination 1 Router 1 |
+ | Code Len Destination 1 Router 1 |
+-----+---+----+-----+----+----+----+----+----+ |
+-----+---+----+-----+----+----+----+----+----+ |
||
| − | | 121 | n | d1 | |
+ | | 121 | n | d1 | ... | dN | r1 | r2 | r3 | r4 | |
+-----+---+----+-----+----+----+----+----+----+ |
+-----+---+----+-----+----+----+----+----+----+ |
||
Destination 2 Router 2 |
Destination 2 Router 2 |
||
+----+-----+----+----+----+----+----+ |
+----+-----+----+----+----+----+----+ |
||
| − | | d1 | |
+ | | d1 | ... | dN | r1 | r2 | r3 | r4 | |
+----+-----+----+----+----+----+----+ |
+----+-----+----+----+----+----+----+ |
||
</PRE> |
</PRE> |
||
| + | Цитата: |
||
| + | <PRE> |
||
| + | DHCP server administrators [...] should specify the default router(s) both in the Router option and in the Classless Static Routes option. |
||
| + | </PRE> |
||
| + | На человеческом это значит что нужно кроме всех маршрутов в опциях выдавать еще и дефолт |
||
| + | <BR> |
||
| + | Тут конечно мало что понятно - попробую привести пример |
||
| + | * маршрут <code>10.20.0.0/16</code> через шлюз <code>1.0.0.1</code> |
||
| + | * Маски и адреса подобраны такими намеренно - что бы показать когда нули отбрасываются а когда нет |
||
| + | |||
| + | |||
| + | * Маска dec(16) => <code>0x10</code> - маска будет <code>10</code>, причем в маске все знаки - значащие, для маски /8 значение будет <code>0x08</code> а не <code>0x8</code> |
||
| + | * Адрес сети <code>10.20.0.0</code> |
||
| + | ** последние 2 октета тут не значащие (они относятся к адресу хоста а не адресу сети, и это опредеяется по маске, и они отбрасываются |
||
| + | ** dec(10) => <code>0x0A</code> - так же как для маски, на каждый октет отводится строго два разряда |
||
| + | ** dec(20) => <code>0x14</code> - тут вопрос разрядности не возникает |
||
| + | ** итоговое значение которое нужно записать в опцию <code>0a 14</code> |
||
| + | * Шлюз <code>1.0.0.1</code> преобразовывается по аналогии с адресом сети, итоговое значение 1 => <code>0x01</code> 0 => <code>0x00</code> 0 => <code>0x00</code> 1 => <code>0x01</code> Итого - <code>01000001</code> |
||
| + | <BR> |
||
| + | Соответвенно конечный результат получается соединением всех частей: |
||
| + | Маска <code>10</code> Адрес Сети <code>0a 14</code> Адрес Шлюза<code>01000001</code> => <code>0x100a1401000001</code> |
||
| + | =Как это настроить на Mikrotik= |
||
| + | <PRE> |
||
| + | /ip dhcp-server option |
||
| + | add code=121 name=static_routes_121 value=0x180a4800c0a816fe130a5000c0a816fe16ac1f00c0a816fe18ac1f64c0a816fe0a6440c0a816fe00c0a816fe |
||
| + | add code=249 name=static_routes_249 value=0x180a4800c0a816fe130a5000c0a816fe16ac1f00c0a816fe18ac1f64c0a816fe0a6440c0a816fe00c0a816fe |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | /ip dhcp-server option sets |
||
| + | add name=static_routes options=static_routes_249,static_routes_121 |
||
| + | </PRE> |
||
| + | <PRE> |
||
| + | /ip dhcp-server |
||
| + | add add-arp=yes address-pool=bridge-home-network-192.168.22.0 comment=bridge-home-network dhcp-option-set=static_routes interface=bridge-home-network-vlan3104 lease-time=1h name=dhcp-server-bridge-home-network server-address=192.168.22.254 |
||
| + | </PRE> |
||
| + | |||
| + | {{caution|text= |
||
| + | Очень важный момент: Некоторые устройства не требуют наличия в Options маршрута к шлюзу по-умолчанию, и работают и так, но в стандарте такое требование есть |
||
| + | <BR> |
||
| + | По-тому '''ВСЕГДА''' нужно добавлять маршрут по-умолчанию |
||
| + | }} |
||
| + | |||
| + | =Сколько маршрутов можно передать= |
||
| + | Длинна опции ограничена (255) и можно прикинуть сколько маршрутов можно отдать: |
||
| + | |||
| + | * Минимальный маршрут: 1 байт (prefix) + 0 байт (сеть /0) + 4 байта (шлюз) = 5 байт. |
||
| + | * Максимальный маршрут: 1 байт (prefix) + 4 байта (сеть /32) + 4 байта (шлюз) = 9 байт. |
||
| + | |||
| + | Теоретический максимум: |
||
| + | * Если все маршруты /32: 255 ÷ 9 ≈ 28 маршрутов. |
||
| + | * Если маршруты /0: 255 ÷ 5 = 51 маршрут. (но конечно не может быть 51 маршрут с маской /0, это просто теоретический максимум) |
||
| + | {{caution|text= |
||
| + | '''<big>Так что если бляди насыпат вам через корпоративный VPN реально много маршрутов с разными масками то этот способ может и не сработать и прийдется городить другой костыль, например OSPF</big> |
||
| + | '''}} |
||
| + | |||
| + | =Скрипт для генерации Options= |
||
| + | * https://github.com/oldengremlin/route-4-dhcp/blob/master/rfc3442.route-4-dhcp.pl |
||
| + | Пример использования |
||
| + | <PRE> |
||
| + | /script.pl 10.72.0.0/24 192.168.22.254 10.80.0.0/19 192.168.22.254 100.64.0.0/10 192.168.22.254 172.31.0.0/22 192.168.22.254 172.31.100.0/24 192.168.22.254 1.0.0.0/1 192.168.22.254 128.0.0.0/1 192.168.22.254 0.0.0.0/0 192.168.22.254 |
||
| + | </PRE> |
||
| + | * Маршруты до сетей и 2 "полуинтернета" что б пидорский ВПН не подменял дефолт |
||
| + | {{#spoiler:show=rfc3442.route-4-dhcp.pl| |
||
| + | <PRE> |
||
| + | #!/usr/bin/perl |
||
| + | |||
| + | use strict; |
||
| + | use warnings FATAL => 'all'; |
||
| + | use diagnostics; |
||
| + | use v5.10.0; |
||
| + | |||
| + | my ($net, $gw, $aggregate) = ("", "", ""); |
||
| + | my $re_ip = "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; |
||
| + | |||
| + | foreach (@ARGV) { |
||
| + | unless ($net) { $net = $_; next; } |
||
| + | unless ($gw) { |
||
| + | $gw = $_; |
||
| + | |||
| + | my ($network, $subnetmask) = split("/", $net); |
||
| + | |||
| + | if (($subnetmask>=0 && $subnetmask<=32) && $network =~ /^$re_ip$/ && $gw =~/^$re_ip$/ ) { |
||
| + | |||
| + | my (@destination) = split( /\./, $network ); |
||
| + | my $destination = ""; |
||
| + | |||
| + | my (@router) = split( /\./, $gw ); |
||
| + | my $router = ""; |
||
| + | |||
| + | my $networklen = to_hex($subnetmask); |
||
| + | |||
| + | my $significantoctets = 0; |
||
| + | $significantoctets = 1 if $subnetmask>=1 && $subnetmask<=8; |
||
| + | $significantoctets = 2 if $subnetmask>=9 && $subnetmask<=16; |
||
| + | $significantoctets = 3 if $subnetmask>=17 && $subnetmask<=24; |
||
| + | $significantoctets = 4 if $subnetmask>=25 && $subnetmask<=32; |
||
| + | |||
| + | if ($significantoctets>0) { |
||
| + | foreach my $index (1..$significantoctets) { |
||
| + | $destination .= to_hex($destination[$index-1]); |
||
| + | } |
||
| + | } else { |
||
| + | $destination .= ""; |
||
| + | } |
||
| + | |||
| + | foreach my $r (@router) { |
||
| + | $router .= to_hex($r); |
||
| + | } |
||
| + | |||
| + | $aggregate .= sprintf("%s%s%s", $networklen, $destination, $router); |
||
| + | |||
| + | printf( |
||
| + | "option_121_route %s : netmask: 0x%s\n", |
||
| + | $net, $networklen |
||
| + | ); |
||
| + | |||
| + | printf( |
||
| + | "option_121_route %s : destination: 0x%s\n", |
||
| + | $net, $destination |
||
| + | ); |
||
| + | |||
| + | printf( |
||
| + | "option_121_route %s : gateway: 0x%s\n", |
||
| + | $net, $router |
||
| + | ); |
||
| + | |||
| + | |||
| + | printf( |
||
| + | "option_121_route_%s_via_%s : 0x%s%s%s\n", |
||
| + | $net, $gw, $networklen, $destination, $router |
||
| + | ); |
||
| + | printf( |
||
| + | "option_249_route_%s_via_%s : 0x%s%s%s\n", |
||
| + | $net, $gw, $networklen, $destination, $router |
||
| + | ); |
||
| + | |||
| + | } else { |
||
| + | print STDERR sprintf("Mask %d, network %s or gateway %s error\n"); |
||
| + | } |
||
| + | |||
| + | } |
||
| + | $net = ""; |
||
| + | $gw = ""; |
||
| + | } |
||
| + | |||
| + | if ($aggregate) { |
||
| + | printf("aggregate_opt_121 : 0x%s\n", $aggregate); |
||
| + | printf("aggregate_opt_249 : 0x%s\n", $aggregate); |
||
| + | } |
||
| + | |||
| + | |||
| + | sub to_hex { |
||
| + | my $n = shift; |
||
| + | return "00" unless $n; |
||
| + | $n = sprintf("%x", $n); |
||
| + | ($n) = "0$n" =~ m/.*(..)$/; |
||
| + | return $n; |
||
| + | } |
||
| + | |||
| + | </PRE> |
||
| + | }} |
||
Текущая версия на 10:20, 31 июля 2025
Mikrotik, DHCP Classless Route
TL;DR
Микротик умеет выдавать маршруты по dhcp хотя конфигуриться это через жопу
Зачем это может быть нужно
Ебучий корпоративный впн разворачивает в себя дефолт, и все хосты в домашней сети кроме L2-connected становятся недоступны. Настройки ВПНа на серверной стороне мне не доступны (и не факт что это убожество умеет нужные фичи)
Соответвенно есть 2 решения и оба они гребаные костыли:
- прописывать маршруты локально каждый раз при поднятии ВПНа (скриптом например)
- выдавать маршруты с dhcp (они будут работать так как за счет более узкой маски будут предпочтительнее чем default)
Как это настроить на микротике
Эта задача разделяется на 2 части
- Сформировать правильно значение опций
- Прописать на микротике
Option 121 и 249
Для устройств с разной реализацией DHCP клиента нужны 2 разные опции (винда/все остальные) но так как формат одинаковый то сложности тут немного
Формат опций 121 и 249
Опция 121, как и все остальные DHCP опции, описана в rfc3442. Этот документ диктует следующие правила и требования к 121 параметру:
- минимальная длина 5 байт.
- можно вписать один или более маршрутов
- каждый из маршрутов должен содержать Адрес сети назначения и IP адрес шлюза.
Согласно этого же документа схема маршрута будет выглядеть так:
Code Len Destination 1 Router 1 +-----+---+----+-----+----+----+----+----+----+ | 121 | n | d1 | ... | dN | r1 | r2 | r3 | r4 | +-----+---+----+-----+----+----+----+----+----+ Destination 2 Router 2 +----+-----+----+----+----+----+----+ | d1 | ... | dN | r1 | r2 | r3 | r4 | +----+-----+----+----+----+----+----+
Цитата:
DHCP server administrators [...] should specify the default router(s) both in the Router option and in the Classless Static Routes option.
На человеческом это значит что нужно кроме всех маршрутов в опциях выдавать еще и дефолт
Тут конечно мало что понятно - попробую привести пример
- маршрут
10.20.0.0/16через шлюз1.0.0.1 - Маски и адреса подобраны такими намеренно - что бы показать когда нули отбрасываются а когда нет
- Маска dec(16) =>
0x10- маска будет10, причем в маске все знаки - значащие, для маски /8 значение будет0x08а не0x8 - Адрес сети
10.20.0.0- последние 2 октета тут не значащие (они относятся к адресу хоста а не адресу сети, и это опредеяется по маске, и они отбрасываются
- dec(10) =>
0x0A- так же как для маски, на каждый октет отводится строго два разряда - dec(20) =>
0x14- тут вопрос разрядности не возникает - итоговое значение которое нужно записать в опцию
0a 14
- Шлюз
1.0.0.1преобразовывается по аналогии с адресом сети, итоговое значение 1 =>0x010 =>0x000 =>0x001 =>0x01Итого -01000001
Соответвенно конечный результат получается соединением всех частей:
Маска 10 Адрес Сети 0a 14 Адрес Шлюза01000001 => 0x100a1401000001
Как это настроить на Mikrotik
/ip dhcp-server option add code=121 name=static_routes_121 value=0x180a4800c0a816fe130a5000c0a816fe16ac1f00c0a816fe18ac1f64c0a816fe0a6440c0a816fe00c0a816fe add code=249 name=static_routes_249 value=0x180a4800c0a816fe130a5000c0a816fe16ac1f00c0a816fe18ac1f64c0a816fe0a6440c0a816fe00c0a816fe
/ip dhcp-server option sets add name=static_routes options=static_routes_249,static_routes_121
/ip dhcp-server add add-arp=yes address-pool=bridge-home-network-192.168.22.0 comment=bridge-home-network dhcp-option-set=static_routes interface=bridge-home-network-vlan3104 lease-time=1h name=dhcp-server-bridge-home-network server-address=192.168.22.254
|
Очень важный момент: Некоторые устройства не требуют наличия в Options маршрута к шлюзу по-умолчанию, и работают и так, но в стандарте такое требование есть
|
Сколько маршрутов можно передать
Длинна опции ограничена (255) и можно прикинуть сколько маршрутов можно отдать:
- Минимальный маршрут: 1 байт (prefix) + 0 байт (сеть /0) + 4 байта (шлюз) = 5 байт.
- Максимальный маршрут: 1 байт (prefix) + 4 байта (сеть /32) + 4 байта (шлюз) = 9 байт.
Теоретический максимум:
- Если все маршруты /32: 255 ÷ 9 ≈ 28 маршрутов.
- Если маршруты /0: 255 ÷ 5 = 51 маршрут. (но конечно не может быть 51 маршрут с маской /0, это просто теоретический максимум)
|
Так что если бляди насыпат вам через корпоративный VPN реально много маршрутов с разными масками то этот способ может и не сработать и прийдется городить другой костыль, например OSPF |
Скрипт для генерации Options
Пример использования
/script.pl 10.72.0.0/24 192.168.22.254 10.80.0.0/19 192.168.22.254 100.64.0.0/10 192.168.22.254 172.31.0.0/22 192.168.22.254 172.31.100.0/24 192.168.22.254 1.0.0.0/1 192.168.22.254 128.0.0.0/1 192.168.22.254 0.0.0.0/0 192.168.22.254
- Маршруты до сетей и 2 "полуинтернета" что б пидорский ВПН не подменял дефолт