TkTopNetFlow::Flow_Server

# Пакет TkTopNetFlow
v0.4
Flow_Server

### Содержание

1. Основные алгоритмы
2. Конфигурация
3. Протокол взаимодействия с клиентской программой

1. Основные алгоритмы

   Программа Flow_Server написана на языке Perl и является полноценным сервисом - т.е. не требует интерактивного взаимодействия с оператором.
   Программа отслеживает появление новых файлов с данными NetFlow, разбирает новые файлы и строит представления трафика. Программа хранит в памяти представления за некоторой предыдущий промежуток времени.
   В процессе анализа данных производится переупаковка потоков. Потоки, начавшиеся в одном интервале времени, а закончившиеся в следующем, разбиваются на 2 потока, так, что каждый из них начинается и заканчивается внутри одного интервала.
   Одновременно, программа ожидает входящих TCP соединений (по умолчанию: localhost:9000) от клиентских программ. При установлении соединения, по запросам клиентов, программа отсылает им накопленные данные.
   Одновременно может обслуживаться несколько клиентских сеансов.
   Системные сообщения и сообщения об ошибках записываются в SYSLOG ( daemon ).
   По сигналу SIGHUP программа перечитывает конфигурационный файл.
   Для работы программы нужно установить пакеты flow-tools-0.66_1, p5-Cflow-1.051.
   Винимание! Нужно скомпилировать и установить пакет Cflow из дистрибутива flow-tools, так как стандартный пакет не поддерживает формат данных flow-tools:

       		$ cd /usr/ports/net/flow-tools/work/flow-tools-0.66/contrib
       		$ tar zxf Cflow-1.051.tar.gz
       		$ cd Cflow-1.051
       		$ perl Makefile.PL
       		$ make; make install

2. Конфигурация

   Для конфигурирования сервера представлений нужен язык описания этой конфигурации. Т.к. сам сервер написан на скриптовом языке Perl, вполне логично, что его конфигурация может быть описана на этом-же языке.
   В этом, пожалуй, и есть самая существенная трудность - при конфигурировании нужно знать язык программирования Perl, и представлять алгоритм работы программы.
   Предполагается, что файл конфигурации лежит в /usr/local/etc/view_definitions.pl. В файле конфигурации Вы должны определить ассоциативный массив %view, и несколько подпрограмм, которые будут вызываться при построении представлений.
   В примере мы опишем представление, в котором входящий от провайдера трафик будет классифицирован по IP адресу источника.

       #---------------------------------------------------------------------------------------
       #!/usr/bin/perl
       use Cflow qw(:flowvars :tcpflags :icmptypes :icmpcodes 1.041);
       #
       @hosts_files = 	   ("/etc/hosts");	#  таблицы хостов
       @protocols_files = ("/etc/protocols");  #  таблицы протоколов
       @services_files =  ("/etc/services");   #  таблицы сервисов
       @asns_files =      ("/usr/local/etc/flow-tools/asn");  # таблицы номеров автономных систем
       #
       undef %view;  #  очистить массив view

       sub traffic_in_filter {
       	if  ($Cflow::exporterip ne "192.168.1.1" ) { return 0; }
       	if  ($Cflow::input_if != 1 ) { return 0; }
       	return 1;
       }; #  входящим считается трафик, прошедший через интерфейс с индексом 1
          #  маршрутизатора 192.168.1.1

       sub classify_by_src_ip {
       	return "$Cflow::srcip";
       }; # Ключем группировки является адрес источника.

       @{$view{input_by_srcip}) = ( "Input traffic classified by SRC IP",  # описание представления, 1 строка.
       	\&traffic_in_filter,	#  ссылка на процедуру-фильтр для представления
       	\&classify_by_src_ip,	#  ссылка на процедуру-классификатор
       	8,			#  количество TOP классов для отображения.
       	\&myPrintFlow,		#  ссылка на процедуру печати(детализации) потока
       	"dst_AS protocol src_addr:src_port dst_addr:dst_port bytes packets" # легенда для
       				#  таблицы детализированных потоков.
       );
       #---------------------------------------------------------------------------------------

   #### Модуль Cflow

   Для доступа к данным NetFlow используется модуль расширения языка Perl - Cflow. В этом модуле, в частности, определены переменные, содержащие значения параметров текущего потока.

       $Cflow::unix_secs - secs since epoch (deprecated)
       $Cflow::exporter - Exporter IP Address as a host-ordered "long"
       $Cflow::exporterip - Exporter IP Address as dotted-decimal string
       $Cflow::localtime - $Cflow::unix_secs interpreted as localtime
       		with this strftime(3) format: %Y/%m/%d %H:%M:%S
       $Cflow::srcaddr - Source IP Address as a host-ordered "long"
       $Cflow::srcip - Source IP Address as a dotted-decimal string
       $Cflow::dstaddr - Destination IP Address as a host-ordered "long"
       $Cflow::dstip - Destination IP Address as a dotted-decimal string
       $Cflow::input_if - Input interface index
       $Cflow::output_if - Output interface index
       $Cflow::srcport - TCP/UDP src port number or equivalent
       $Cflow::dstport - TCP/UDP dst port number or equivalent
       $Cflow::ICMPType - high byte of $Cflow::dstport.
       		Undefined if the current flow is not an ICMP flow.
       $Cflow::ICMPCode - low byte of $Cflow::dstport.
       		Undefined if the current flow is not an ICMP flow.
       $Cflow::ICMPTypeCode - symbolic representation of $Cflow::dstport.
       		 The value is a the type-specific ICMP code, if any, followed by the ICMP type. E.g.  ECHO  HOST_UNREACH. Undefined if the current flow is not an ICMP flow.
       $Cflow::pkts - Packets sent in Duration
       $Cflow::bytes - Octets sent in Duration
       $Cflow::nexthop - Next hop router's IP Address as a host-ordered "long"
       $Cflow::nexthopip - Next hop router's IP Address as a dotted-decimal string
       $Cflow::startime - secs since epoch at start of flow
       $Cflow::start_msecs - fractional portion of startime (in milliseconds).
       		This will be zero unless the source is flow-tools or argus.
       $Cflow::endtime - secs since epoch at last packet of flow
       $Cflow::end_msecs - fractional portion of endtime (in milliseconds).
       		This will be zero unless the source is flow-tools or argus.
       $Cflow::protocol - IP protocol number (as is specified in F, i.e. 1=ICMP, 6=TCP, 17=UDP, etc.)
       $Cflow::tos IP - Type-of-Service
       $Cflow::tcp_flags - bitwise OR of all TCP flags that were set within packets in the flow;
       		0x10 for non-TCP flows
       $Cflow::TCPFlags - symbolic representation of $Cflow::tcp_flags.
       		The value will be a bitwise-or expression.
       		E.g.   PUSH|SYN|FIN|ACK.
       		Undefined if the current flow is not a TCP flow.
       $Cflow::Bps - the minimum bytes per second for the current flow
       $Cflow::pps - the minimum packets per second for the current flow

       The following variables are undefined if using NetFlow v1
       (which does not contain the requisite information):

       $Cflow::src_as - originating or peer AS of source address
       $Cflow::dst_as - originating or peer AS of destination address

       The following variables are undefined if using NetFlow v1 or LFAPv4
       (which do not contain the requisite information):

       $Cflow::src_mask - source address prefix mask bits
       $Cflow::dst_mask - destination address prefix mask bits
       $Cflow::engine_type - type of flow switching engine
       $Cflow::engine_id - ID of the flow switching engine

       The tcpflags are:

          $TH_FIN $TH_SYN $TH_RST $TH_PUSH $TH_ACK $TH_URG

       The icmptypes are:

          $ICMP_ECHOREPLY     $ICMP_DEST_UNREACH $ICMP_SOURCE_QUENCH
          $ICMP_REDIRECT      $ICMP_ECHO         $ICMP_TIME_EXCEEDED
          $ICMP_PARAMETERPROB $ICMP_TIMESTAMP    $ICMP_TIMESTAMPREPLY
          $ICMP_INFO_REQUEST  $ICMP_INFO_REPLY   $ICMP_ADDRESS
          $ICMP_ADDRESSREPLY

       The icmpcodes are:

          $ICMP_NET_UNREACH  $ICMP_HOST_UNREACH $ICMP_PROT_UNREACH
          $ICMP_PORT_UNREACH $ICMP_FRAG_NEEDED  $ICMP_SR_FAILED
          $ICMP_NET_UNKNOWN  $ICMP_HOST_UNKNOWN $ICMP_HOST_ISOLATED
          $ICMP_NET_ANO      $ICMP_HOST_ANO     $ICMP_NET_UNR_TOS
          $ICMP_HOST_UNR_TOS $ICMP_PKT_FILTERED $ICMP_PREC_VIOLATION
          $ICMP_PREC_CUTOFF  $ICMP_UNREACH      $ICMP_REDIR_NET
          $ICMP_REDIR_HOST   $ICMP_REDIR_NETTOS $ICMP_REDIR_HOSTTOS
          $ICMP_EXC_TTL      $ICMP_EXC_FRAGTIME

   #### Таблицы хостов, сервисов, протоколов и номеров автономных систем.

   Здесь перечислены файлы, из которых программа будет читать таблицу соответствия символических имен хостов IP адресам.
   Ожидается, что файлы имеют формат файла hosts.
   Для каждого файла отслеживается время последней модификации, и в случае, если файл был изменён, он перечитывается заново.
   Это позволяет, не тратить время на резолвинг ip адресов внутри программы (это может занимать очень много времени), а внешним образом асинхронно резолвить IP адреса.
   Доступ к таблице:

       	if ( defined $hosts{"192.168.1.2"} ) { $hostname = $hosts{"192.168.1.2"}; };

   Для протоколов - таблицы должны иметь формат файла protocols
   Доступ к таблице:

       	if ( defined $protocols{"57"} ) { $proto = $protocols{"57"}; };

   Для сервисов - таблицы должны иметь формат файла services
   Доступ к таблицам:

       	if ( defined $tcp_services{"110"} ) { $srv = $tcp_services{"110"}; };
       	if ( defined $udp_services{"53"} ) { $srv = $udp_services{"53"}; };

   Для номеров автономных систем - таблицы должны иметь формат:
   Доступ к таблице:

       	if ( defined $asns{"3333"} ) { $asn_name = $asns{"3333"}; };

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

   #### Описание VIEW

   Значение элемента ассоциативного массива %view представляет собой ссылку на массив параметров. При этом ключем(индексом) является короткая текстовая строка(слово) - уникальный идентификатор view.
   Первым элементом массива параметров является расширенное описание этого view (текстовая строка).

   #### Процедура - фильтр.

   Основной алгоритм программы состоит в том, что над каждым потоком, исполняется несколько процедур, и по результатам их работы этот поток причисляется к тому или иному классу трафика.
   Процедура-фильтр это нормальная подпрограмма в смысле языка Perl, которая должна возваращать логическое значение 0 (false) или 1 (true). Если процедура-фильтр вернула 1, то считается, что текущий анализируемый поток должен учитываться в текущем view (должен быть классифицирован).
   Иначе - текущий поток игнорируется.
   Внутри процедуры-фильтра можно ссылаться на параметры текущего потока экспортированные из модуля Cflow.
   Для удобства анализа кода, и для уникальности названий процедур, в названии процедур-фильтров испрользуется суффикс "_filtеr".

   #### Процедура-классификатор.

   После того, как принято решение о том, что текущий поток принадлежит текущему view, исполняется процедура-классификатор.
   Процедура-классификатор это нормальная подпрограмма в смысле языка Perl, которая должна возваращать строку - название класса. Впоследствии, счетчик байтов текущего потока суммируется со счетчиком класса.
   Внутри процедуры-классификатора можно ссылаться на параметры текущего потока экспортированные из модуля Cflow.
   Для удобства анализа кода, и для уникальности названий процедур, в названии процедур-классификаторов испрользуется префикс "classify_".

   #### Компактизация классов

   После анализа всех потоков, в выбранном интервале времени, может оказатьcя, что классов очень много - в пределе, их может быть столько-же, сколько потоков.
   Но отображать большое количество классов - неэффективно, так как такая картинка плохо воспринимается оператором, поэтому применяется алгоритм уменьшения количества классов.
   Для этого, все классы в текущем view сортируются в порядке убывания счетчика байтов, и для отображения выбираются первые N классов (у которых самые большие значения счетчиков).
   Счетчики остальных классов суммируются, в специальном классе "other".
   Четвёртый параметр в массиве описания view - это количество TOP классов для отображения. Этот параметр должен быть в диапазоне от 1 до 10.

   #### Процедура детализации потока.

   Часто бывает необходимо посмотреть, какие потоки попали в определенный класс в выбранном интервале времени.
   Для решения этой задачи, для каждого потока вызывается процедура детализации (пятый параметр массива описания view).
   Эта процедура должна вернуть текстовую строку. Каждое слово в этой строке будет размещено в отдельной колонке в таблице детализированных потоков, поэтому эта строка должна иметь одинаковое количество слов независимо от параметров потока.
   В процедуре детализации потоков можно ссылаться на параметры текущего потока экспортированные из модуля Cflow, и использовать массивы %hosts %protocols %tcp_services %udp_services %asns.
   Это обязательный параметр, и если Вы не планируете использовать собственную процедуру детализации потоков, здесь нужно указать встроенную процедуру детализации PrintFlow.

   #### Легенда таблицы

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

3. Протокол взаимодействия с клиентской программой

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

   Протокол взаимодействия: текстовый.
   Режим обмена: один запрос - один ответ.
   Запрос состоит из одной непустой строки, за которй следует пустая строка.
   Ответ состоит из одной или более непустых строк, за которыми следует пустая строка.
   Ответы сервера отформатированы таким образом, чтобы их легче было обрабатывать из клиентской программы на Tcl/Tk.

   Запрос состоит из ключевой фразы и, возможно, нескольких параметров.
   Параметры могут быть:

   - view_name - идентификатор view
   - timestamp - время в секундах как его возвращает time()
   - time_interval - интервал времени в секундах, для отображения истории.

   ### Список команд

   GET PARAMS - вернуть параметры сервера представлений - номер версии, величну шага в секундах и глубину окна, в секундах.
   GET VIEWS - вернуть идентификаторы всех известных view.
   DESCRIBE VIEW "view_name" - вернуть описание view ( первый элемент массива описания view )
   GET FLOWS "view_name" timestamp - вернуть детальное описание потоков view_name за интервал с меткой времени timestamp
   GET FLOWS LEGEND "view_name" - вернуть легенду детального описания потоков для view_name
   UPDATE "view_name" timestamp - вернуть отсчеты для view_name, с метками времени больше , чем timestamp.
   HISTORY "view_name" timestamp time_interval - вернуть отсчеты для view_name с метками времени в диапазоне от timestamp до timestamp+time_interval
   HISTORY MODE - перейти в режим исторических данных
   QUIT - отключиться.

Last change: