Хочу предупредить, чтоб не тратили своё время! Это продолжение размышлений на тему сопровождения L2 сети уровня города. Стоит прочесть эту статью, чтоб понять нужно оно Вам или нет.

Администратор сети:
image
Моя работа начинается если, мне прилетел отчёт об отказе узла связи.

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

Для физической организации сети связи за нас давно придуман стандарт TIA/EIA-606 «Стандарт на администрирование телекоммуникационной инфраструктуры коммерческих зданий(ГОСТ Р 53246-2008, аналог Американского стандарта). Архитектурная инфраструктура сети включает в себя три подсистемы кабельного хозяйства.

  • уровень доступа (access layer);
  • уровень агрегации (distibution layer);
  • уровень ядра (core layer).

Логическая организация того что имеем.

графическое представление того что есть

Теперь рассмотрим, какими данными мы обладаем

  1. Управляющая сеть, через которую можно достучаться по IP к управляемому коммутатору выделенная в отдельный Vlan (vlan 100 на рисунке, untagged на UpLink)
  2. Протокол ARP, который позволит нам спуститься на L2 увидеть мак-адреса,
  3. Таблицы коммутации, покажут какие мак-адреса в каких портах живут.

Причём второй и третий пункты не документированы в силу того что информация обновляется и распределена по всей сети. Другими словами у нас тут проблемка… в случае отказа узла или искажения таблицы коммутации во время флуда усложняется задача поиска точки (порта) отказа. Сам же поиск представляет собой работу с документацией и последовательный (по цепочке) опрос коммутаторов.

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

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

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

В качестве средства автоматизации, я планирую использовать Python v3, для работы с MAC и IP адресами библиотеку netaddr (первоначально думал использовать ipaddress, но эта даёт большую свободу действий). В качестве площадки для сбора выступит сервер на котором развёрнут zabbix-proxy основная причина выбора уже работающего сервера — он находится менеджмент-vlan одним из интерфейсов.

Шаг первый выявление „Живых“


Код внутри, ОСТОРОЖНО! Может вызвать раздражение глаз Профи.
import datetime
import json
import re

from netaddr import IPNetwork, IPAddress, EUI
from netaddr.core import AddrFormatError
import subprocess


class AliveHost:
    """
    Средствами операционной системы, а именно ping ip и arp -n ip заполняем поля этого класса
    """

    def __init__(self, address, mac):
        self.ip = IPAddress(address)
        self.mac = EUI(mac)
        self.current_time = datetime.datetime.now()

    def __repr__(self):
        return "{} - {}".format(self.ip, self.mac)

    def __hash__(self):
        # TODO: Какова вероятность совпадения hash-значений сочетания ip+mac???
        return hash((self.ip, self.mac))

    @staticmethod
    def _str_class(o):
        # TODO: Сократить и перенести в метод to_json
        result = {}
        for attr in o.__dict__:
            result.update({attr: str(o.__dict__.get(attr))})
        return result

    def to_json(self):
        return json.dumps(self, default=self._str_class,
                          sort_keys=True, indent=4)


def ping(host):
    """PEP 324 – PEP proposing the subprocess module"""
    h = str(host)
    result = []
    with subprocess.Popen(["ping", "-c 1", h], stdout=subprocess.PIPE) as s_ping:
        if '1 received, 0% packet loss' in str(s_ping.stdout.read()):
            result.append(h)
    if not len(result):
        return None, None
    with subprocess.Popen(["arp", "-n", h], stdout=subprocess.PIPE) as s_ping:
        mac = re.compile(r'(([0-9A-Fa-f]){2}?:){5}([0-9A-Fa-f]){2}')
        result.append(re.search(mac, str(s_ping.stdout.read().decode('utf-8')))[0])
    return result


if __name__ == '__main__':
    alive = []
    for ip in IPNetwork('10.0.0.0/22').iter_hosts():
        try:
            alive.append(AliveHost(*ping(ip)))
        except AddrFormatError:
            continue
        except TypeError:
            continue


Выполняя этот код, мы получим список объектов, которые уже содержат в себе часть нужной для построения дерева информации.

Следующий шаг — Сбор информации с использованием библиотеки telnetlib и формирование примерно таких записей: (alive[0], port_13),(alive[1],alive[2],alive[3]).

Намеренно избегаю пока обсуждение сериализации данных, так как объем собранной информации будет небольшим в частности сеть /24 заняла 24Kб памяти, а следовательно нет никакого смысла спешить.

А вот узнать Ваше мнение на предмет правильности рассуждений или же смысла публикаций хочется уже сейчас.

Комментарии (11)


  1. DoMoVoY
    15.10.2018 10:10

    telnet не нужен. Используйте SNMP опрос и сделать приемник SNMP-traps для realtime данных ос состоянии портов (link traps). Топологию строить по LLDP.


    1. mmblsc Автор
      15.10.2018 14:27

      Спасибо за совет!
      habr.com/post/213247 в этой статье описание минусов опроса коммутаторов., Откровенно говоря snmp-trap единственное полезное при условии доставки, которую не гарантируют.
      Касаемо LLDP — сбор информации осуществляется всё тем же SNMP.
      Собственно это очень даже хорошая альтернатива старому telnet-у. Обязательно попробую альтернативную ветку для сравнения качества получаемой информации и скорости её получения.


      1. duckhawk
        15.10.2018 15:00

        Это правильная альтернатива телнету. Единственная железка, с которой нельзя снимать fdb по snmp — это циски 35хх/76хх, ибо у них это грузит в полку проц, у остального все вполне нормально.
        Для многопоточности используйте асинхронщину в pysnmp.


    1. ADual
      15.10.2018 14:53

      Топологию строить по LLDP

      С этим могут быть сложности, связанные с багами и «особенностями» некоторых устройств


      1. duckhawk
        15.10.2018 14:59

        Из интереса, Вы про какие железки?
        У всех вендоров, с которыми сталкивался, работает. Бывают глюки, конечно, но мелкие, и чинят по запросу.


        1. ADual
          15.10.2018 16:32

          LINKSYS — SPS224G4
          Huawei — чтобы по snmp отдавалась ветка snmp нужна настройка (по дефолту не отдается)
          Huawei S9303 — точно не помню, но был баг с некорректно отдаваемым номером порта по snmp


  1. duckhawk
    15.10.2018 14:53

    Используйте snmp, telnetlib Вам здесь не нужен.
    Для топологии используйте lldp, он также прекрасно доступен на всех длинках через snmp.
    Также, не понимаю, зачем Вам тут хэш, что Вы экономите? На коммутаторах очень дорогая память, но на сервере-то зачем хэшировать? Храните, как есть.


    1. mmblsc Автор
      15.10.2018 15:01

      Если вы про def __hash__(self)… то я его планирую использовать в качестве временного ключа для построения графа (именования узлов). в последствии, при разработке хранилища, возможно я пересмотрю в своё решение в сторону PK базы данных. В следующей статье планирую выложить на ваш суд дальнейшие размышления и код, который позволит генерировать изображение узлов и связей.
      Спасибо за внимание к моему творчеству.


  1. ugenk
    16.10.2018 02:32

    Посмотрите в сторону nocproject.org


    1. mmblsc Автор
      16.10.2018 09:53

      даже год эксплуатировал, ещё userside пробовал. Оба проекта добавляют работы, а я пытаюсь решить задачу по снижению нагрузки на персонал и решение проблемы «ой я забыл позвонить, а теперь не помню»


  1. alexgreat7
    18.10.2018 02:49

    Zabbix вам в помощь. Snmp + auto discovery.