Friday, November 28, 2014

xbmcswift2 — микро-фреймворк для написания плагинов к Kodi (XBMC)

Вступление


Это, так сказать, «бонусная» статья в моей серии статей о плагинах к медиацентру Kodi (XBMC). Прежде всего, необходимо отметить, что, начиная с версии 14.0, популярный медиацентр меняет название с XBMC на Kodi. О причинах смены названия можно почитать на официальном сайте и форуме, и для нашей статьи они не принципиальны. Однако дальше в статье будет использоваться новое название — Kodi.

Предыдущие статьи

Подробная анатомия простого плагина для XBMC
Пишем плагин для XBMC с собственным интерфейсом: часть I — теория и простейший пример
Пишем плагин для XBMC с собственным интерфейсом: часть II — диалоги и украшателства
Пишем плагин для XBMC с собственным интерфейсом: часть III — API и микро-фреймворк

xbmcswift2


В первой статье — «Подробная анатомия простого плагина для XBMC» — было рассказано о базовых принципах работы плагинов-источников контента, т. е. плагинов, которые позволяют смотреть видео и слушать музыку с различных онлайновых ресурсов. Этих базовых принципов два:
  1. Каждый элемент виртуального каталога (ссылка на подраздел или файл для проигрывания) представляет собой объект классаxbmcgui.listItem, содержащий всю информацию об элементе виртуального каталога. При создании списка элементов мы последовательно создаем объекты xbmcgui.listItem, задаем их свойства (эскиз, фанарт, ссылка, дополнительная информация) и «скармливаем» эти элементы функции xbmcplugin.addDirectoryItem.
  2. Для создания многоуровневых каталогов плагин рекурсивно вызывает сам себя, передавая параметры в виде URL-encoded строки через элемент списка sys.argv[2]. При этом нам нужно декодировать эти параметры и вызвать соответствующую часть кода, чтобы, например, сформировать каталог нижнего уровня (подраздел) или воспроизвести видео по ссылке. Т. е. нам нужно организовать маршрутизацию таких рекурсивных вызовов.

В результате на разработчика плагина возлагается лишняя работа, не связанная непосредственно с получением информации, организацией контента и его воспроизведением.

При создании xbmcswift2 разработчик, очевидно, вдохновлялся популярными микро-фреймворками Python для веб-разработки — Flask и Bottle. Механизм маршрутизации рекурсивных вызовов явно позаимствован у этих фреймворков — пути вызовов и передача параметров реализованы через декораторы функций.
Кроме этого, в xbmcswift2 унифицирована структура элементов виртуальных каталогов. Теперь отдельный элемент представляет собой питоновский словарь со всеми необходимыми свойствами в виде пар ключ—значение. Эти элементы объединяются в список, и для отображения списка элементов в интерфейсе Kodi функция, «украшенная» декоратором маршрута, должна вернуть этот список. Дальнейшую обработку списка и декодирование словарей, описывающих элементы этого списка, берет на себя xbmcswift2.
Помимо упрощения создания списков контента и маршрутизации рекурсивных вызовов xbmcswift2 предлагает такие приятные возможности, как кэширование объектов, возвращаемых функциями и методами, а также постоянное хранилище для хранения состояния объектов между рекурсивными вызовами. xbmcswift2 также позволяет выполнять отладку кода плагина в консоли, без использования Kodi.

Чтобы проиллюстрировать использование xbmcswift2, я возьму плагин из статьи «Подробная анатомия простого плагина для XBMC» и перепишу под этот фреймворк. Для простоты новый плагин не будет выводить никаких сообщений на экран, поэтому языковые файлы в нем отсутствуют.

Код плагина


Теперь, как всегда, построчный разбор. Для отображения номеров строк используйте текстовый редактор с соответствующей функцией, например Notepad++. Очевидные вещи и то, что понятно из комментариев, пропускаю.

30: декоратор @plugin.cached() используется для кэширования объектов, возвращаемых функциями или методами. Таким декоратором рекомендуется «украшать» функции, получающие содержимое с веб-сайтов, чтобы не создавать излишнюю нагрузку на эти сайты. Срок кэширования в минутах задается в качестве параметра декоратора.
49: декоратор @plugin.route() используется для маршрутизации вызовов плагина. Плагин в обязательном порядке должен содержать как минимум корневой маршрут ('/').
55—61: свойства элемента списка задаются в виде достаточно простого и понятного словаря.
61: метод url_for() формирует правильный путь для рекурсивного вызова плагина, чтобы этот путь мог быть декодирован xbmcswift2. В качестве первого параметра используется имя вызываемой функции в виде строки, а дополнительная информация передается через именованные параметры. В качестве параметров можно использовать только простые строки. Соответственно, все другие типы данных должны быть приведены к строкам. Символы, отличные от ASCII, можно передавать в виде URL-encoded последовательности (например, «Вася» > «%D0%92%D0%B0%D1%81%D1%8F » или в кодировке base64.
65: метод finish() используется для передачи дополнительных параметров отображения списка контента (помимо самого списка). Если никаких дополнительных параметров возвращать не нужно, можно вернуть сам список, не используя метод finish().
69,70: вызываем функцию, которая формирует список подкастов. В качестве параметра передаем номер раздела в списке (точнее, tuple) FEEDS.
83: указываем, что этот элемент не содержит вложенных элементов (в данном случае элемент списка — файл для проигрывания). По умолчанию этот параметр равен False, поэтому в предыдущей функции он опущен.
89—90: здесь для отправки файла в основной код Kodi на проигрывание используется специальная функция play_podcast(), которая, в свою очередь, вызывает метод set_resolved_url(). Этот метод представляет собой «обертку» xbmcswift2 вокруг стандартной функции Kodi Python API xbmcplugin.setResolvedUrl(). Использование xbmcplugin.setResolvedUrl() плохо документировано, но именно такой метод является предпочтительным для запуска проигрывания мультимедийных файлов. Безусловно, можно использовать прямые ссылки на эти файлы (и в примере из статьи «Подробная анатомия простого плагина для XBMC» был использован простой вариант с прямыми ссылками), но при использовании прямых ссылок имеются нежелательные побочные эффекты. Например, при формировании списка файлов Kodi старается прочитать метаданные этих файлов, что при большом количестве элементов списка и медленном соединении приводит к тому, что список формируется очень долго. Кроме того, при использовании прямых ссылок не поддерживаются автозакладки и отметки просмотренного. Причина последнего непонятна (по всей видимости, баг.) Однако в случае использования xbmcplugin.setResolvedUrl() и его аналога из xbmcswift2 — set_resolved_url() — этих побочных эффектов не наблюдается.

Заключение


Микрофреймврок xbmcswift2 доступен в официальном репозитории Kodi, и при создании плагина на его основе микро-фреймворк нужно указать в качестве зависимости в файле метаданных плагина Kodi — addon.xml. Подробнее об этом см. в предыдущих статьях и в официальной Вики.
Готовый демонстрационный плагин на базе xbmcswift2 можно загрузить отсюда.

Надеюсь, информация из этих статей поможет вам в написании полезных плагинов для Kodi. Как показывает практика, самая сложная задача при написании плагина — это вытащить ссылки на видео или музыку с того или иного сайта, а уже организовать информацию и ссылки в плагине значительно проще.

Источники информации


Официальная документация xbmcswift2.

Десктопные CRM: дегустация бесплатного сыра


Пока на Хабре с азартом выбирали облачные CRM, передо мной встала обратная задача — найти CRM десктопную. Такое решение было продиктовано необходимостью обеспечения безопасности данных, особенно клиентской базы и рядом других, не менее весомых причин. Покупка предстояла серьезная (как-никак, 30 мест с возможной доработкой) и подход нужен был соответствующий.

Эксперимент

Прежде, чем купить ту или иную систему, мы провели большой эксперимент в несколько этапов:
  1. Собрали списки существующих CRM, отзывы на них, просмотрели сайты и цены.
  2. Определили свои цели и собрали требования: CRM должна быть операционной, рассчитанной на ведение клиентов, сделок, цикла продаж, базы, на планирование и контроль за действиями менеджеров, построение внятных и быстрых отчетов.
  3. Установили мне (администратору) и менеджерам бесплатные версии на тестирование.
  4. Установили демо-версии выбранных CRM и работаем на них.

Рассказ получается длинным, поэтому в первой части обзора для Хабра решено рассмотреть бесплатные однопользовательские версии выбранных CRM.
image

Сделай сам

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

Galloper CRM — достаточно продуманная система с обширным функционалом и, как и предполагает логика этой группы, никаким интерфейсом. В принципе, при должном старании и умении работать с СУБД (хотя бы MS Access), Galloper можно доработать под нужды бизнеса любого профиля. Здесь настраивается с нуля или почти с нуля всё: справочники, маршруты продаж, события, активности, настройки напоминаний и проч… Карточка клиента имеет огромный набор полей с возможностью дополнительной кастомизации. В системе предусмотрено множество отчетов по продажам, товарам, активностям, воронка продаж.

image

Из очевидных минусов — непрозрачность логики создания многих полей и медленная работа при мало-мальски серьезном наполнении базы. Создалось ощущение, что эта система рассчитана все-таки на компании с небольшой клиентской базой.

Supasoft CRM изначально позиционируется как платформа для разработки персональных конфигураций, поэтому и вид «конструктора» принимает образ фишки. Анонсированная на сайте простота интерфейса представляет собой в реальности пустое окно после запуска с простым и доступным меню. В этой CRM нет личного планировщика, дел, задач, отслеживания действий менеджера, однако просто создаются формы для учета товаров, продаж, клиентов. В Supasoft можно строить отчеты с самым широким набором параметров, организуя по шаблону свои сводные таблицы.

image

В целом, Supasoft CRM — это прекрасная альтернатива MS Excel. Она неплохо организована и при грамотном подходе с ней можно спокойно работать как с базой товаров, услуг, клиентов и сделок.

Политика девелоперов этих CRM-решений не совсем понятна с точки зрения инженера и абсолютно прозрачна с точки зрения маркетинга. Другие бесплатные CRM предоставляют гораздо более богатые возможности и при этом дают красивый и удобный интерфейс. Пользователи CRM – это, как правило, менеджеры, далекие от мира IT и их просто пугают пустые, скучные поля, которые нужно «допиливать». Хотя мне, как менеджеру по IT, очень понравилось доводить эти «легкие» CRM до ума, но just for fun.

Чужой среди своих

Monitor CRM – эта CRM стоит особняком только потому, что она слишком избыточна для целей управления клиентами. Это функциональная, продуманная аналитическая CRM, однозначно заслуживающая отдельного внимания. К сожалению, сайт не допускает скачку их бесплатной версии Lite, поэтому пришлось воспользоваться демо-версией, которую можно успешно наполнять своими данными и использовать для своих нужд.

image

Прежде всего, Monitor удивляет набором полей каждой из карточек. Например, для продукта предусмотрено изображение, заменители, цены конкурентов на такой же продукт, ГОСТы и т.д… Из таких полей строятся аналитические данные, которые больше подойдут службе маркетинга или развития, чем отделу продаж или клиентского сервиса. При этом модуль продаж отлично организован: можно смотреть и создавать отгрузки, заявки, оплату. В планировщике задач можно создавать задачи разного типа с цветовой индикацией и напоминаниями.

Если обратиться к аналитике, то в этой CRM считается маржа, рентабельность и множество других показателей. Интересна вкладка «Проблемные зоны» с возможностью создания кастомных группировок клиентов, которые являются проблемными. Из очевидных промахов юзабилити — множество окон на одном экране: обзор процесса ухудшается, окна приходится ужимать, логика некоторых ветвей и деревьев непонятна и неудобна для пользователя.

В заключение могу сказать, что как пользователь я не вижу смысла в однопользовательской аналитической CRM – вся мощь аналитики, которая пригодилась бы в крупной компании при совместной работе, превращается в неуклюжий, ненужный набор, тянущийся за неплохим планировщиком и системой управления продажами.

Прошли во второй этап

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

Quick Sales CRM — трудолюбивая CRM, соответствующая своему логотипу-пчеле. Простой и понятный интерфейс, доступные кнопки вызова модулей в меню справа, хорошо написанная справка.

image

Карточка клиента обладает всеми необходимыми полями, можно проставлять статус клиента, предусмотрены кнопки для быстрого перехода на сайт клиента и для звонка через софтфон, легко прописываются планы по клиенту.
Вся работа с клиентом фактически ведется в его карточке — в ней создаются работы (с классификацией типа), договоры (с ссылками на файл), заметки, планы, а также вносятся товары и услуги.

Что касается товаров и услуг, то их необходимо сначала вносить в справочник «Продукты», при создании можно выставлять хинт «Услуга», но на мой вкус, лучше создавать разные папки для разных групп товаров и услуг. Перед началом работы с продуктами совершенно не лишним будет зайти в раздел «Общие настройки» и разобраться с валютами по умолчанию и валютой прайса в справочнике Продукты. При введении цены в прайс валютой по умолчанию является доллар, но предупреждения об этом нигде нет. Но при этом, если в прайс внесены цены и валюту сменить уже после внесения, то цена останется внесенной (было 10 долларов, стало 10 рублей).

Не понравилось, как реализована база знаний, однако ее существование — уже плюс. Она предусматривает ответ и вопрос по продукту, без вложенности и особой распространенности, но с возможностью прикрепления файла. Такое решение очень здорово может помочь менеджерам, работающим с клиентами, а также техподдержке. В Quick Sales CRM хорошо реализована древовидная структура справочников, которые можно расширять и кастомизировать под свои потребности.

А вот что конкретно не понравилось, так это наличие в меню функций, недоступных в бесплатной версии. Их можно было бы вынести в отдельный тур, раздел справки, всплывающее окно, куда угодно — только не в меню. Открываешь с наивной радостью: интеграция с 1С, импорт базы QS, рассылка, групповые операции над данными, а тебе в ответ окно с информацией о доступности только в платной версии. После очередной недоступной функции удовольствие от пользования CRM разбавляется раздражением.

RegionSoft CRM. В бесплатной редакции, работающей под СУБД Firebird, можно подключаться как к существующим базам данным, так и создавать и наполнять новые базы. При первом запуске система выводит форму, в которой заносятся данные о вашей организации и учетной записи.

image

Работать в CRM просто — она имеет интуитивный интерфейс с графическими кнопками и привычным меню. Слева находится меню «Ассистент», в котором в один клик можно открыть счета, планировщик, задачи. Планирование в Express хорошо продумано  — настроены напоминания, можно сдвигать планы, редактировать карточки задач. Задачи создаются в одно окно, можно выставить время напоминания, добавить комментарий, выбрать ответственного.

В RegionSoft Express, пожалуй, самые полные и аккуратные справочники, которые можно дополнять в несколько кликов. Такая наполненность данными значительно экономит время при старте работы с CRM.

При создании карточки клиента можно выставить флаг важности (статус: горячий клиент, позитивный процесс, негативный процесс). Внизу карточки реализована вся его история с вкладками: события, задачи, счета, продажи, услуги, корреспонденция и файлы (файлы имеют вложенную структуру, можно создавать папки).

Карточка товара создается также просто, прямо в ней можно создать коммерческое предложение и прикрепить необходимые файлы, например, фото товара, его спецификацию, сертификат соответствия и проч… Продажи можно заносить прямо в раздел «Продажи» и создаваться через счет: выписывается счет, выставляется клиенту и затем на основе существующего счета создается продажа.

Кроме того, в RegionSoft CRM предусмотрен журнал корреспонденции, база знаний с разделами и внутренним редактором, мощные настраиваемые фильтры. Отчеты строятся в виде таблиц или гистограмм, в отдельных файлах, которые можно выгружать и импортировать. Среди достоинств RS отдельно нужно отметить печатные формы — в пару кликов можно создать и распечатать любой отчет, который не стыдно показать на любом совещании. Примечательно, что в RegionSoft CRM самый богатый набор горячих клавиш — это тоже значительно экономит время.

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

ClientCommunicator. Самая богатая по функционалу из бесплатных CRM, но со своими «заморочками», которые начинаются с установки. При установке КлиК скачивает порядка 500 Мб дополнительных файлов: Windows Installer, MS SQL2008R2, который обязательно будет скачиваться, даже если стоит предыдущая версия MS SQL. Процесс установки на современном компьютере занимает чуть больше, чем 40 минут.

image

Интерфейс КлиКа настойчиво напоминает MS Office 2010, очень удобно для тех, кто привык. В ходе работы открытые вкладки перегружают окно, мне откровенно не хватало 15 дюймов ноутбука, чтобы иметь желаемый обзор. При переключении между функциями даже в однопользовательской версии происходит «подвисание» до 10 секунд. Однако такой интерфейс полностью оправдывается набором функций.
Карточка товара (запись в разделе «Продукция») включает обширные данные по позиции, типы цен, единицы измерения, скидки, поставщиков. Продажи включают основную карточку записи, а также форму для SWOT-анализа и учета возражений, историю стадий продажи. Раздел «Маркетинг» позволяет вести учет маркетинговых инициатив, конкурентных предложений, информационных источников. Модуль «Персонал» дает возможность учитывать KPI, мотивацию персонала и заработную плату, диверсифицируя эффективность каждого менеджера по установленным критериям.

Отчеты в ClientCommunicator есть в модулях и реализованы отдельно, в виде OLAP. Панель показателей отображает данные по плану, факту и проценту выполнения в табличном представлении и в виде красивых «спидометров» с индикацией каждого показателя. Таблицы удобные и наглядные, чего не сказать о графических индикаторах — они красивые, но абсолютно не функциональные. Раздел «Создание отчетов» достаточно сложен по своей реализации — менеджеры, которые тестировали софт, не все справились с отчетами. Мне же был интересен OLAP от КлиКа. Выросшая на OLAPe CBOSS, в КликКе я проблем не испытала, но могу точно сказать, что это гибкое и тонко настраиваемое решение для создания отчетов практически нереально для использования обычными менеджерами по работе с клиентами — они просто не привыкли к таким конструкторам.

Из дополнительных приятных фишек: дерево несложных фильтров, наполненные справочники, горячие клавиши управления. Кстати, о клавишах. Непривычно отсутствие кнопки «Создать» (товар, продажу, контрагента и т. д.), работа с таблицами происходит при помощи правой клавиши мыши или горячих клавиш (создать — Insert).

В целом ClientCommunicator — функциональная и приятная для работы CRM, однако избыточность, медлительность и сложность построения отчетов пугают рядовых пользователей. А вот небезразличного IT-шника порадует конфигуратор для создания объектов, процедур и изменения логики системы, а также дизайнер форм, доступные даже в бесплатной версии.

Выводы и тизеры

Было бы странным среди недостатков бесплатных CRM указывать отсутствие сетевой работы или ориентированность на одно локальное место. Можно сказать одно — если перед вами хорошая, сильная бесплатная CRM с продуманным интерфейсом и юзабилити, то это отличная возможность провести полномасштабные испытания софта перед покупкой.

Мы еще не купили CRM, начинаем «обкатывать» демо-версии с более широким функционалом. Во второй части эксперимента мы продолжим разбираться с финалистами этой части и добавим новых, именитых и не очень, участников. А заодно поднимем вопрос цены и целесообразности внедрения. Надеюсь, будет что сказать.

P.S.: если вы хотите в следующем обзоре увидеть какие-то особые параметры, пишите. Постараюсь учесть все пожелания.

IPv6 под прицелом




Казалось бы, зачем сейчас вообще вспоминать про IPv6? Ведь несмотря на то, что последние блоки IPv4-адресов были розданы региональным регистраторам, интернет работает без каких-либо изменений. Дело в том, что IPv6 впервые появился в 1995 году, а полностью его заголовок описали в RFC в 1998 году. Почему это важно? Да по той причине, что разрабатывался он без учета угроз, с той же доверительной схемой, что и IPv4. И в процессе разработки стояли задачи сделать более быстрый протокол и с большим количеством адресов, а не более безопасный и защищенный.


Кратко про темпы роста


Если изучить графики, которые предоставляет региональный регистратор IP-адресов и автономных систем, то можно обнаружить, что по состоянию на первое сентября 2014 года количество зарегистрированных IPv6 автономных систем уже перевалило за 20%. На первый взгляд, это серьезная цифра. Но если брать во внимание только реальное количество IPv6-трафика в мире, то сейчас это около 6% от всего мирового интернет-трафика, хотя буквально три года назад было всего 0,5%.


Рис. 1. Реальные объемы IPv6-трафика

По самым скромным оценкам ожидается, что к концу 2015 года доля IPv6-трафика дойдет как минимум до 10%. И рост будет продолжаться. Кроме того, недавно вступил в силу специальный протокол для региональных регистраторов. Теперь новый блок IPv4-адресов будет выдан только в том случае, если компания докажет, что уже внедрила у себя IPv6. Поэтому если кому-то потребуется подсеть белых IPv4-адресов — придется внедрять IPv6. Этот факт также послужит дальнейшему росту IPv6-систем и увеличению трафика. Что же касается рядовых пользователей, то уже по всему миру начали проявляться провайдеры, которые предоставляют конечным абонентам честные IPv6-адреса. Поэтому IPv6 будет встречаться все чаще и чаще, и мы не можем оставить это без внимания.

Что нового в IPv6?


Первое, что бросается в глаза, — это адреса. Они стали длиннее, записываются в шестнадцатеричном виде и сложно запоминаются. Хотя, поработав некоторое время с IPv6, обнаруживаешь, что адреса в целом запоминаемые, особенно если используются сокращенные формы записи. Напомню, что IPv4 использует 32-битные адреса, ограничивающие адресное пространство 4 294 967 296 (2^32) возможными уникальными адресами. В случае же IPv6 под адрес уже выделено 128 бит. Соответственно, адресов доступно 2^128. Это примерно по 100 адресов каждому атому на поверхности Земли. То есть адресов должно хватить на достаточно длительное время.

Адреса записываются в виде восьми групп шестнадцатеричных значений. Например, IPv6-адрес может выглядеть как 2001:DB8:11::1. Важно отметить, что IPv6-адресов на одном интерфейсе может быть несколько, причем это стандартная ситуация. Например, на интерфейсе может быть частный адрес, белый адрес и еще по DHCPv6 приедет дополнительный адрес. И все будет штатно работать, для каждой задачи будет использоваться свой адрес. Если нужно выйти в мир, то будет использоваться белый адрес. Надо до соседнего сервера? Пойдет через частный адрес. Все это будет решаться обычным анализом поля destination.

Все IPv6-адреса делятся на две группы: линк-локал и глобал юникаст. По названию очевидно, что Link local — это адрес, который используется только в пределах одного линка. Такие адреса в дальнейшем применяются для работы целого ряда механизмов вроде автоматической настройки адреса, обнаружения соседей, при отсутствии маршрутизатора и тому подобное. Для выхода в мир такие адреса использовать не допускается.

Link local адрес назначается автоматически, как только хост выходит онлайн, чем-то отдаленно такие адреса похожи на механизмAPIPA в ОС Windows. Такой адрес всегда начинается с FE80, ну а последние 64 бита — это мак-адрес с FFFE, вставленными посередине, плюс один бит инвертируется. Механизм формирования такого адреса еще называется EUI-64. В итоге адрес будет уникальный, так как мак-адреса обычно отличаются у всех хостов. Но некоторые ОС используют рандомный идентификатор вместо механизма EUI-64.

Что еще нового


Только адресами изменения, естественно, не заканчиваются. Еще был значительно упрощен заголовок (см. рис. 2).


Рис. 2. Сравнение заголовков IPv6 и IPv4

Теперь все, что не является обязательным для маршрутизации пакета из точки в А в точку Б, стало опциональным. А раз опциональное — значит, переезжает в extension header, который лежит между IPv6-заголовком и TCP/UDP-данными. В этом самом extension-заголовке уже и проживают фрагментирование, IPsec, source routing и множество другого функционала.

Резко упростили задачу маршрутизаторам, ведь уже не надо пересчитывать контрольные суммы, и в итоге IPv6 обрабатывается быстрее, чем IPv4. Контрольные суммы убрали вовсе. Во-первых, у фрейма на уровне L2 есть CRC, во-вторых, вышележащие протоколы (TCP) тоже будут обеспечивать целостность доставки. В итоге из заголовка выбросили лишние поля, стало проще, быстрее и надежнее.

Aвтоконфигурирование и служебные протоколы


Существует два основных варианта назначения IPv6-адресов: stateless autoconfiguration — это когда роутер отправляет клиентам адрес сети, шлюза по умолчанию и прочую необходимую информацию и statefull autoconfiguration — когда используется DHCPv6-сервер. Поэтому если раньше DHCP был единственным вариантом раздачи информации, то в IPv6 он стал дополнительным.

ICMP 6-й версии тоже не остался без внимания, в него было добавлено множество фич. Например, механизм Router discovery — клиенты могут слушать, что сообщает им роутер (сообщения ICMPv6 тип 134 router advertisement, которые приходят в рамках процесса stateless autoconfiguration), и при включении могут сразу звать роутер на помощь, мол, помоги сконфигуриться (сообщения ICMPv6 тип 133 router solicitation).

Еще добавили механизм Neighbor discovery — можно сказать, что это своеобразная замена ARP, которая помогает находить мак-адреса соседей, маршрутизаторы и даже обнаруживать дублирующиеся адреса в сегменте (duplicate address detection DaD), работает исключительно по мультикасту. Чистого бродкаста в IPv6 уже нет, но не нужно забывать, что глупые копеечные свичи весь мультикаст рассылают широковещательно, в итоге часть новых механизмов сводится на нет.

Инструментарий пентестера IPv6


Перед тем как перейти к уязвимостям и атакам, неплохо бы рассмотреть, какие есть инструменты в арсенале пентестера. До недавнего времени существовал только один набор утилит для проведения атак на протоколы IPv6 и ICMPv6. Это был THC-IPV6 от небезызвестного Марка ван Хаузера, того самого автора брутфорсера THC-hydra и массы других незаменимых инструментов. Именно он в 2005 году серьезно заинтересовался этой темой и вплотную занялся ресерчем протокола IPv6. И до недавнего времени оставался первопроходцем.

Но в последний год ситуация начала меняться. Все больше исследователей обращают свое внимание на IPv6, и, соответственно, стали появляться новые утилиты и новые сканеры. Но на сегодня THC-IPV6 по-прежнему остается лучшим набором утилит для пентестера. В его комплект входит уже более 60 инструментов, разделенных на различные категории — от сканирования и митмов до флудинга и фаззинга. Но не будем забывать и тру инструмент scapy — утилиту, которая позволяет вручную создавать любые пакеты, с любыми заголовками, даже если такие вариации не предусмотрены ни в одном RFC.

Разведка в IPv6-сетях


Перед тем как атаковать цель, нужно ее как-то обнаружить, поэтому стандартный пентест обычно начинается с поиска живых хостов. Но здесь появляется проблема: мы не можем просканировать весь диапазон. Сканирование всего одной подсети затянется на годы, даже если отправлять миллион пакетов в секунду. Причина в том, что всего лишь подсеть /64 (или их еще называют префиксами) больше, чем весь интернет сегодня, причем значительно больше. Поэтому самая серьезная проблема с IPv6 — это обнаружение целей.

К счастью, выход есть. Вначале нужно будет найти AS (автономную систему), которая принадлежит цели (объекту пентеста). Сервисов, позволяющих искать по AS их владельцев, вполне достаточно, можно это делать прямо на сайтах региональных регистраторов (европейский регистратор — это RIPE NCC). Затем, зная номер AS, принадлежащей конкретной компании, можно уже искать выделенные ей IPv6-подсети.

Самый удобный такой поисковый сервис предоставляет Hurricane Electric (bgp.he.net). В итоге можно найти несколько огромных подсетей, которые, как мы уже убедились, нереально просканировать на предмет живых хостов. Поэтому нужно составлять список часто используемых адресов и проводить сканирование уже точечно по ним.

Каким образом можно собрать такой словарь? Если проанализировать, как в компаниях, которые уже внедрили IPv6, назначаются адреса клиентам, то можно выделить три основные группы: автоконфигурация, ручное назначение адресов и DHCPv6.

Автоконфигурация может осуществляться тремя способами: на основе мак-адреса, с использованием privacy option (то есть рандомно и, например, меняться раз в неделю) и fixed random (полностью случайным образом). В данной ситуации возможно сканировать только те адреса, что строятся на основе мака. В результате могут выйти подсети, сравнимые по размеру с IPv4 класса А, процесс работы с такими сетями не очень быстрый, но все равно это уже вполне реально. Например, зная, что в целевой компании массово используются ноутбуки определенного вендора, можно строить сканирование, основываясь на знаниях о том, как будет формироваться адрес.

Если адреса задаются вручную, то они могут назначаться либо случайным образом, либо по некому шаблону. Второе, естественно, в жизни встречается гораздо чаще. А паттерн может быть ::1,::2,::3 или ::1001,::1002,::1003. Также иногда в качества адреса используются порты сервисов, в зависимости от сервера: например, веб-сервер может иметь адрес ::2:80.

Если же брать DHCPv6, то в этом случае обычно адреса раздаются последовательно из пула (точно такое же поведение можно наблюдать и с обычным DHCPv4-сервером). Зачастую в DHCPv6 можно встретить пул вроде ::1000-2000 или ::100-200. Поэтому в итоге берем утилиту alive6 (она включена в комплект THC-IPV6 и, как и все рассматриваемые сегодня инструменты, по дефолту входит в Kali Linux) и запускаем:

# alive6 -p eth0 2001:67c:238::0-ffff::0-2
  Alive: 2001:db8:238:1::2 [ICMP echo-reply]
  Alive: 2001:db8:238:3::1 [ICMP echo-reply]
  Alive: 2001:db8:238:3::2 [ICMP echo-reply]
  Alive: 2001:db8:238:300::1 [ICMP echo-reply]
  Scanned 65536 systems in 29 seconds and found 4 
  systems alive


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

Но это еще не все — естественно, можно использовать и DNS. С приходом IPv6 никуда не делись трансферы DNS-зоны и брутфорсы DNS по словарю. Применив все эти техники вместе, можно обнаруживать до 80% всех включенных хостов в заданной IPv6-подсети, что очень неплохо. В случае же компрометации одного лишь хоста обнаружить всех его соседей не составит никакого труда при помощи мультикаста. Достаточно будет запустить ту же утилиту alive6, только уже с ключом -l.

Из свежих фич THC-IPV6, и в частности утилиты alive6, можно отметить возможность искать живые хосты, передавая в качестве паттерна для перебора целую IPv4-подсеть:

# alive6 -4 192.168.0/24


Если же брать классическое сканирование, то здесь практически ничего не изменилось. Тот же Nmap, те же варианты сканирования портов, единственное отличие в том, что теперь сканировать можно только один хост за раз, но это вполне очевидное решение.

Пожалуй, единственная дополнительная техника при сканировании портов — это сканирование IPv4 вначале, а затем получение IPv6-информации по этим хостам. То есть некое расширение поверхности атаки. Для этого можно использовать как вспомогательный модуль метасплойта ipv6_neighbor, так и отдельные скрипты ipv6_surface_analyzer. Работают они по схожему принципу — принимают на входе IPv4-подсеть, сканируют ее, находят живые хосты, проверяют порты на открытость, а затем, определив MAC-адрес, высчитывают по нему IPv6-адрес и уже пробуют работать по нему. Иногда это действительно помогает, но в некоторых случаях (privacy option) IPv6-адреса обнаружить не удается, даже несмотря на то, что они есть.

INFO


При использовании протокола IPv4 и ARP достаточно полезно было иногда смотреть ARP-кеш; что на линуксе, что на Windows-платформе это можно было сделать, используя команду arp -a.
Теперь же, в случае IPv6, в линуксе, чтобы посмотреть соседей, используется команда ip -6 neighbor show, а в Windows среде это можно сделать командой netsh interface ipv6 show neighbors.


Угрозы периметра IPv6



Если рассмотреть внешний периметр, то можно обнаружить, что многие компании, которые уже начали внедрять IPv6, не спешат закрывать свои административные порты (SSH, RDP, Telnet, VNC и так далее). И если IPv4 уже почти все стараются как-то фильтровать, то про IPv6 или забывают, или не знают, что их нужно защищать так же, как и в случае с IPv4. И если можно отчасти понять используемый IPv4 телнет — например, ограниченная память или CPU не позволяют в полной мере использовать SSH, — то каждое устройство, которое поддерживает сегодня IPv6, просто гарантированно будет поддерживать и протокол SSH. Бывают даже случаи, когда ISP выставляют в мир административные порты IPv6 на своих роутерах. Выходит, что даже провайдеры более уязвимы к IPv6-атакам. Происходит это по различным причинам. Во-первых, хороших IPv6-файрволов еще не так много, во-вторых, их еще нужно купить и настроить. Ну и самая главная причина — многие даже и не подозревают об угрозах IPv6. Также бытует мнение, что пока нет IPv6-хакеров, малвари и IPv6-атак, то и защищаться вроде как не от чего.

Угрозы, поджидающие внутри LAN


Если вспомнить IPv4, то там обнаружится три атаки, которые эффективны и по сей день в локальных сетях, — это ARP spoofing, DHCP spoofing, а также ICMP-редиректы (подробно этот класс атак освещался во время моего выступления на PHDays, так что можешь поискать соответствующее видео в Сети).

В случае же протокола IPv6, когда атакующий находится в одном локальном сегменте с жертвой, ситуация, как ни странно, остается примерно такой же. Вместо ARP появился NDP, на смену DHCP пришла автоконфигурация, а ICMP просто обновился до ICMPv6. Важно то, что концепция атак осталась практически без изменений. Но кроме того, добавились новые механизмы вроде DAD, и, соответственно, сразу же появились новые векторы и новые атаки.

Протокол обнаружения соседей (Neighbor Discovery Protocol, NDP) — это протокол, с помощью которого IPv6-хосты могут обнаружить друг друга, определить адрес канального уровня другого хоста (вместо ARP, который использовался в IPv4), обнаружить маршрутизаторы и так далее. Чтобы этот механизм работал, а работает он с использованием мультикаста, каждый раз, когда назначается линк-локал или глобал IPv6-адрес на интерфейс, хост присоединяется к мультикаст-группе. Собственно, используется всего два типа сообщений в процессе neighbor discovery: запрос информации, или NS (neighbor solicitation), и предоставление информации — NA (neighbor advertisement).
Взаимодействие в таком режиме можно увидеть на рис. 3.


Рис. 3. Штатная работа ND

В результате атакующему нужно всего лишь запустить утилиту parasite6, которая будет отвечать на все NS, пролетающие в отдельно взятом сегменте (см. рис. 4). Перед этим нужно не забыть включить форвардинг (echo 1 > /proc/sys/net/ipv6/conf/all/forwarding), в противном случае произойдет не MITM-атака, а DoS.


Рис. 4. Работа утилиты parasite6

Минусами такой атаки является то, что атакующий будет пытаться отравить ND-кеш всех хостов, что, во-первых, шумно, во-вторых, затруднительно в случае больших объемов трафика. Поэтому можно взять scapy и провести эту атаку вручную и прицельно. Сначала необходимо заполнить все необходимые переменные.

>>> ether=Ether(src="00:00:77:77:77:77",
dst="00:0c:29:0e:af:c7")
Вначале идут адреса канального уровня, в качестве адреса отправителя выступает мак-адрес атакующего, в качестве адреса получателя — мак-адрес жертвы.
>>> ipv6=IPv6(src="fe80::20d:edff:fe00:1",
dst="fe80::fdc7:6725:5b28:e293")
Далее задаются адреса сетевого уровня, адрес отправителя спуфится (на самом деле это адрес роутера), адрес получателя — это IPv6-адрес жертвы.
>>> na=ICMPv6ND_NA(tgt="fe80::20d:edff:
fe00:1", R=0, S=0, O=1)


Третьей переменной нужно указать правильно собранный пакет NA, где ICMPv6ND_NA — это ICMPv6 Neighbor Discovery — Neighbor Advertisement, а tgt — это собственно адрес роутера, который анонсируется как адрес атакующего. Важно правильно установить все флаги: R=1 означает, что отправитель является роутером, S=1 скажет о том, что анонс отправляется в ответ на NS-сообщение, ну а O=1 — это так называемый override-флаг.

>>> lla=ICMPv6NDOptDstLLAddr
(lladdr="00:00:77:77:77:77")
Следующая переменная — это Link local адрес ICMPv6NDOptDstLLAddr (ICMPv6 Neighbor Discovery Option — Destination Link-Layer). Это мак-адрес атакующего.
>>> packet=ether/ipv6/na/lla
Осталось собрать пакет в единое целое, и можно отправлять такой пакет в сеть.
>>> sendp(packet,loop=1,inter=3)


Значение loop=1 говорит о том, что отправлять нужно бесконечно, через каждые три секунды.
В итоге через некоторое время жертва обновит свой кеш соседей и будет отправлять весь трафик, который предназначается маршрутизатору, прямо в руки атакующему. Нужно отметить, что для того, чтобы создать полноценный MITM, потребуется запустить еще один экземпляр scapy, где адреса будут инвертированы для отравления роутера. Как видишь, ничего сложного.

Также стоит отметить, что в IPv6 не существует понятия gratuitous NA, как это было во времена ARP (gratuitous ARP — это ARP-ответ, присланный без запроса). Но вместе с тем кеш ND живет недолго и быстро устаревает. Это было разработано, чтобы избегать отправки пакетов на несуществующие MAC-адреса. Поэтому в сети IPv6 обмен сообщениями NS — NA происходит очень часто, что сильно играет на руку атакующему.

Угрозы конечных хостов


И раз уж заговорили про RA, то плавно перейдем к угрозам конечных хостов, и в частности к тем хостам, работа которых с IPv6 не планировалась. То есть рассмотрим атаку на хосты, работающие в дефолтной конфигурации IPv6, в обычной IPv4-сети. Что произойдет, если любая современная ОС получит пакет RA? Так как любая система сейчас поддерживает IPv6 и ожидает такие пакеты, то она сразу превратится в так называемый дуал стек. Это ситуация, когда в пределах одной ОС используется и IPv4, и IPv6 одновременно. При этом сразу же откроется целый ряд ранее недоступных векторов. Например, можно будет сканировать цель, ведь IPv4 обычно фильтруется, а про IPv6, как уже знаем, зачастую вообще не думают.

Кроме того, в большинстве ОС IPv6 имеет приоритет над IPv4. Если, например, придет запрос DNS, то большая вероятность, что IPv6 сработает раньше. Это открывает огромный простор для различных MITM-атак. Для проведения одной из самых эффективных потребуется разместить свой зловредный IPv6-маршрутизатор. Каждый маршрутизатор IPv6 должен присоединиться к специальной мультикаст-группе. Это FF02::2. Как только роутер присоединится к такой мультикаст-группе, он сразу же начинает рассылать сообщения — RA. Сisco-роутеры рассылают их каждые 200 с по дефолту. Еще один нюанс состоит в том, что клиентам не нужно ждать 200 с, они отправляют RS-сообщение — Router Solicitation — на этот мультикаст-адрес и таким образом незамедлительно требуют всю информацию. Весь этот механизм называется SLAAC — Stateless Address Autoconfiguration. И соответственно была разработана атака на него с очевидным названием SLAAC attack.

Атака заключается в том, что нужно установить свой роутер (не стоит понимать буквально, в роли роутера может выступать любой линукс или даже виртуальная машина), который будет рассылать сообщения RA, но это только полдела. Также атакующему потребуется запустить DHCPv6-сервер, DNSv6 и NAT64-транслятор. В качестве сервиса, способного рассылать сообщения RA, можно использовать Router Advertisement Daemon (radvd), это опенсорсная реализация IPv6-роутера. В итоге после правильной конфигурации всех демонов жертва получит RA и превратится в дуал стек и весь трафик жертвы будет абсолютно незаметно идти через IPv6.

На маршрутизаторе атакующего этот трафик будет перебиваться натом в обычный IPv4 и затем уже уходить на настоящий роутер. DNSv6-запросы также будут иметь приоритет и также будут обрабатываться на стороне атакующего.

Таким образом, атакующий успешно становится посередине и может наблюдать весь трафик жертвы. А жертва при этом ничего не будет подозревать. Такая атака несет максимальную угрозу, работает даже при использовании IPv4-файрволов и статических ARP-записей, когда, казалось бы, воздействовать на жертву нет никакой возможности.

Как же защищать IPv6


Если говорить про защиту от обозначенных выше атак, то сперва очевидно, что на периметре необходимо внимательно фильтровать весь трафик и отключать неиспользуемые сервисы, также отдельное внимание нужно уделять административным сервисам. Для того чтобы сократить воздействие локальных атак, направленных на служебный протокол ICMPv6, можно ограничивать поверхность таких атак, разбивая большие сети на подсети (что еще называется микросегментацией). Одна и та же сетевая инфраструктура может быть разделена на несколько вланов, с отдельным IPv6-префиксом для каждого такого влана. В таком случае атакующий сможет атаковать хосты, только находящиеся с ним в одном влане, что уже сильно ограничит возможный урон от атак.


Рис. 5. Схема SLAAC attack


Рис. 6. Результат SLAAC attack

Отдельно существует защита от ложных RA-сообщений, которые, как известно, должны приходить только от маршрутизаторов. Компания Cisco реализовала фичу под названием Router Advertisement Guard, которая предотвращает инжект недоверенных RA-сообщений, отдельно помечая потенциально небезопасные порты. То есть пакеты RA просто не будут приниматься с пользовательских портов. Работает эта фича по аналогии с DHCP-снупингом. Единственный минус в том, что доступна такая фича только на определенном классе железок — на каталистах серий 2960S, 3560 и 3750. Кроме того, в 2012 году появились DHCPv6 Guard и NDP Snooping, опять же это аналоги DHCP Snooping и Dynamic ARP Inspection из мира IPv4. Доступны эти защитные механизмы на каталистах 4500/4948 и на роутерах серии 7600.

Если рассматривать защиту конечных хостов, то все последние версии Windows позволяют полностью отключить обработку RA-сообщений. В случае если все IPv6-параметры конфигурируются вручную, это может быть неплохим вариантом, хотя и несколько ломает канонические механизмы IPv6. Выключается достаточно легко, прямо на интерфейсе командой

netsh int ipv6 set int X routerdiscovery=disabled


где X — это индекс интерфейса (просмотреть индексы IPv6-интерфейсов можно командой netsh int ipv6 show int). Проверяется результат командой netsh int ipv6 show int X.

Если же рассмотреть ситуацию с обнаружением атак IPv6, то в целом там все хорошо. Детектить IPv6-атаки достаточно легко, но пока их сложно превентить.

Завершаем рассказ


Что же имеем в сухом остатке? Как оказалось, сам по себе протокол IPv6 не безопаснее, но при этом и не дырявее, чем IPv4. Проблема лежит в недостаточных знаниях и опыте работы с этим протоколом. Нужно фильтровать IPv6 на периметре и выключать его, если он не используется на конечных устройствах. Многие люди считают, что IPv6 значительно безопаснее, чем IPv4, потому, что IPv6 требует использования IPsec. Но это миф. Да, IPsec может сразу работать в среде IPv6, но ни разу не является обязательным. IPv6 делает некоторые вещи лучше, другие — хуже, но большинство вещей просто отличаются от того, к чему все успели привыкнуть. Другими словами, протокол IPv6 не более или менее безопасен, чем IPv4, протокол IPv6 просто уникален и несет свои собственные соображения на счет безопасности.

Автор: Александр Дмитриенко, PentestIT



Впервые опубликовано в журнале «Хакер» от 11/2014.

Mikrotik. Failover. Load Balancing

из песочницы

Когда у меня встала необходимость разобраться, как сделать failover или load balancing, имея два и более каналов в мир, я нашел множество статей и инструкций, в которых описывались рабочие конфигурации. Но почти нигде не нашел разъяснения, как все работает, и описания отличий разных вариантов. Хочу исправить эту несправедливость и собрать простейшие варианты построения failover и load balancing конфигураций в одной статье.

Итак, у нас есть роутер, который соединяет нашу локальную сеть и два канала в интернет (основной ISP1 и резервный ISP2).

Давайте рассмотрим что же мы можем сделать:

Сразу предупрежу: несмотря на то, что в этой статье буду все описывать для mikrotik, не буду касаться темы скриптов

Failover


image

У нас появился резервный канал, в который можно направить трафик при отказе основного. Но как сделать, чтобы mikrotik понял, что канал упал?

Простейшее резервирование каналов


Простейший failover можно настроить, используя приоритет маршрута (distance у mikrotik/cisco, metric в linux/windows), а так же механизм проверки доступности шлюза — check-gateway.

В приведенной ниже конфигурации весь интернет трафик по умолчанию ходит через 10.100.1.254 (ISP1). Но как только адрес 10.100.1.254 станет недоступным (а маршрут через него неактивным) — трафик пойдет через 10.200.1.254 (ISP2).

конфигурация: простейший failover
# Настроим сети провайдеров:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс 
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
###Обеспечение резервирования каналов традиционным способом###
# укажем 2 default gateway с разными приоритетами
/ip route add dst-address=0.0.0.0/0 gateway=10.100.1.254 distance=1 check-gateway=ping
/ip route add dst-address=0.0.0.0/0 gateway=10.200.1.254 distance=2 check-gateway=ping

check-gateway=ping для mikrotik обрабатывается так:
Периодически (каждые 10 секунд) шлюз проверяется отсылкой на него ICMP пакета (ping). Потерянным пакет считается, если он не вернулся в течении 10 секунд. После двух потерянных пакетов шлюз считается недоступным. После получения ответа от шлюза он становится доступным и счетчик потерянных пакетов сбрасывается.


Обеспечение failover с более глубоким анализом канала


В прошлом примере все замечательно, кроме ситуации, когда шлюз провайдера виден и пингуется, но интернета за ним нет. Нам бы это здорово помогло, если бы можно было принимать решение о жизнеспособности провайдера, пингуя не сам шлюз, а что-то за ним.

Я знаю два варианта решения этой инженерной задачи. Первый и самый распространенный — использовать скрипты, но так как в этой статье мы скрипты не трогаем, остановимся подробнее на втором. Он подразумевает не совсем корректное использование параметра scope, но поможет нам прощупать канал провайдера глубже, чем до шлюза.
Принцип прост:
Вместо традиционного указания default gateway=шлюз провайдера, мы скажем роутеру что default gateway это какой-то извсегда_доступных_узлов (например 8.8.8.8 или 8.8.4.4) и он в свою очередь доступен через шлюз провайдера.

конфигурация: failover с более глубоким анализом канала
# Настроим сети провайдеров:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс 
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
###Обеспечение failover c более глубоким анализом канала###
#с помощью параметра scope укажем рекурсивные пути к узлам 8.8.8.8 и 8.8.4.4
/ip route add dst-address=8.8.8.8 gateway=10.100.1.254 scope=10
/ip route add dst-address=8.8.4.4 gateway=10.200.1.254 scope=10
# укажем 2 default gateway через узлы путь к которым указан рекурсивно
/ip route add dst-address=0.0.0.0/0 gateway=8.8.8.8 distance=1 check-gateway=ping
/ip route add dst-address=0.0.0.0/0 gateway=8.8.4.4 distance=2 check-gateway=ping

Теперь разберем, что происходит чуть подробнее:
Хитрость в том, что шлюз провайдера не знает о том, что 8.8.8.8 или 8.8.4.4 — это роутер и направит трафик по обычному пути.
Наш mikrotik считает, что по умолчанию весь интернет трафик нужно отправлять на 8.8.8.8, который напрямую не виден, но через 10.100.1.254 доступен. А если пинг на 8.8.8.8 пропадает (напомню что путь к нему у нас жестко указан через шлюз от ISP1) то mikrotik начнет слать весь интернет трафик на 8.8.4.4, а точнее на рекурсивно определенный 10.200.1.254 (ISP2).

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

Load Balancing


Теперь давайте рассмотрим другую схему:

image

В ней второй второй канал уже не резервный, а равноценный. Почему бы не использовать оба канала одновременно, повысив таким образом пропускную способность?

Начинаем настраивать Load Balancing


Первое правило Load Balancing — следить за соединениями: на пришедшее извне соединение отвечать с того же адреса, на который оно пришло. Для исходящих соединений — отправлять пакеты только через тот адрес, с которым установилось соединение.

Второе, что тоже важно понимать — нужно разделять понятия входящего и исходящего трафика. Дело в том, что для исходящего трафика роутер может решать, по какому пути он пойдет, а входящий трафик для него как «трафик Шредингера». Пока его нет, наш mikrotik не знает, через какой интерфейс он придет, а когда пришел — менять интерфейс уже поздно.

Третье — балансировка каналов не является резервированием. Это две отдельные функции.

Кстати почему при разделе трафика мы оперируем соединениями, а не пакетами?
Почитайте, как работает TCP протокол. Если коротко — задача TCP протокола не только швырнуть пакетом в получателя, но и проконтролировать, как тот его принял. Делается это с помощью установки соединения, в рамках которого, собственно, и передаются пакеты данных — вместе со служебной информацией. Если оперировать пакетами и забыть про соединения, то возможны ситуации, когда удаленный хост, установив соединение с одним адресом, просто отбросит часть пакетов пришедшую со второго — «неправильного» адреса.


Готовимся принять «трафик Шредингера»


Итак, при любом варианте балансировки канала нам нужно сначала подготовиться к принятию входящего трафика и научить mikrotik отвечать на входящие соединения в тот же канал, из которого они пришли. С помощью маркировки соединений и последующей маркировки маршрутов для них мы, по сути, делаем несколько таблиц маршрутизации, отдельных для каждого внешнего адреса.

начальная конфигурация для load balancing с двумя внешними IP адресами
# Настроим сети провайдеров:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс 
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
#Пометим каждое соединение пришедшее снаружи и адресованное нашему роутеру:
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP1 new-connection-mark=cin_ISP1
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP2 new-connection-mark=cin_ISP2
#что бы отвечать через те же интерфейсы, откуда пришли запросы, поставим соответствующую роутинг-марку на каждое соединение.
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP1 new-routing-mark=rout_ISP1 passthrough=no
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP2 new-routing-mark=rout_ISP2 passthrough=no
#добавим default gateway в каждую из промаркированных таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=rout_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=rout_ISP2 check-gateway=ping

Таким образом mikrotik будет проводить каждый пакет помеченного соединения по соответствующей таблице маршрутизации и внешние адреса (10.100.1.1, 10.200.1.1) будут доступны извне без путаницы в каналах и маршрутах.

Делим исходящий трафик


Для распределения исходящего трафика по интерфейсам, нам всего-то нужно повесить соответствующую марку маршрута на соединение. Сложность в том, что нужно решить на какое соединение вешать метку ISP1, а на какое ISP2.

Существует несколько вариантов разделения соединений по группам:

1) Делим исходящий трафик, прикручивая марку намертво


Правила, балансирующие трафик мы можем прописать жестко:
Например мы хотим настроить важные для нас протоколы HTTP(80 port), HTTPS (443 port), POP (110 port), SMTP (25 port) через ISP1, а весь остальной трафик пустить через второго провайдера:

конфигурация с балансировкой канала по жестко прописанным правилам
# Настроим сети провайдеров:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс 
/ip add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
#Пометим каждое соединение пришедшее снаружи и адресованное нашему роутеру:
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP1 new-connection-mark=cin_ISP1
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP2 new-connection-mark=cin_ISP2
#что бы отвечать через те же интерфейсы, откуда пришли запросы, поставим соответствующую роутинг-марку на каждое соединение.
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP1 new-routing-mark=rout_ISP1 passthrough=no
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP2 new-routing-mark=rout_ISP2 passthrough=no
#добавим default gateway в каждую из промаркированных таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=rout_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=rout_ISP2 check-gateway=ping
#failover через второго провайдера для каждого из шлюзов
/ip route add distance=2 gateway=10.200.1.254 routing-mark=rout_ISP1 
/ip route add distance=2 gateway=10.100.1.254 routing-mark=rout_ISP2 
# отправим трафик идущий к портам 80,443,110,25 на ISP1
/ip firewall mangle add chain=prerouting action=mark-routing new-routing-mark="lan_out_ISP1" passthrough=no dst-port=80,443,110,25 protocol=tcp 
#а весь остальной трафик на ISP2:
/ip firewall add chain=prerouting action=mark-routing new-routing-mark="lan_out_ISP2" passthrough=no
#добавим default gateway в каждую из промаркированных для LAN трафика таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=lan_out_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=lan_out_ISP2 check-gateway=ping
#failover через второго провайдера для каждого из шлюзов
/ip route add distance=2 gateway=10.200.1.254 routing-mark=lan_out_ISP1 
/ip route add distance=2 gateway=10.100.1.254 routing-mark=lan_out_ISP2 


2) Делим исходящий трафик, выбирая каждое Н-ое соединение


Можем делить соединения по-порядку. Первые налево, вторые — направо. Все просто.

конфигурация с балансировкой канала по Н-ному соединению:
# Настроим сети провайдеров:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс 
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
#Пометим каждое соединение пришедшее снаружи и адресованное нашему роутеру:
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP1 new-connection-mark=cin_ISP1
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP2 new-connection-mark=cin_ISP2
#что бы отвечать через те же интерфейсы, откуда пришли запросы, поставим соответствующую роутинг-марку на каждое соединение.
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP1 new-routing-mark=rout_ISP1 passthrough=no
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP2 new-routing-mark=rout_ISP2 passthrough=no
#добавим default gateway в каждую из промаркированных для внешних адресов таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=rout_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=rout_ISP2 check-gateway=ping
#из каждых двух соединений первое пометим на отсылку через ISP1
/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=lan_out_ISP1 nth=2,1
#а второе на отсылку через ISP2
/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=lan_out_ISP2 nth=2,2
#добавим default gateway в каждую из промаркированных для LAN трафика таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=lan_out_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=lan_out_ISP2 check-gateway=ping
#failover через второго провайдера для каждого из шлюзов
/ip route add distance=2 gateway=10.200.1.254 routing-mark=lan_out_ISP1 
/ip route add distance=2 gateway=10.100.1.254 routing-mark=lan_out_ISP2 


3) Делим исходящий трафик, используя PCC (per connection classifier)


PCC подходит к дележу трафика чуть сложнее. Он разделяет трафик по группам, основываясь на данных TCP заголовка (src-address, dst-address, src-port, dst-port).

конфигурация с балансировкой канала по PPC:
# Настроим сети провайдеров:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс 
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
#Пометим каждое соединение пришедшее снаружи и адресованное нашему роутеру:
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP1 new-connection-mark=cin_ISP1
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP2 new-connection-mark=cin_ISP2
#что бы отвечать через те же интерфейсы, откуда пришли запросы, поставим соответствующую роутинг-марку на каждое соединение.
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP1 new-routing-mark=rout_ISP1 passthrough=no
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP2 new-routing-mark=rout_ISP2 passthrough=no
#добавим default gateway в каждую из промаркированных таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=rout_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=rout_ISP2 check-gateway=ping
#failover через второго провайдера для каждого из шлюзов
/ip route add distance=2 gateway=10.200.1.254 routing-mark=rout_ISP1 
/ip route add distance=2 gateway=10.100.1.254 routing-mark=rout_ISP2 
#используя PPC разделим трафик на две группы по исх. адресу и порту
/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=lan_out_ISP1 per-connection-classifier=src-address-and-port:2/0
/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=lan_out_ISP2 per-connection-classifier=src-address-and-port:2/1
#добавим default gateway в каждую из промаркированных для LAN трафика таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=lan_out_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=lan_out_ISP2 check-gateway=ping
#failover через второго провайдера для каждого из шлюзов
/ip route add distance=2 gateway=10.200.1.254 routing-mark=lan_out_ISP1 
/ip route add distance=2 gateway=10.100.1.254 routing-mark=lan_out_ISP2 


Делим исходящий трафик, используя ECMP (equal cost multipath routing)


На мой взгляд самый простой и вкусный вариант разделения траффика:

конфигурация с балансировкой канала по ECMP
# Настроим сети провайдеров:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс 
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
#Пометим каждое соединение пришедшее снаружи и адресованное нашему роутеру:
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP1 new-connection-mark=cin_ISP1
/ip firewall mangle add action=mark-connection chain=input in-interface=ISP2 new-connection-mark=cin_ISP2
#что бы отвечать через те же интерфейсы, откуда пришли запросы, поставим соответствующую роутинг-марку на каждое соединение.
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP1 new-routing-mark=rout_ISP1 passthrough=no
/ip firewall mangle add action=mark-routing chain=output connection-mark=cin_ISP2 new-routing-mark=rout_ISP2 passthrough=no
#добавим default gateway в каждую из промаркированных таблиц маршрутизации:
/ip route add distance=1 gateway=10.100.1.254 routing-mark=rout_ISP1 check-gateway=ping
/ip route add distance=1 gateway=10.200.1.254 routing-mark=rout_ISP2 check-gateway=ping
#промаркируем весь траффик из локальной сети
/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=mixed
#используем ECMP для балансировки траффика из локальной сети
/ip route add dst-address=0.0.0.0/0 gateway=10.100.1.254,10.200.1.254 routing-mark=mixed

Mikrotik сам поделит трафик по шлюзам, используя round-robin алгоритм.

Кстати, в версии 6.Х RouterOS mikrotik поломал check-gateway в ECMP, так что использовать конструкцию
/ip route add gateway=10.100.1.254,10.200.1.254 check-gateway=ping можно и логично, но абсолютно бесполезно.
Для пометки неживых маршрутов в ECMP нужно создать дополнительные маршруты, которые используют каждый из gateway по-отдельности. С включенным check-gateway разумеется. Помечая маршрут неактивным, mikrotik делает это для всех.

И последнее немаловажное замечание про скорость каналов


Возьмем 2 неравнозначных канала, например, 100 мбит и 50 мбит. Сбалансируем их через Nth, PCC или ECMP. Какую суммарную пропускную способность получим?

На самом деле — где-то около 100 мбит (самый слабый канал Х раз).
Происходит это потому, что mikrotik понятия не имеет о пропускной способности каналов, он ее не измеряет. Он просто делит трафик на относительно равные группы.

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

Например
в ECMP это можно сделать указав более скоростной шлюз несколько раз, тем самым повышая частоту его использования.
/ip route add dst-address=0.0.0.0/0 gateway=10.100.1.254,10.100.1.254,10.200.1.254


В PCC тоже можно сделать неравные группы:

/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=lan_out_ISP1 per-connection-classifier=src-address-and-port:3/0
/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=lan_out_ISP1 per-connection-classifier=src-address-and-port:3/1
/ip firewall mangle add src-address=10.1.1.0/24 action=mark-routing chain=prerouting new-routing-mark=lan_out_ISP2 per-connection-classifier=src-address-and-port:3/2


Спасибо за внимание.

Удачи в настройках безотказных систем маршрутизации.

6434
237
vdemchuk 19,2