Для конфигурирования сервера представлений нужен язык описания этой конфигурации.
Т.к. сам сервер написан на скриптовом языке 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" # легенда для
# таблицы детализированных потоков.
);
#---------------------------------------------------------------------------------------
Для доступа к данным 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
(текстовая строка).
Основной алгоритм программы состоит в том, что над каждым потоком, исполняется
несколько процедур, и по результатам их работы этот поток причисляется к тому или
иному классу трафика.
Процедура-фильтр это нормальная подпрограмма в смысле языка 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тоящий из номеров колонок.