MooSE 2009-02-02 07:49:59
Проверил: MooSE

Очень часто у системных администраторов
возникает задача учёта трафика локальной сети. Ниже будет показано как
можно решить эту задачу используя flow-сенсор fprobe и утилиты из
пакета flow-tools.

Озвучим начальные условия:

  • Локальная сеть с адресным пространством 192.168.2.0/24.
  • Интернет-шлюз под управлением Ubuntu Server 8.10, подключенный к
    локальной сети интерфейсом eth1 и имеющий на нём адрес 192.168.2.1.
  • Сервер мониторинга, работающий под управлением Debian Lenny. Он
    имеет адрес 192.168.2.10. На него мы будем собирать логи и на нём же мы
    будем их обрабатывать.

Первым делом установим fprobe на сервер:

apt-get install fprobe

На вопрос с какого интерфейса снимать трафик нужно
ответить «eth1», а на вопрос куда отсылать логи — «192.168.2.10:9999».
Порт можно выбрать произвольно — главное чтобы на сервере мониторинга
он был свободен. Собственно на этом настройка интернет-шлюза
заканчивается, переходим к серверу мониторинга.

Установим flow-tools:

apt-get install flow-tools

Далее приводим файл /etc/flow-tools/flow-capture.conf к виду:

-w /var/log/flow -n 275 0/192.168.2.1/9999

Здесь flow-capture будет слушать на адресе
192.168.2.1 и порту 9999 (если на шлюзе вы указали другой порт
назначения — измените соответствующим образом его значение и здесь.
Логи будут сохраняться в /var/log/flow. Место их хранения
непринципиально. Но если вы выберите другое место — делайте
соответствующие поправки во всех дальнейших инструкциях.

Создадим директорию для логов:

mkdir -p /var/log/flow

И перезапустим flow-коллектор:

invoke-rc.d flow-capture restart

На всякий случай убеждаемся что коллектор слушает нужный порт:

netstat -lpnu|grep flow-capture

В случае если всё хорошо — вывод будет выглядеть примерно вот так:

udp 0 0 0.0.0.0:9999 0.0.0.0:* 19652/flow-capture

Если же коллектор не запустился — внимательно проверьте его настройки.

Через некоторое время в указанной директории начнут
собираться логи. Остаётся только написать скрипты для генерации отчётов
на основе этих логов. Создадим директорию /root/flows, все дальнейшие
действия мы будем производить в ней:

mkdir /root/flows

Создадим файл flow.acl, в котором опишем необходимые
нам списки доступа, этот файл потом будет использоваться утилитой
flow-filter:

ip access-list standard localnet permit 192.168.2.0 0.0.0.255
ip access-list standard localnet deny any

ip access-list standard internet deny 192.168.2.0 0.0.0.255
ip access-list standard internet permit any

Здесь список localnet описывает адресное
пространство локальной сети, а список internet описывает адресное
пространство, трафик с которого мы будем считать. Если какие-то адреса
нужно внести в «бесплатную зону» — их нужно добавить в список internet
с директивой deny (По аналогии с адресным пространством локальной сети).

Так же ненужно забывать что при указании сетей в
этом файле нужно использовать инверсные маски. Если вы не очень
свободно работаете с такими масками — воспользуйтесь IP-калькулятором.

Следующим шагом создадим файл report.conf, который будет использоваться утилитой flow-report:

stat-report localnet
type ip-destination-address
output
format ascii
options +header,+xheader,+totals
fields -flows,-packets,-duration

stat-definition localnet
report localnet

На этом написание конфигурационных файлов
заканчивается и можно переходить к написанию скриптов. Сначала создадим
скрипт для генерации ежесуточных отчётов и сохраним под именем
stat_daily.sh. Вот его листинг:

#!/bin/sh

# Получаем вчерашнюю дату
RPT_Y=`/bin/date +%Y -d "-1 day"`
RPT_M=`/bin/date +%m -d "-1 day"`
RPT_D=`/bin/date +%d -d "-1 day"`

# Путь для хранения отчётов
RPT_DIR="/var/www/flow-reports/daily"

# Дата отчёта
RPT_DATE=${RPT_Y}-${RPT_M}-${RPT_D}

# Файл с отчётом
RPT_NAME=${RPT_DIR}/${RPT_DATE}.html

# Директория с логами
FLOW_DIR="/var/log/flow"

# Если вдруг директория для отчётов не существует - она будет создана
mkdir -p ${RPT_DIR}

# Создаём шапку отчёта
echo -e "<HTML>\n<HEAD>\n<TITLE>${RPT_DATE}</TITLE>\n</HEAD>\n<BODY>\n<H1>${RPT_DATE}</H1>\n" > ${RPT_NAME}

# Создаём отчёт
#
# Утилита flow-cat "выбрасывает" на стандартный вывод данные из логов
#
# утилита flow-filter выделяет из логов определённые данные.
# С помощью ключа -f указывается файл со списками доступа
# С помощью ключа -S указывается список, описывающий источник трафика
# С помощью ключа -D указывается список, описывающий получателя трафика (нашу локальную сеть)
#
# Утилита flow-report создаёт отчёт, используя один из предопределённых отчётов.
# Файл со список отчётов задаётся с помощью ключа -s, а конкретный отчёт - с помощью ключа -S
#
# Утилита flow-rptfmt форматирует отчёт, полученный с помощью flow-report.
# Ключ -f задаёт формат, а ключ -H отключает вывод заголовка со служебной информацией
/usr/bin/flow-cat ${FLOW_DIR}/${RPT_Y}/${RPT_Y}-${RPT_M}/${RPT_Y}-${RPT_M}-${RPT_D} \
|/usr/bin/flow-filter -f/root/flows/flow.acl -Sinternet -Dlocalnet \
|/usr/bin/flow-report -s /root/flows/report.conf -S localnet \
| /usr/bin/flow-rptfmt -f html -H >> ${RPT_NAME}

# Закрываем HTML-тэги в отчёте
echo -e "</BODY>\n</HTML>\n" >> ${RPT_NAME}

Делаем скрипт исполнимым и добавляем его запуск в cron:

chmod +x stat_daily.sh && echo "20 0 * * * root /root/flows/stat_daily.sh" >> /etc/cron.d/flow_stat

После этого каждый день в директории
/var/www/flow-reports/daily будут складываться отчёты о трафике за
предыдущий день. Отчёт будет выглядеть примерно вот так:

2009-02-01

ip-destination-address octets
192.168.2.3 1619973024
192.168.2.2 1954758
192.168.2.10 163242
192.168.2.4 548683

В колонке «ip-destination-address » отображается
адрес компьютера в локальной сети, а в колонке «octets» — потреблённый
трафик (в байтах).

Так же хорошо бы получать ежемесячные отчёты и удалять старые данные. Для этого создадим скрипт stat_monthly.sh:

#!/bin/sh

# Будем генерировать отчёт за предыдущий месяц
RPT_Y=`/bin/date +%Y -d "-1 month"`
RPT_M=`/bin/date +%m -d "-1 month"`

# Здесь всё практически тоже, что и в предыдущем скрипте
RPT_DIR="/var/www/flow-reports/monthly"

RPT_DATE=${RPT_Y}-${RPT_M}

RPT_NAME=${RPT_DIR}/${RPT_DATE}.html

FLOW_DIR="/var/log/flow"

# Дополнительная переменная - сюда будем архивировать старые логи
FLOW_DIR_OLD=${FLOW_DIR}/old

# Как и в предыдущем скрипте генерируем отчёт
mkdir -p ${RPT_DIR}

echo -e "<HTML>\n<HEAD>\n<TITLE>${RPT_DATE}</TITLE>\n</HEAD>\n<BODY>\n<H1>${RPT_DATE}</H1>\n" > ${RPT_NAME}

/usr/bin/flow-cat ${FLOW_DIR}/${RPT_Y}/${RPT_Y}-${RPT_M} \
|/usr/bin/flow-filter -f/root/flows/flow.acl -Sinternet -Dlocalnet \
|/usr/bin/flow-report -s /root/flows/report.conf -S localnet \
| /usr/bin/flow-rptfmt -f html -H >> ${RPT_NAME}

echo -e "</BODY>\n</HTML>\n" >> ${RPT_NAME}

# Переходим к удалению старых логов
# На всякий случай пересоздаём хранилище этих логов
mkdir -p ${FLOW_DIR_OLD}

# Пеерходим в директорию с логами за прошлый месяц
cd ${FLOW_DIR}/${RPT_Y}/${RPT_Y}-${RPT_M}

# Архивируем логи
/bin/tar -cjf ${FLOW_DIR_OLD}/${RPT_Y}-${RPT_M}.tar.bz2 ./

# Удаляем старые логи
cd ${FLOW_DIR}/${RPT_Y}
rm -rf ${FLOW_DIR}/${RPT_Y}/${RPT_Y}-${RPT_M}

Делаем скрипт исполняемым и добавляем его в cron:

chmod +x stat_monthly.sh && echo "30 0 1 * * root /root/flows/stat_monthly.sh" >> /etc/cron.d/flow_stat

На этом всё. В принципе учёт трафика можно настроить
и используя всего один сервер — для этого flow-сенсор должен отсылать
данные на адрес 127.0.0.1, а коллектор должен слушать на этом адресе.

Для доступа к отчётам можно поднять веб-сервер, или
настроить отправку этих отчётов на e-mail. Например для отправки
ежемесячных отчётов нужно добавить в скрипт stat_monthly.sh строку:

/usr/bin/uencode ${RPT_NAME} `/usr/bin/basename ${RPT_NAME}` | /usr/bin/mail -s "Traf Report" admin@some.host

На этом всё. Приятной работы!

Карта сайта: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34