Mikrotik, DHCP Classless Route

  • Tutorial
DHCP Classless Route, зачем он нужен?

У нас в компании для VPN используется решение на tincd. Из-за того, что на Mikrotik я не нашёл простого способа запустить tinc, было решено запускать VPN на отдельном сервере и использовать его как шлюз. Первая попытка — прописать маршрут на маршрутизаторе. По пингам было видно, что маршрутизатор присылает сообщение о редиректе, при этом наблюдались сетевые лаги. При работе создавалось ощущение, что соединение, установленные таким образом, подтормаживает.

В качестве эксперимента решил попробовать на своём рабочем месте прописать маршрут руками. Это оказалось правильным решением — лаги пропали, но данную операцию нужно было проделать на всех машинах офиса, а руками вбивать как то не хотелось. В связи с этим понадобился способ, без особого напряжения, настраивать статический маршрут, на всех клиентах, получающих адрес по DHCP протоколу.

Процесс гугления привёл меня на страницу документации Mikrotika. Всё ясно — нам поможет DHCP Classless Route. Настройка относительно легка, но вот из-за этой относительности убил на настройку пол дня. При этом возникали проблемы с сетевым доступом у хостов сети — у Windows машин пропадал маршрут по умолчанию.
Ещё одна сложность настройки Mikrotik заключается в том, что нужно вводить маршрут в шестнадцатеричном (либо в двоичном) виде, что меня слегка сбило с толку. Да и в документации некоторые нюансы не указаны. Данная опция рассмотрена в базовом варианте. А дальше как хотите )). Пришлось немного углубиться в подробности настройки.

Для того что бы у вас маршрут получили все хосты, независимо от семейства операционной системы нужно настроить 2 опции 121 и 249. Если бы все разработчики следовали бы RFC, то возможно жизнь системных администраторов была бы гораздо преснее и менее интересной.

Опция 121
Опция 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 |
+----+-----+----+----+----+----+----+


Для того что бы правильно составить маршрут нужно перевести адрес сети назначения, маску подсети и адрес шлюза в шестнадцатеричный формат. Желающие пострадатьповысить личный скилл могут переводить в двоичный формат.
Пример 1.
Составим строку маршрута для сети 10.0.0.0/24 через маршрутизатор 192.168.0.2
LEN (маска подсети назначения) = 24 = 0x18
DESTINATION = 10.0.0.0 = 0A 00 00
ROUTER = 192.168.0.2 = c0 a8 00 02
Итоговая строчка: 0x180A0000c0a80002
добавляем маршрут в микротик:
через winbox

через консоль
/ip dhcp-server option
add code=121 name=opt_121_10 value=0x180A0000c0a80002
set 0 dhcp-option=opt_121_10

Пример 2.
Составим строку маршрута для сети 10.0.0.0/8 через маршрутизатор 192.168.0.2
LEN (маска подсети назначения) = 8 = 0x08
DESTINATION = 10.0.0.0 = 0A
ROUTER = 192.168.0.2 = c0 a8 00 02
Итоговая строчка: 0x080Ac0a80002
Пример 3.
Составим строку маршрута для сети 10.0.0.0/8 через маршрутизатор 192.168.0.2
LEN (маска подсети назначения) = 29 = 0x19
DESTINATION = 172.16.4.0 = AC100400
ROUTER = 192.168.0.2 = AC10040001
Итоговая строчка: 0x19AC100400AC10040001
Картинки ко 2 им 3 примерам не прикладываю, т.к. на самом маршрутизаторе настраивать идентично примеру 1.

Очень легко можем нарваться на внезапное отключение клиентов из-за одного маленького нюанса
Если вы некорректно укажете адрес подсети. Ошибку сделать очень легко. Что бы избежать этого нужно вспомнить теорию и применить её на практике.

Давайте вспомним. Есть адрес и маска подсети. Адрес делят на две части — сетевую и хостовую.
Маска подсети указывает сколько первых бит адреса относится к сетевой части. Соответственно, оставшаяся часть адреса, указывает на хостовую.
Если нам нужен маршруте к сети с маской 24 бита, то нам нужны первые 3 октета адреса сети назначения (Пример 1)
Если нам нужен маршруте к сети с маской 8 бит, то нам нужен, всего лишь, 1-й октет адреса сети назначения (Пример 2)
Если нам нужен маршруте к сети с маской 25 бит, то тут нужно будет указывать все октеты (Пример 3)


Опция 249
На страничке wikipedia с описанием dhcp есть ссылка на общепринятые DHCP опции. 249 опция находится в диапазоне для частного использования.
Я не знаю почему товарищи мелгкомягкие придерживаются взглядов товарища Ленина, но им они следуют достаточно фанатично. Несмотря на наличие RFC3442 майкрософт решил на своих клиентах маршрут получать опцией 249.
На микротике данная опция настраивается подобно 121-й опции
0x[маска подсети адреса назначения][адрес назначения][адрес шлюза]
Если возникнут проблемы с настройкой Windows машин, то попробуйте воспользоваться советом под спойлером
0x[маска подсети адреса назначения][адрес назначения][адрес шлюза]00[адрес шлюза]
Добавьте к строчке 00 и адрес маршрутизатора ещё раз.
Почему это работает я не понял. Путём эмпирических изысканий было найдено предоставленное решение. В последствии у меня заработала опция и без этого костыля.


Несколько маршрутов одной строкой

К сожалению в документации на сайте Mikrotik нет примера как правильно настраивать несколько маршрутов. На помощь нам приходит RFC3442 в котором есть замечательная схема составления нескольких маршрутов которая приведена выше.
Добавляем к первому маршруту второй маршрут без 0x
Пример
два маршрута 10.0.0.0/8 и 172.16.4.0/24 через шлюз 192.168.0.2 одной строкой будут выглядеть так:
0x080Ac0a8000218AC100Bc0a80002
жирным выделил маски подсетей

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

PS: Прошу замечания и предложения направлять в личку.

UPD:
товарищ orlovdl набросал python функцию для перевода блока адресов в Hex формат.

UPD:
товарищ poofeg подсказал:
Я бы обратил внимание на эту фразу в RFC3442:
DHCP server administrators [...] should specify the default router(s) both in the Router option and in the Classless Static Routes option.
Во всех ваших примерах в опции 121 маршрут по умолчанию отсутствует. То есть к обоим строчкам лучше в конце дописать 00c0a80001 (0.0.0.0/0 via 192.168.0.1).
Метки:
Поделиться публикацией
Похожие публикации
Комментарии 29
  • 0
    Если не секрет то что за Mikrotik был и какой трафик через него лился?
    • 0
      Вот такая машинка стоит 2011UAS-2HnD. Трафик — да обычный офисный — серфинг в интернете, + работа с удалёнными серверами по web,ssh, + телефония
      • 0
        К чему вопрос то был.
        У меня есть два RouterBOARD 2011UiAS-RM. Между ними L2TP. Одна сеть 192.168.12.0\24 вторая 192.168.88.0\24
        И все бы ни чего, но периодически при открытии файлов из расшаренных папок другой подсети я вижу миросовтовсую ошибку 64 иногда «Указанное сетевое имя более не доступно». При том что если сделалть попытку номер два и повторно открыть файл то все открывается. Вот и думаю связанна ли моя проблема с тем что маршруты то же прописаны на микротиках.
    • 0
      Извините, но пора уже переползать на MPLS.
      • 0
        Пора перестать заниматься ерундой — настройте проксиарп на сервере с впн или выдавайте адреса из другой подсети и пропишите маршрут на роутере.
        • 0
          я в начале статьи написал — маршрут сначал был настроен на роутере — соединения лагали.
          Кому и зачем выдавать адреса из другой посети? Серверу VPN? — можно, но есть несколько нюансов которые, пока, не позволяют это сделать.
          Насчёт proxyarp спасибо — покопаю.
          • 0
            Вы видимо пытались «маршрутизировать» пакеты из одной подсети, от того оно могло слать только icmp редиректы со всеми вытекающими.
            Если у вас впн клиенты попадают в локалку с адресами из локалки — то проксиарп, если нет — маршрутизация через дефолтный шлюз. Если вам там что то мешает вынести впн сервер из локалки, повесьте на впн сервер алиасом адрес не из локалки и маршрутизируйте на него.

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

            121 и 249 — формируются абсолютно одинаково, подробностей не помню, если интересно — смотрите в моём дхцп сервере на перле: netlab.linkpc.net/download/tmp/dhcpd.pl
            mk_classless_routes_bin_mask()

            Удобство пользования тиком конечно доставляет, ибо в любой мыльнице есть dnsmasq где это делается на порядок удобнее.
            • 0
              Вы видимо пытались «маршрутизировать» пакеты из одной подсети

              верно. Дефолтный шлюз 192.168.0.1, а VPN-шлюз — 192.168.0.2

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

              Почему? Я не вижу никакой проблемы. Маршруты и маршруты — хоть 200 штук. Какая разница?

              121 и 249 — формируются абсолютно одинаково

              Ну я это понял и в статье отписал. Просто при первой настройке (ещё не всё голове уложилось) и заработало с тем, что под спойлером спрятано. А так — да, одинаково.

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

              Вы представляете этот уровень «костылизма», по сравнению с передачей роутов по DHCP?
              1. Алиас на интерфейс VPN-шлюза (ну в линуксе это сделать просто)
              2. Алиас на интерфейс локалки на микротике. — (КАК?! а вот тут что то я не нашёл решения простого)
              3. В локальной сети пакеты будут бегать с адресацией из другой подсети.

              Вот второй пункт как то не получится. У меня не получилось, по крайней мере. Мне нужно добавить на Микротик алиас на интерфейс, но я не нашёл как это сделать. Нашёл какие то варианты с файерволом левые — в общем я пока не представляю как это реализовать.

              Если у вас впн клиенты попадают в локалку с адресами из локалки — то проксиарп

              Зачем? Я не вижу преимущества. Нужно дополнительно настраивать службу на VPN-шлюзе. +1 костыль.
              • 0
                1. Клиенты впн получают адрес из локалки.
                Если включить прокси арп на впн сервере то он будет анонсить все адреса клиентов в локалку со своим маком и
                все эти маршруты станут не нужны.
                Всё будет работать как и должно, без лишних заморочек.

                2. Если клиент не из локалки адрес получает, то это классический роутинг.
                Не вижу причин почему не вынести впн сервер из локалки совсем и ходить к нему через дефолтный шлюз.
                200 маршрутов в дхцп — может вызвать снос мозга клиентам.
                Для таких целей существуют всякие RIP, OSPF, BGP и прочее.

                В случае FreeBSD + MPD5 достаточно включить одну опцию и оно само будет добавлять адреса клиентов в арт таблицу как локальных — те анонсить.
                • 0
                  у меня вариант №2.
                  Несколько площадок, на каждой своя подсеть. На VPN сервере поднят ещё и OSPF. VPN у меня полносвязный одноточечный — tinc — мешсеть на его основе.
                  У меня нет простой возможности вынести VPN сервер из локалки. Я не хочу заморачиваться vlan`ами — пока нет такой острой необходимости. Я бы с удовольствием терменировал VPN на микротике, если бы была возможность — пока я её не видел.
                  Насчёт 200 маршуртов DHCP — это я пошутил, но я пока так и не понял, чем мой вариант плох.
                  Пора перестать заниматься ерундой
                  Выдача маршрутов, кроме дефолт шлюза на своей сети это вообще крайняя, костыльная мера.

                  Где я занялся ерундой? И почему выдача доп. маршрутов это «костыльная мера» если это заложено в RFC?
                  • 0
                    Мало ли что в RFC заложено.

                    Костыльная потому что в данном случае не оправданная технически, только из за административной прихоти.

                    Техническим оправданием выдачи доп маршрутов может служить то что по этим маршрутам будет ходить настолько много трафа что через шлюз по умолчанию ему не пролезть без проблем. Либо существует какое то разделение на физ уровне и более рационально это изначально учитывать сразу на клиентах с помощью до маршрутов.

                    Крайняя мера потому что не все клиенты могут проглотить маршруты.
                    В некоторых сетях мак шлюза на коммутаторах связывается с его IP чтобы предотвратить спуфинг, в таких случаях придётся везде дополнительно прописывать ещё маки других шлюзов с их адресами.
                    Кроме того, если нужно будет что либо оперативно изменить — вы не сможете это сделать, тк клиенты по дхцп настройки получают относительно редко.
                    • 0
                      Я думаю можно закрыть обсуждение, т.к. вы высказываете своё ИМХО, но внятного пояснения, чем плохо выдавать маршруты по DHCP, я пока так и не увидел.
                      RFC на то и RFC, что производители и разработчики следуют описанным стандартам. Раз данная опция существует и не пропала со времени создания этого RFC, значит ничего криминального и «технически неоправданного» тут нет.
                      Не придумывайте лишние сущности. Борьба со спуфингом, настройка коммутаторов, это уже другая тема. Откуда вы знаете какие у меня коммутаторы стоят? Может у нас очень мало денег и мы купили дешевые неуправляемые коммутаторы? (это не так, но для примера сойдёт).
                      Есть задача, есть варианты решения. Мой вариант ничем не хуже.
        • 0
          А почему самими Тиком не ВПНите?
          • 0
            как подключить его к VPN сети на tinc? Я просто искал подобное, но не нашёл такой возможности на микротике. Ну и "+" в том, что все сервера управляются через puppet — мне проще так показалось.
            • 0
              Я имел ввиду что почему не использовать Микротик как сервер ВПН. Он же на входе в сеть. И ни чего не надо было городить. Куча разных протоколов. Маршрутизируй не хочу.
              • 0
                Вы знаете как включить Микротик в VPN сеть на TINC?
                Я нет.
          • 0
            Вот набросал python функцию для этого, может еще кому пригодится ;-)
            • 0
              Спасибо. Добавил апдейтом к статье.
              • 0
                Ну, а для откровенных лентяев ниже написан скрипт ;), правда не на python, а на perl…
            • 0
              Я бы обратил внимание на эту фразу в RFC3442:
              DHCP server administrators [...] should specify the default router(s) both in the Router option and in the Classless Static Routes option.

              Во всех ваших примерах в опции 121 маршрут по умолчанию отсутствует. То есть к обоим строчкам лучше в конце дописать 00c0a80001 (0.0.0.0/0 via 192.168.0.1).
              • 0
                Спасибо. Добавил как апдейт.
              • 0
                Интересно, какие версии Windows не обрабатывают опцию 121?
                Windows 7 SP1, Windows 8, Windows 8.1, Windows 2012 R2 точно обрабатывают, причём для них маршрут по умолчанию добавлять нет необходимости.
              • 0
                Никак не вкурю как вычислять если маска не кратна 8, например 10.84.113.0/26 via 192.168.0.1
                • 0
                  Основной коментарий приведён несколько ниже, тут кратко:
                  $ rfc3442.route-4-dhcp.pl 10.84.113.0/26 192.168.0.1
                  option_121_route_10.84.113.0/26_via_192.168.0.1 : 0x1a0a547100c0a80001
                  option_249_route_10.84.113.0/26_via_192.168.0.1 : 0x1a0a547100c0a80001
                  aggregate_opt_121 : 0x1a0a547100c0a80001
                  aggregate_opt_249 : 0x1a0a547100c0a80001
                • +1
                  Может кому поможет скрипт, который родился исключительно из-за лени rfc3442.route-4-dhcp.pl.

                  Использовать его просто:
                  $ rfc3442.route-4-dhcp.pl 10.0.0.0/8 192.168.88.2 172.16.0.0/12 192.168.88.2 192.168.0.0/16 192.168.88.2 0.0.0.0/0 192.168.88.1
                  option_121_route_10.0.0.0/8_via_192.168.88.2 : 0x080ac0a85802
                  option_249_route_10.0.0.0/8_via_192.168.88.2 : 0x080ac0a85802
                  option_121_route_172.16.0.0/12_via_192.168.88.2 : 0x0cac10c0a85802
                  option_249_route_172.16.0.0/12_via_192.168.88.2 : 0x0cac10c0a85802
                  option_121_route_192.168.0.0/16_via_192.168.88.2 : 0x10c0a8c0a85802
                  option_249_route_192.168.0.0/16_via_192.168.88.2 : 0x10c0a8c0a85802
                  option_121_route_0.0.0.0/0_via_192.168.88.1 : 0x00c0a85801
                  option_249_route_0.0.0.0/0_via_192.168.88.1 : 0x00c0a85801
                  aggregate_opt_121 : 0x080ac0a858020cac10c0a8580210c0a8c0a8580200c0a85801
                  aggregate_opt_249 : 0x080ac0a858020cac10c0a8580210c0a8c0a8580200c0a85801
                  • 0
                    Спасибо за статью! Приятно, что кто-то раскурил это до меня :)

                    Один нюанс: я правильно понимаю, что в третьем примере ошибка из-за копипаста и имелась в виду сеть 172.16.4.0/29? И шлюз там не должен быть аналогичен второму примеру (192.168.0.2 = c0 a8 00 02)?

                    И где пример с маршрутами одной строкой, поясните, пожалуйста — как микротик определяет, где заканчивается один маршрут и начинается второй, если поля разной длины (например, когда 10.0.0.0 интерпретируется в 0A, а не в 0A 00 00 00)?
                    • 0
                      Рад что пригодилось.
                      я правильно понимаю, что в третьем примере ошибка из-за копипаста

                      Совершенно верно.

                      как микротик определяет, где заканчивается один маршрут и начинается второй

                      Чуть выше вашего комментария скрипт oldengremlin который собирает в одну строку.
                      Маршруты разделяются по маске подсети.

                      LEN (маска подсети назначения) = 8 = 0x08
                      DESTINATION = 10.0.0.0 = 0A

                      Маска подсети — 8 бит. Это означает, что сетевая часть адреса — первый октет. Всё. Больше искать смысла нет т.к. остальное это адреса хостов подсети.
                      Если сетевая маска 24 бита, то сетевая часть адреса это 3 октета. Как то так ))
                    • 0
                      Интересно, «перебить» выданный стандартным DHCP маршрут по умолчанию так можно? Мне на ум тольков вариант приходит вместо пути для 0.0.0.0/0 прислать два пути для 0.0.0.0/1 и 128.0.0.0/1 — маска у них точнее, будут иметь приоритет.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.