пятница, 19 июня 2015 г.

Разработка ACL для DES-3200-28/C1

Недавно наконец-то закончил разбираться с ACL-ками для ревизии C1. Коммутаторы DES-3200-28 этой ревизии являются самыми распространенными в моей сети - их число приближается к 900. Долгое время они не имели вообще никаких ACL - ситуацию спасали сегментация трафика и влан-на-коммутатор - но хотелось дополнительной защиты от потенциального спуфинга.

Итак, задачи, которые должны решать ACL:

  • Блокировка трафика от абонентов к сетям управления.
  • Блокировка определенных портов для предотвращения доступа к общим сетевым ресурсам.
  • Блокировка неправильных ARP-пакетов от абонентов (в целях предотвращения ARP-spoofing'а).
  • Блокировка IP-пакетов с поддельными SRC IP-адресами (IP-Spoofing) в целях предотвращения DDoS-атак и исчерпания пула NAT.
  • Отправка приоритетного трафика (телевидение) в определенную очередь (резервирование полосы пропускания).
  • Блокировка мультикаста от абонентов.
  • Разрешение любого трафика с порта (включается вручную).
На коммутаторах ревизии C1 логика работы ACL менялась в процессе разработки ПО. В результате этого не вся информация, приведенная на форумах и в официальных презентациях, является актуальной.

Сейчас все выглядит так:
  • На коммутаторе может быть всего 4 ACL профиля, причем 2 из них уже созданы - это Ethernet и IP.
  • Можно создать еще два профиля на выбор из набора Ethernet, IP, IPv6 и PCF, причем PCF профиль может быть всего один.
  • Кадр сопоставляется с правилами последовательно, так, как идут правила в профилях. Профили тоже проверяются последовательно. То есть все точно также, как и на других моделях.
  • В PCF правила можно добавлять до 4-х chunk по 4 байта каждый.
Ограничения по количеству профилей накладывают ограничения и на общую структуру правил. То есть, если один чанк уже был использован с одной маской, то именно в эту маску именно в этом профиле и придется уложить все правила, где проверяются соответствующие чанку байты.

Примечание: Соответствие chunk и байт смотри тут.

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

Конкретно замедитировав, я остановился на следующей логике:
  1. Профиль #1 (vip): Безусловно разрешается трафик для нужных портов. Настраивается исключительно вручную и при необходимости.
  2. Профиль #2 (vlandscp): Разрешается трафик для управляющих и служебных сетей (коммутаторы, камеры, wi-fi). Меняется приоритет правильным мультикаст-группам.
  3. Профиль #3 (security): Запрещается мультикаст от абонентов и некоторые не очень хорошие TCP порты
  4. Профиль #4 (pcf): Запрещается трафик к служебным сетям от абонентов. Разрешаются только корректные ARP и source IP. Остальные ARP и IP для абонентов блокируются.

После разбирательств с QoS и идеи вообще не фильтровать трафик на служебных портах профиль №2 потерял свою актуальность. Здесь я оставлю его просто в качестве примера правил.

Профиль vip:
create access_profile profile_id 1 profile_name vip ethernet source_mac 00-00-00-00-00-00
#to manually allow any traffic for port X add following rule:
#config access_profile profile_name vip add access_id auto_assign ethernet source_mac 00-00-00-00-00-00 port X permit


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

create access_profile profile_id 2 profile_name vlandscp ip destination_ip_mask 255.255.248.0 vlan 0xFF0
#allow vlans with tag 0-15, 16-31 (management) 448-463, 464-479 (wi-fi), 576-591 (cams 586)
config access_profile profile_name vlandscp add access_id auto_assign ip vlan_id 1 port all permit
config access_profile profile_name vlandscp add access_id auto_assign ip vlan_id 16 port all permit
config access_profile profile_name vlandscp add access_id auto_assign ip vlan_id 448 port all permit
config access_profile profile_name vlandscp add access_id auto_assign ip vlan_id 464 port all permit
config access_profile profile_name vlandscp add access_id auto_assign ip vlan_id 576 port all permit
 

#replace priority on multicast groups in range 239.1.8.0/21
config access_profile profile_name vlandscp add access_id 64 ip destination_ip 239.1.8.0 port [up] permit priority 6 replace_dscp_with 48
config access_profile profile_name vlandscp add access_id 64 ip destination_ip 239.1.8.0 port [pu] permit priority 6 replace_dscp_with 48


Если профиль vip имел тип ethernet, то vlandscp имеет тип ip (оба эти профиля зарезервированы и уже созданы системой). В последнем случае профиль создан с destination_ip_mask для сетей /21 и диапазона из 16 vlan. Последнее достигается из-за использования бинарной/неполной маски 0xFF0.

Первые 5 правил разрешают трафик в 5 диапазонах из 16 служебных vlan. Следующие два правила отправляют телевидение в 6-ю очередь и переписывают метку dscp.

Повторюсь, от профиля vlandscp я отказался, в данном случае это всего лишь демонстрация правил.

Фактически весь трафик попадает под обработку только двух оставшихся профилей - security и pcf.

Профиль security:

create access_profile profile_id 3 profile_name security ip destination_ip_mask 240.0.0.0 tcp dst_port_mask 0xFFFF
#deny multicast from subscribers
config access_profile profile_name security add access_id auto_assign ip destination_ip 224.0.0.0 port [ss] deny
#deny TCP 135,139,445,2869,3587,5357,5358
config access_profile profile_name security add access_id auto_assign ip tcp dst_port  135 port [ss] deny
config access_profile profile_name security add access_id auto_assign ip tcp dst_port  139 port [ss] deny
config access_profile profile_name security add access_id auto_assign ip tcp dst_port  445 port [ss] deny
config access_profile profile_name security add access_id auto_assign ip tcp dst_port 2869 port [ss] deny
config access_profile profile_name security add access_id auto_assign ip tcp dst_port 3587 port [ss] deny
config access_profile profile_name security add access_id auto_assign ip tcp dst_port 5357 port [ss] deny
config access_profile profile_name security add access_id auto_assign ip tcp dst_port 5358 port [ss] deny


Сначала блокируется multicast с абонентских портов, после чего блокируются некоторые не очень нужные абоненту TCP-порты. В моем случае блокировка TCP-портов несколько избыточна, но я решил оставить ее на всякий случай. Остальной трафик для обнаружения сетевых ресурсов будет заблокирован из-за сегментации трафика, ACL на маршрутизаторе и vlan, ограничивающегося коммутатором.

Ну и самый интересный профиль - pcf:
create access_profile profile_id 4 profile_name pcf packet_content_mask offset_chunk_1 3 0xFFFF offset_chunk_2 7 0xFFFFFEF8 offset_chunk_3 8 0xFFF80000
#deny networks 172.16.0.0/13 and 10.99.0.0/13 for subscribers
config access_profile profile_name pcf add access_id 8 packet_content offset_chunk_1 0x0800 offset_chunk_3 0xAC100000 port [ss] deny
config access_profile profile_name pcf add access_id 9 packet_content offset_chunk_1 0x0800 offset_chunk_3 0x0A600000 port [ss] deny
#allow specific source network (10.XX.YY.port_N*8 0.0.1.7) for a customer
config access_profile profile_name pcf add access_id
auto_assign packet_content offset_chunk_1 0x0800 offset_chunk_2 0x0A(fn_2oct#custom1)(fn_3oct#custom1)08 port  [ss#1] permit
config access_profile profile_name pcf add access_id
auto_assign packet_content offset_chunk_1 0x0800 offset_chunk_2 0x0A(fn_2oct#custom1)(fn_3oct#custom1)10 port  [ss#2] permit
...
#permit ARP with correct 4th octet (between port_N*8 and port_N*8+7)
config access_profile profile_name pcf add access_id
auto_assign packet_content offset_chunk_1 0x0806 offset_chunk_3 0x(fn_3oct#custom1)080000 port  [ss#1] permit
config access_profile profile_name pcf add access_id auto_assign packet_content offset_chunk_1 0x0806 offset_chunk_3 0x(fn_3oct_p1#custom1)080000 port  [ss#1] permit
config access_profile profile_name pcf add access_id auto_assign packet_content offset_chunk_1 0x0806 offset_chunk_3 0x(fn_3oct#custom1)100000 port  [ss#2] permit
config access_profile profile_name pcf add access_id auto_assign packet_content offset_chunk_1 0x0806 offset_chunk_3 0x(fn_3oct_p1#custom1)100000 port  [ss#2] permit

...
#deny IP
config access_profile profile_name pcf add access_id 254 packet_content offset_chunk_1 0x0800 port [ss] deny
#deny ARP
config access_profile profile_name pcf add access_id 255 packet_content offset_chunk_1 0x0806 port [ss] deny


Обратите внимание на используемые чанки и их маски: offset_chunk_1 3 0xFFFF, offset_chunk_2 7 0xFFFFFEF8 и offset_chunk_3 8 0xFFF80000.

В этом профиле мы фильтруем ethertype, ip src, ip dst, arp src. Посмотрим на расположение этих данных в структуре кадра:
ethertype - байты 12  и 13
arp src ip - байты 28, 29, 30 и 31
ip src - байты 26, 27, 28  и 29
ip dst - байты 30, 31, 32 и 33

Поэтому согласно приведенной выше таблице нас интересуют чанки №3, №7 и №8, которые включают в себя все нужные нам байты. Самое забавное в нашей ситуации то, что arp src ip находится "между" чанками 7 и 8, т.е. захватывает вторую половину 7 чанка и первую половину 8-го чанка. При этом, как я уже упоминал выше, мы можем использовать каждый чанк только 1 раз. Поэтому придется строить правила с учетом этого нюанса.

Разберем что именно нам надо описать в правилах:
В сети каждому абоненту выдается диапазон адресов /29, основанный на номере порта. При этом первый бит третьего октета IP-адреса может меняться на единичку. Исторически это использовалось для блокирования должников. При этом сама сеть, в которую попадают абоненты одного коммутатора, имеет маску /23.

Это будет лучше понятно на примере:
Если абонент подключен в порт №1 и для абонентов этого коммутатора выделена сеть 10.128.4.0/23, то правильными адресами для абонента будут 10.128.4.8/29  и 10.128.5.8/29.
Аналогично для 10-го порта и сети 10.133.56.0/23 - соответственно 10.133.56.80/29 и 10.133.57.80/29.

Как нетрудно догадаться, такая схема описывается маской 0xFFFFFEF8. В бинарном представлении последние два байта здесь будут выглядеть как 0b11111110 и 0b11111000. Если кто забыл, это, фактически, инверсия cisco wildcard mask, где биты, соответствующие нулевым битам маски, игнорирутся.

Таким образом мы разобрались с одной маской для IP SRC (чанк 7) - это 0xFFFFFEF8. Теперь аналогичным образом нужно описать ARP. Но ARP SRC IP смещен на 2 байта по отношение к IP SRC и самые интересный нам байты попадают уже в чанк 8. Это байты с номерами 30 и 31. А вот остальные 2 байта нам уже не нужны. Отсюда наша маска для чанка 8 должна была бы быть 0xFEF80000. Однако, согласно техзаданию нам надо блокировать еще доступ и к сетям управления, которые в нашем случае описываются как 172.16.0.0/15 и 10.99.0.0/16. Как видно, 172 и 10 - это байт №30, а 16 и 99 - байт №31, т.е. те же самые байты, которые мы пытаемся описать для ARP SRC IP. И если для байта №31 мы еще можем позволить себе забрать дополнительные 8 адресов (т.к. это локальные адреса), то забирать по 1 дополнительному адресу для байта №30 было бы слишком роскошно. Отсюда вывод: использовать маску 0xFFFFFFF8 и описывать ARP двумя правилами - с жестко заданными третьим октетом X и X+1.*

Ну и чтобы отделять мух от котлет ARP от IP нам потребуется знать ethertype. Его задаем жестко, поэтому используем маску 0xFFFF (0x0000FFFF).

* Эту "мелочь" я обнаружил уже в процессе написания заметки. Изначально я забыл про "нечетный" третий октет для ARP. Все-таки полезно иногда писать такие статьи и заново все разбирать. :)

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

Потом одним правилом разрешаем абонентский блок 10.XX.YY.port_N*8 0.0.1.7 (и YY+1).

Далее двумя правилами разрешаем валидные ARP-пакеты.

И последними двумя правилами запрещаем остальные IP и ARP от абонентов.

Ну и в конце классика жанра:
enable cpu_interface_filtering

create cpu access_profile profile_id 1 ip destination_ip_mask 255.255.255.255
config cpu access_profile profile_id 1 add access_id 1 ip destination_ip 224.0.0.2 port all permit

create cpu access_profile profile_id 2 ip destination_ip_mask 255.255.248.0
config cpu access_profile profile_id 2 add access_id 1 ip destination_ip 239.1.8.0 port all permit

#deny multicast-query for subscribers
create cpu access_profile profile_id 3 ip destination_ip_mask 240.0.0.0
config cpu access_profile profile_id 3 add access_id 1 ip destination_ip 224.0.0.0 port [ss] deny


И еще:
config cpu_filter l3_control_pkt [all] all state disable
config cpu_filter l3_control_pkt  [ss] all state  enable


Этим мы запрещаем всякие служебные пакетики от абонентов, не попадающие под обычные ACL, но разрешаем возможность отписываться от мультикаст-групп.

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

P.P.S. О конструкциях типа [ss], [all] и (fn_3oct#custom1) можно прочитать на странице сервиса генерации конфигов Dracon.

среда, 17 июня 2015 г.

Dracon - сервис генерации конфигурационных файлов 'на лету'

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

В самом шаблоне при этом можно писать что-то вроде:
config ports [ss] state enable

Где [ss] при выгрузке заменяется на нужный диапазон портов.

Можно использовать собственные функции, например для подстановки в ACL нужных IP или MAC адресов.

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

Проще говоря, если вдруг поменялся uplink, добавилась новая магистраль или подключился VIP-клиент со специфичными настройками порта - просто правим нужные свойства в биллинге и запрашиваем с коммутатора новый конфиг у Dracon.

пятница, 29 мая 2015 г.

Обновлены примеры ACL правил для ревизии C1

Обновил примеры правил на этой странице.

Хочу сказать что ревизия C1 нравится мне все больше и больше. Просто новые модели коммутаторов D-Link надо использовать через пару лет после их появления, когда все устаканится, а баги будут выпилены.

Неудобно, правда, что в этой ревизии можно использовать только 1 PCF профиль. Ладно бы, если бы можно было использовать большое число чанков, но нет! Текущее ограничение в 4 чанка по 4 байта не позволяет реализовать мои хотелки. Так что придется выкручиваться.

На следующей неделе планирую закончить разработку правил и составить разбор на тему "что как и почему".

понедельник, 25 мая 2015 г.

Конференция в jabber

От скуки зарегистрировал конференцию в джаббере - ccna@conference.jabber.ru.

Собираюсь присутствовать там в рабочее время и, иногда, по вечерам. Заходите, пообщаемся, обсудим нюансы сетестроения. :)

p.s. Из новостей - плотно взялся за PCF ACL на коммутаторах DES-3200-xx/C1. Через пару недель поделюсь результатами.

пятница, 3 апреля 2015 г.

Перезагрузка коммутаторов при помощи Briseis

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

В любом месте файла userdict.py определяем списки OID для формирования varbind:

reboot3028 = [
    ['.1.3.6.1.4.1.171.11.63.6.2.1.2.1','0','3','INTEGER']
]

reboot3200 = [
    ['.1.3.6.1.4.1.171.11.113.1.3.2.1.2.1','0','3','INTEGER']
]

reboot3200_c1 = [
    ['.1.3.6.1.4.1.171.12.1.2.19','0','2','INTEGER']
]


reboot_01_04 = [
    ['1.3.6.1.4.1.171.12.1.2.32.1.3','1','\x05\x05','OCTETSTR'],
    ['1.3.6.1.4.1.171.12.1.2.32.1.4','1','\x01\x04\x07\xdf','OCTETSTR'],
    ['1.3.6.1.4.1.171.12.1.2.32.1.5','1','1','INTEGER']
]


Первые 3 списка нужны для мгновенной перезагрузки коммутатора, а 4-й позволяет выполнить отложенную перезагрузку коммутаторов DES-3200-28 ревизии C1.

Теперь в файле bconfig.py исправляем 'PassSetSet' на:
PassSetSet  = {1:['reboot']}

А 'oids_set' на:
oids_set={
    'DES-3200-28':{
       'reboot':reboot3200
    },
    'DES-3200-28/C1':{
        'reboot':reboot3200_c1
    },
    'DES-3028':{
       'reboot':reboot3028
    }
}


Для модели DES-3200-28/C1 при желании можем использовать отложенную перезагрузку, заменив значение 'reboot3200_c1' на 'reboot_01_04'. Поскольку 1-е апреля уже прошло, то есть смысл заменить '\x01\x04' на желаемую дату. Кстати, дата в команде дана скорее для примера оформления hex-значений для net-snmp в Python. На самом деле достаточно указывать только время:
delayed reboot = [
    ['1.3.6.1.4.1.171.12.1.2.32.1.3','1','\x05\x05','OCTETSTR'],
    ['1.3.6.1.4.1.171.12.1.2.32.1.5','1','1','INTEGER']
]

Такой набор позволит планировать перезагрузку в любой день без правки словаря. Перезагрузка произойдет когда часы в следующий раз покажут 5:05.

Закончим это небольшое, но весьма полезное отступление и запустим программу:
./briseis.py start

Не забудем и остановить ее через несколько секунд:
./briseis.py stop

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

вторник, 31 марта 2015 г.

Перепрошивка коммутаторов с помощью Briseis

Briseis - мой проект для сбора метрик с сетевых устройств. Иногда перед чтением метрики требуется предварительно выполнить операцию записи. Такое может понадобиться, например, при диагностики состояния кабельной линии - сначала выполняется инициализация теста, а затем уже сам сбор результатов. Briseis умеет производить операции snmpset и этой возможностью мы воспользуемся для использования программы не совсем по прямому назначению, а именно - для массовой перепрошивки коммутаторов. :) При этом несколько усложним себе задачу и представим, что мы не знаем с какими именно моделями и ревизиями коммутаторов D-Link нам потребуется работать. Будем считать, что нам известен критерий выбора этих устройств из базы MySQL и их write-community.

1. Для начала напишем MySQL-запрос к нашей СУБД для выбора коммутаторов по некоторому критерию. В моей случае это IP-адрес. В вашем случае это может быть что-то другое, поэтому не вижу смысла приводить здесь мой запрос - важен лишь результат. Убедитесь, что имеете доступ к вашему MySQL-серверу с машины, на которой будете запускать Briseis и что сам запрос возвращает табличку вида:
+------+---------------+-------------+
| id   | ip            | wcomm       |
+------+---------------+-------------+
| 6248 | 10.90.90.91   | private     |
| 6249 | 10.90.90.92   | private     |
| 6250 | 10.90.90.93   | private     |
+------+---------------+-------------+


2. Идем далее. Если мы не знаем, какие модели и ревизии коммутаторов присутствуют в этом списке, то мы можем получить эту информацию из статистики Briseis. Создадим на сервере MySQL базу данных с таблицей для размещения статистики и гарантируем пользователю 'briseis' права для работы с этой таблицей.
CREATE DATABASE IF NOT EXISTS `blackhole` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `blackhole`;

CREATE TABLE IF NOT EXISTS `stats` (
  `device_id` int(4) unsigned NOT NULL,
  `host` char(16) NOT NULL,
  `mname` char(16) NOT NULL,
  `set_timestamp` int(4) unsigned NOT NULL,
  `walk_timestamp` int(4) unsigned NOT NULL,
  `avail` int(4) unsigned NOT NULL,
  `not_avail` int(4) unsigned NOT NULL,
  `errors` int(4) unsigned NOT NULL,
  `time` int(4) unsigned NOT NULL,
  PRIMARY KEY (`device_id`),
  KEY `host` (`host`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

GRANT USAGE ON *.* TO 'briseis'@'%' IDENTIFIED BY 'briseis_pass';
GRANT ALL PRIVILEGES ON `blackhole`.`stats` TO 'briseis'@'%' WITH GRANT OPTION;


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

3. Скачиваем Briseis отсюда. При написании этой заметки я проделал этот несложный маневр при помощи простой команды:
wget https://github.com/xcme/briseis/archive/v1.0.2.tar.gz --no-check-certificate

Распаковываем архив и притупаем к правке bconfig.py. Правим настройки для MySQL на нужные нам, т.е. прописываем адреса серверов, логины, пароли и т.п. Исправляем 'useMySQLstat' на 'True' и не забываем вписать в 'mysql_query_p' запрос, который мы разработали на шаге №1. Исправляем 'logfile', указывая желаемый путь для файла журнала.

Меняем 'PassSetSet' и 'PassSetWalk' на словари с одним пустым списком:
PassSetSet = {1:[]}
PassSetWalk = {1:[]}


Задаем 'oids_set' как пустой словарь, а 'oids_walk' как пустой список:
oids_set={}
oids_walk=[]


Значения 'useGraphite' и 'useAttractor' выставляем в 'False'.

При такой настройки Briseis выполнит только проверку устройств на доступность, опросив их по ключу 'oid_ModelName', и запишет результаты в таблицу статистики.

Важно: При написании заметки обнаружил один нюанс. По умолчанию программа использует '/var/run/briseis.pid' в качестве pid-файла. Доступ к этому каталогу для обычного пользователя может быть закрыт. Если вы не хотите запускать программу от root или давать доступ к этому каталогу, исправьте путь в файле 'briseis.py' на нужный вам. В этом случае программа запустится от обычного пользователя.

4. Сохраним настройки и выполним ручной запуск программы:
./briseis.py start
При появлении в логе сообщения об завершении цикла или же просто через несколько секунд останавливаем программу:
./briseis.py stop
При этом в файле журнала мы увидим примерно следующее:
Connection to MySQL Server '*******' established
MySQL Read-Query '*Select devices*' OK. 17 rows found
(+++) Added 17 devices to database
Polling devices from the database. Attempt #1 of 2 completed for 0.6087 sec
Polling devices from the database. Attempt #2 of 2 completed for 0.0000 sec
Sending set-queries for []...
Completed all set-requests. Elapsed time 0.0470 sec. Going to sleep for 3 sec...
Sending get/walk-queries for []...
Completed all walk-requests. Elapsed time 0.0566 sec
Total number of metrics in memory: 0
Connection to MySQL statistics Server '*******' established
Sended 17 entries to statictics server. Elapsed time 0.0632 sec
------- Pass №1 completed for 4.3851 sec -------


Как видим, 17 устройств было добавлено в память программы из базы, все они оказались доступными (нет сообщений о недоступных устройствах) и 17 записей было отправлено в таблицу статистики.

5. Подключимся к нашему серверу с базой статистики и выполним запрос:
SELECT mname,count(mname) FROM blackhole.stats GROUP by mname;

В ответ получаем:
+----------------+--------------+
| mname          | count(mname) |
+----------------+--------------+
| DES-3028       |           13 |
| DES-3200-28    |            1 |
| DES-3200-28/C1 |            3 |
+----------------+--------------+
3 rows in set (0.01 sec)


Прекрасно! Теперь мы знаем с какими устройствами нам предстоит работать.

6. Теперь нам нужно научить Briseis заливать ПО на коммутаторы. Если модели устройств были бы известны нам заранее, этот пункт можно было выполнять сразу после шага №1.

В любом месте файла userdict.py определяем списки OID для формирования varbind:
fw_up3200 = [
    ['1.3.6.1.4.1.171.12.1.2.1.1.3','1','10.90.90.101','IPADDR'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.4','1','2','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.5','1','DES-3200R_1.85.B008.had','OCTETSTR'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.7','1','3','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.8','1','3','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.9','1','2','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.10','1','1','INTEGER'],
]

fw_up3028 = [
    ['1.3.6.1.4.1.171.12.1.2.1.1.3','1','10.90.90.101','IPADDR'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.4','1','2','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.5','1','DES_3028_52_V2.94-B07.had','OCTETSTR'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.7','1','3','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.8','1','3','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.9','1','2','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.1.1.10','1','1','INTEGER'],
]

fw_up3200_c1 = [
    ['1.3.6.1.4.1.171.12.1.2.18.1.1.3','1','10.90.90.101','IPADDR'],
    ['1.3.6.1.4.1.171.12.1.2.18.1.1.5','1','DES3200R_4.39.B008.had','OCTETSTR'],
    ['1.3.6.1.4.1.171.12.1.2.18.1.1.8','1','3','INTEGER'],
    ['1.3.6.1.4.1.171.12.1.2.18.1.1.12','1','3','INTEGER'],
]


TFTP-сервером в нашем примере будет '10.90.90.101'. Значения остальных параметров рекомендую посмотреть тут.

Важно: Пакет net-snmp в какой то из версий имеет баг, не позволяющий работать с типом IPADDR в python-модуле. В этом случае при работе Briseis пакет не будет сформирован и ничего не произойдет. Если вы уверены, что делаете все правильно, но при этом результата нет - обновите пакет net-snmp.

Исправляем 'PassSetSet':
PassSetSet  = {1:['FW_upd']}

Исправляем 'oids_set':
oids_set={
    'DES-3200-28':{
        'FW_upd':fw_up3200
    },
    'DES-3200-28/C1':{
        'FW_upd':fw_up3200_c1
    },
    'DES-3028':{
        'FW_upd':fw_up3028
    }
}


Правим 'snmp_Retries':
snmp_Retries  = 0

Это нужно чтобы запрос отправлялся только 1 раз. При получении первого запроса на обновление ПО коммутатор может быть занят выполнением команды и не успеет отправить подтверждение. Когда мы выставляем 0 дополнительных попыток, то спасаем коммутатор от обновления ПО несколько раз - по 1 на каждую попытку.

Запускаем программу:
./briseis.py start
И через 5 секунд останавливаем:
./briseis.py stop
В логе видим:
Sending set-queries for ['FW_upd']...
Completed all set-requests. Elapsed time 0.2973 sec. Going to sleep for 3 sec...


7. Через 3-5 минут проверяем коммутаторы. Видим, что прошивка успешно загрузилась. Теперь в 'oids_set' комментируем строки:
#    'DES-3200-28/C1':{
#        'FW_upd':fw_up3200_c1
#    },

В файле userdict.py в списках 'fw_up3200' и 'fw_up3028' меняем строку
['1.3.6.1.4.1.171.12.1.2.1.1.10','1','1','INTEGER'],
на
['1.3.6.1.4.1.171.12.1.2.1.1.10','1','2','INTEGER'],

После чего снова запускаем и останавливаем программу
./briseis.py start
./briseis.py stop


Этими действиями мы перепрошили второй образ для DES-3200-28 и DES-3028, исключив при этом из обработки модель DES-3200-28/C1.

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

пятница, 27 марта 2015 г.

Attractor - Анализатор метрик, собираемых с сетевых устройств

В прошлом посте упоминал про анализатор метрик. Теперь он доступен тут: https://github.com/xcme/attractor

Attractor - Анализатор метрик, собираемых Briseis.

Программа может работать только в паре в Briseis, где и собираются сами метрики. Документация прилагается в комплекте.