Предисловие


Когда-то давно, в далекой далекой галактике… Хотя если подумать, это было всего то 15 лет назад.

В общем были времена, когда в качестве центрального шлюза в сеть Интернет использовались решения на базе FreeBSD и Linux. И были эти решения любовно настроены, и обвешивались они всеми возможными и невозможными функциями (от межсетевого экрана и VPN серверов до TFTP+PXE-сервисов бездисковой загрузки)… и не было беды, и все было хорошо…

Но времена меняются, появляются новые решения, появляются компании, которые «дешево и сердито» готовят ядро Linux, обвешивают необходимым функционалом и продают это за весьма скромные деньги (сопоставимые со стоимостью аппаратной части).

Примером таких решения является компания Mikrotik и ее одноименные решения.

Текущие реалии


Итого текущая ситуация – купить и поставить Mikrotik в организацию, в которой от 10 до 5000 компьютеров, быстрее и экономичнее, чем брать «очередной системник» и собирать шлюз по частям (сетевухи, софт, сервисы и т.д.).

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

Учет WEB-трафика прост и понятен – связка Squid + LightSquid позволяет просто и быстро собирать и агрегировать информации о том, кто какие сайты посещает, какие файлы качает и сколько в Youtube-е зависает. При необходимости можно и ограничить сайты, время и т.д. Простое, удобное решение, проверенное годами. В Mikrotik делается одно правило, выпускающее IP прокси-сервера в интернет. И все счастливы.

Но вот проблема – не все успешно проходит через Squid. Есть банк-клиенты, написанные без поддержки HTTP и Socks прокси. Есть сложные программы, которые для разных типов трафика используют разные соединения – итог – либо плохо работают через Proxy, либо вообще не работают. А есть отдельная категория так называемых VIP-персон… которым проще дать «Full NAT», чем обострять отношения, когда «что-то у них не открывается».

Таким образом, в Mikrotik рано или поздно, но будут появляться отдельные правила, выпускающие «особенных» напрямую через NAT, минуя прокси-сервер. И их трафик мы в статистике уже не видим.

Решение по учету такого трафика напрашивается следующее:

  • Включить на внешнем интерфейсе Mikrotik захват NetFlow статистики;
  • Отправка этой статистики в NAS (например, в службу flow-tools, через flow-capture)

Для удобного анализа получаемых на NAS-сервере файлов, данное решение предлагается улучшить с помощью пары самописных скриптов:

  • Perl-скрипт, который будет обрабатывать ft-файлы, и загружать информацию в СУБД MySQL;
  • PHP-скрипт, который будет выполнять роль преднастроенного UI, для удобного анализа NetFlow-данных.

Настройка Mikrotik


Все просто и по документации:

/ip traffic-flow
set enabled=yes interfaces=WAN

/ip traffic-flow target
add dst-address=<NAS IP Address> port=8787 v9-template-timeout=1m version=5

Настройка Flow-Tools на примере FreeBSD


# Установка NetFlow сенсора:
pkg install flow-tools

# Настройка запуска:
echo 'flow_capture_enable="YES"' >> /etc/rc.conf.local
echo 'flow_capture_flags="-N-2"' >> /etc/rc.conf.local

# Запуск:
service flow_capture start

Установка и подготовка СУБД MySQL для импорта NetFlow данных


# Установим, запустим и настроим MySQL сервер:
pkg install mysql56-server

# Запуск службы

echo 'mysql_enable="YES"' >> /etc/rc.conf
service mysql start

# Начальная настройка СУБД:
mysql_secure_installation

# Установим Perl-модули для работы скрипта с СУБД:
pkg install p5-DBI p5-DBD-mysql

# Входим в СУБД и создаем базу и пользователя для работы с ней:
mysql -u root -p

# Создаем СУБД и пользователя:

mysql> create database netflow;
mysql> grant insert,create,update,select,delete on netflow.* to nfuser@'localhost' identified by '987654321';
mysql> flush privileges;
mysql> exit;

Perl-скрипт для анализа ft-* файлов статистики NetFlow и загрузки данных в MySQL


Скрипт был написан не с нуля – когда то давно, в 2005-м году на сайте OpenNET была выложена статья (ссылка) о подсчете трафика на шлюзе FreeBSD с использованием NetGraph модуля ng_ipacct.

Скрипт загрузки был взят за основу и переписан на использование с NetFlow и flow-tools. Работает как на FreeBSD, так и на Linux (только пути переписать до программ flow-cat и flow-print).

Особенности скрипта – данный вариант предназначен для анализа всех ft-* файлов за прошедшие сутки и их загрузки в базу (построчно). При этом реализовано исключение строк по нескольким шаблонам, чтобы не грузить в MySQL избыточную информацию (например, исключить широковещательный трафик, трафик DNS-запросов, трафик с HTTP/Socks прокси (благо статистика по прокси есть в другом месте). По моим замерам, исключение позволяет сократить количество загружаемых в СУБД строк в 10, а то и в 20-30 раз.

Таблицы в СУБД создаются автоматически с началом нового месяца. К стандартному NetFlow v5 формату добавляется день, время записи (используется время создаваемых ft-файлов – например, каждые 15 минут), также указывается имя источника NetFlow и имя сетевого интерфейса.

PHP UI для упрощенного построения SQL-запросов


В далеком 2005-м, когда использовались Perl-скрипты автора, для анализа данных в MySQL мы использовали SQL команды… и все всех устраивало.

Но рано или поздно настал момент, когда вводить запросы надоело. И, собравшись с мыслями, был написал небольшой PHP-код, который позволял проводить построение SQL-запросов более быстрым и простым способом.

Внешний вид:



Что позволяет сделать скрипт:

  1. Производить SQL-запросы, видеть сам итоговый запрос и его результат в табличной форме;
  2. Видеть сумму трафика NetFlow за любой месяц;
  3. Группировать трафик по одному показателю (SourceIP, SourcePort, DestIP, DestPort, Proto, Date);
  4. Видеть количество строк вместо суммы (как за месяц так и с группировкой по одному признаку);
  5. Фильтровать по объему трафика;
  6. Видеть сами записи вместо суммы трафика;
  7. Запрашивать указанное количество записей из базы (например, для дальнейшего copy/paste в Excel).

PS: Владелец файла netflow.php должен быть пользователь Web-сервера (например, Apache).
PSS: Доступ к СУБД указан в файле netflow.php явно – так что измените под себя.

Обслуживание MySQL таблиц


Если таблицы получаются довольно большие (хотя никто Вам не мешает грузить в СУБД только то, что Вам нужно, исключая «шлак» и уменьшая размер), то есть интересный прием, позволяющий существенно уменьшить размер СУБД. Речь идет об использовании компрессии БД в формате MyISAM, а также об оптимизации индекса.

Для автоматического выполнения этих процедур был написан еще один Perl-скрипт, который первого числа каждого нового месяца запускается через Cron:

  • Ремонтирует таблицу на всякий случай (вдруг были некорректные отключения службы и MyISAM содержит ошибки);
  • Переименовывает таблицу, добавляя в конце символ c (от слова compressed);
  • Выполняет программы myisamchk и myisampack, которые сжимают БД и строят новый и отсортированный индекс для сжатой таблицы.

Итого после выполнения скрипта данная таблица станет ReadOnly, будет сжата (размер уменьшиться раза в 3), и будет построен новый отсортированный и оптимизированный индекс. Запросы в такую таблицу будут выполняться быстрее.

Резюме


Все скрипты можно скачать по ссылке.

Update1: Доработал скрипт netflow.php — для работы с PHP версии 7.x: ссылка

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


  1. voe
    01.05.2018 17:50

    А почему просто не взять ELK и готовый фильтр и дашборт для него, например вот такой github.com/robcowart/elastiflow?


  1. mickvav
    01.05.2018 18:31

    А ещё есть RocksDB (в виде myRocks) и ему можно объяснить, что у строк в таблице такой-то TTL. И он за вас будет табличку чистить. А архивирует он из коробки. Только с внешними ключами осторожнее.


    1. voidMan
      02.05.2018 12:38

      MongoDB тоже такое умеет


  1. neumeika
    01.05.2018 19:50

    а ещё в мускле есть partitioning, хотя вариант с еластиксёрч + logstash netflow imho удобнее


  1. dnbstd
    01.05.2018 21:39

    Я бы даже сказал что тут бы был отличный вариант: logstash+influxdb+grafana. Хотя ваш самописный вариант мне тоже нравится.


  1. alex005
    02.05.2018 00:45

    С тогоже Микротика собираю статистику используя nfsen и nfdump, плюс в том, что данные тулзы при наличии Juniper в сети позволяют собирать и jflow. Но честно сказать, идея не хорошая хранить потоки в БД, лучше там хранить агрегированную статистику, а трафик туда не совать, слишком это пухнет быстро.


  1. fdroid
    02.05.2018 04:03

    Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /usr/local/www/apache24/data/netflow.php on line 215
    Пробовал на 10 и 11 версии, в разных виртуалках. Что может быть не так?


    1. fdroid
      02.05.2018 04:56

      Разобрался — я забыл про netflow.pl


      1. fdroid
        02.05.2018 11:52

        … но это особо не помогло. В виртуалке на FreeBSD, в итоге, всё заработало, а вот на рабочем сервере с Ubuntu Server 16.04 — нет. И дело не в путях в netflow.pl, которые я поправил в соответствии с системой, а, похоже, в самом скрипте netflow.php, который не работает как положено, т.к., вероятно, написан для PHP 5.6, а у меня PHP 7 — половины полей нет, данные не импортируются. Сам поправить не смог, т.к. не программист от слова «совсем». Пока трафик считаю, настроив flow-tools по старенькой, но вполне актуальной статье. Да, гибкость не та, удобства нет. По сути, такая простая задача как визуализация статистики трафика по IP неожиданно стала непростой — гуглятся либо монстроподобные комбайны, от который и 10-й доли возможностей не нужно, либо давно неактуальный софт, который годами не обновляется и с современными системами не работает. Казалось бы, скрипт автора способен решить задачу, но увы, PHP 5 я устанавливать не буду.


        1. Dorlas Автор
          02.05.2018 13:34

          Я попробую на днях адаптировать к PHP 7-й версии. Как будет результат — напишу и дополню.
          Спасибо за тестирование.


        1. Dorlas Автор
          02.05.2018 17:16

          Переписал netflow.php на использование mysqli функций. Тестировал на PHP версии 7.2.5 — работает. Ссылка на загрузку в статье либо тут.
          Там же список пакетов, с которыми тестировал.


    1. slavkoid
      02.05.2018 13:09

      mysql_fetch_array() вам вернуло false. Т.е. ошибка в запросе.


  1. CentALT
    02.05.2018 11:12

    flow-tools напрямую в mysql умеет складывать насколько я помню


  1. ugenk
    03.05.2018 22:55

    Рекомендовал бы попробовать pmacctd, он умеет сразу в sql, и много другого вкусного


    1. Dorlas Автор
      04.05.2018 08:49

      Интересный инструмент, спасибо! Обязательно попробую.