# emerge -av trafd
# cat /etc/conf.d/trafd
# what interface to run on IFACE=eth1
# rc-update add trafd default
# mkdir /var/trafd/
# touch /var/trafd/trafd.eth1
# /etc/init.d/trafd start
echo “*/5 * * * * root /usr/bin/trafdump eth1; sleep 2; /usr/bin/trafsave eth1” » /etc/crontab
mysql> create database trafd;
mysql> grant all privileges on trafd.* to trafd@localhost identified by 'trafd';
#!/bin/sh # Вводим данные для подключения к MySQL серверу # IP адрес MySQL сервера IP_MySQL_servera="localhost" # Имя пользователя для доступа к БД в которой храниться траффик username="trafd" # Пароль пользователя MySQL user_passw="trafd" # Имя базы данных db_name="trafd" # поехали # Сегодяшний день day="`date +%Y-%m-%d`" # Текущий год year="`date +%Y`" # Текущий месяц month="`date +%m`" # Текущее время (секунды специально сделаны 00 - иногда cron запускает скрипт не # в 00 секунд а позже (максимум что я видел - в 13), если машина очень загружена - # как итог в логах начинает фигурировать разное число секунд. # Мне это непонравилось :) curr_time="`date +%H:%M:00`" # Директория в которой будут храниться текстовые файлы с логами trafd NewDir="/var/traffic/${year}/${month}" # Пытаемся создать эту самую директорию на случай если это первый запуск # или произошла смена месяца (года) mkdir -p ${NewDir} # Ну и топаем туда cd ${NewDir} # Местоположение исполняемого файла клиента MySQL mysql="/usr/bin/mysql" # Префикс для команд (лень же каждый раз набивать параметры подключения) sql_preffix="${mysql} --host=${IP_MySQL_servera} \ --user=${username} --password=${user_passw} --database=${db_name}" # Для всех интерфейсов выковырнутых из rc.conf (висят в ${trafd_ifaces}) # выполняем один и тот же набор действий по разбору логов и запихиванию # их в базу данных for iface in "eth1" do # Сохраняем статистику по текущему интерфейсу /usr/bin/trafsave ${iface} # Преобразуем логи из двоичного в текстовый формат. Сохраняются они в # папке /tmp в виде файлов summary.* c расширением по имени интерфейса /usr/bin/traflog -i ${iface} -a -n -s > /tmp/summary.${iface} 2>/dev/null # Очищаем файл с логами в двоичном формате cat /dev/null > /var/trafd/trafd.${iface} # Дозаписываем логи в текстовый файл (пусть лежат на всякий случай...) cat /tmp/summary.${iface} >> ${NewDir}/summary.${iface} # Далее - загоняем траффик в БД # ${sql_preffix} --execute="CREATE TABLE \`traffic_tmp\` \ (\`date\` DATE NOT NULL, \`time\` TIME NOT NULL, \ \`from_IP\` CHAR(16) NOT NULL, \`port_from_IP\` CHAR(8) NOT NULL, \ \`to_IP\` CHAR(16) NOT NULL, \`port_to_IP\` CHAR(8) NOT NULL, \ \`protocol\` ENUM('icmp','tcp','udp') NOT NULL, \`bytes\` int(16) NOT NULL, \ \`all_bytes\` int(16) NOT NULL) TYPE=MyISAM COMMENT='tmp_table'" 2>/dev/null # Лопатим данные для интерфейса ${iface} # Очищаем временную таблицу ${sql_preffix} --execute="DELETE FROM \`traffic_tmp\`" # Построчно превращаем файл со статистикой в набор переменных grep -v "^ " /tmp/summary.${iface} | { while read stroka do from_IP=`echo "${stroka}" | awk '{print $1}'` port_from_IP=`echo "${stroka}" | awk '{print $2}'` to_IP=`echo "${stroka}" | awk '{print $3}'` port_to_IP=`echo "${stroka}" | awk '{print $4}'` protocol=`echo "${stroka}" | awk '{print $5}'` bytes=`echo "${stroka}" | awk '{print $6}'` all_bytes=`echo "${stroka}" | awk '{print $7}'` # Загоняем полученный набор во временную таблицу ${sql_preffix} --execute="INSERT INTO \`traffic_tmp\` (\`date\`, \ \`time\`, \`from_IP\`, \`port_from_IP\`, \`to_IP\`, \`port_to_IP\`, \ \`protocol\`, \`bytes\`, \`all_bytes\`) \ values ('${day}', '${curr_time}', '${from_IP}', \ '${port_from_IP}', '${to_IP}', '${port_to_IP}', \ '${protocol}', '${bytes}', '${all_bytes}')" done } # Стираем пустые строки (а вот откуда они вылазиют я так и непонял....) ${sql_preffix} --execute="DELETE FROM \`traffic_tmp\` WHERE from_IP='' AND \ port_from_IP='' AND to_IP='' AND port_to_IP='' AND protocol=''" # Стираем строки в которых полное число байт (вместе с технической инфой) # равно нулю (тоже непойми откуда берутся - раз в статистику trafd попали - # значит соединение было и байты должны были б быть...) ${sql_preffix} --execute="DELETE FROM \`traffic_tmp\` WHERE all_bytes='0'" # Создаём таблицу для окончательного хранения траффика # (на тот случай если она не создана - хотя конечно тоже дурацкий вариант - # пытаться создать таблицу при каждом запуске скрипта, но другой вариант - # проверять существование и если нету её - то создавать. А какая разница? Так # как сделано сейчас - проще и менее ресурсоёмко) ${sql_preffix} --execute="CREATE TABLE \`${iface}_${year}\` \ (\`unic_id\` INT(16) NOT NULL AUTO_INCREMENT, \ \`date\` DATE NOT NULL, \`time\` TIME NOT NULL, \ \`from_IP\` CHAR(16) NOT NULL, \`port_from_IP\` CHAR(8) NOT NULL, \ \`to_IP\` CHAR(16) NOT NULL, \`port_to_IP\` CHAR(8) NOT NULL, \ \`protocol\` ENUM('icmp','tcp','udp') NOT NULL, \`bytes\` int(16) NOT NULL, \ \`all_bytes\` int(16) NOT NULL, \ PRIMARY KEY (\`unic_id\`), \ KEY \`date\`(\`date\`) \ ) TYPE=MyISAM COMMENT='База \ данных траффика по (${iface}) интерфейсу за ${year} год'" 2>/dev/null # Перекидываем траффик из временной таблицы в окончательную, при этом # объединяем строки в которых совпадает ВСЁ кроме числа байт. ${sql_preffix} --execute="INSERT INTO \`${iface}_${year}\`\ (\`date\`, \`time\`, \`from_IP\`, \`port_from_IP\`, \`to_IP\`,\ \`port_to_IP\`, \`protocol\`, \`bytes\`, \`all_bytes\`) \ SELECT \`date\`, \`time\`, \`from_IP\`, \`port_from_IP\`,\ \`to_IP\`, \`port_to_IP\`, \`protocol\`, sum(\`bytes\`) as \`bytes\`,\ sum(\`all_bytes\`) as \`all_bytes\` FROM \ \`traffic_tmp\` GROUP BY \`date\`, \`time\`, \`from_IP\`, \`port_from_IP\`,\ \`to_IP\`, \`port_to_IP\`, \`protocol\`" done ${sql_preffix} --execute="delete from \`${iface}_${year}\` where \`from_IP\`='192.168.0.1'" ${sql_preffix} --execute="delete from \`${iface}_${year}\` where \`to_IP\`='192.168.0.1'" # Очищаем файл c логами о том когда и по какому интерфейсу сохранялась статистика cat /dev/null > /var/log/traffic.log
# echo “1 * * * * root /usr/local/bin/trafd.sh” » /etc/crontab
mysql> CREATE TABLE `ip_list` ( `ip_address` char(16) NOT NULL, `day_used int(16)`, `day_limit` int(16) NOT NULL, `is_blocked` tinyint(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
for i in `seq 2 254`;do echo "INSERT INTO ip_list VALUES ('192.168.0.$i',0,104857600,0);";done|mysql -utrafd -ptrafd trafd
#!/usr/bin/perl use DBI; use DBD::mysql $platform = "mysql"; $database = "trafd"; $host = "localhost"; $port = "3306"; $user = "trafd"; $pw = "trafd"; $tablename = "eth1_".`date +%Y`; $date=`date +%Y-%m-%d`; chomp($date); chomp($tablename); # DATA SOURCE NAME $dsn = "dbi:$platform:$database:$host:$port"; # PERL DBI CONNECT $connect = DBI->connect($dsn, $user, $pw); $queryip="select ip_address from ip_list;\n"; #print ($queryip."\n"); $queryip_handle = $connect->prepare($queryip); $queryip_handle->execute(); $queryip_handle->bind_columns(undef, \$ip); print (`date`); while ($queryip_handle->fetch()) { print($ip."\n"); $query="select sum(all_bytes) from ".$tablename." where date='".$date."' and (to_IP='".$ip."' or from_IP='".$ip."');\n"; # print($query); $query_handle = $connect->prepare($query); $query_handle->execute(); $query_handle->bind_columns(undef, \$sum); $query_handle->fetch(); $query_handle->finish; $sum=0+$sum; print("sum bytes for ".$ip." is ".$sum."\n"); $query="select * from ip_list where ip_address='".$ip."';\n"; # print ($query); $query_handle = $connect->prepare($query); $query_handle->execute(); $query_handle->bind_columns(undef, \$ip_address, \$day_used, \$day_limit, \$is_blocked); $query_handle->fetch(); $query_handle->finish; print ("ip_address: ".$ip_address."\n"); print ("day_limit: ".$day_limit."\n"); print ("is_blocked: ".$is_blocked."\n"); print("limit bytes for ".$ip." is ".$day_limit."\n"); $query="update ip_list set day_used=".$sum." where ip_address='".$ip_address."';\n"; $query_handle = $connect->prepare($query); $query_handle->execute(); if ($sum>=$day_limit) { print ("traffic quota exceeded\n"); if ($is_blocked==0) { print ("ip is not blocked.. i'm blocking it...\n"); $runstr="sudo iptables -I FORWARD -s ".$ip_address." -j DROP"; print ($runstr); system($runstr); $query="update ip_list set is_blocked=1 where ip_address='".$ip_address."';\n"; $query_handle = $connect->prepare($query); $query_handle->execute(); }#$is_blocked==0 }#if ($sum>=$day_limit) if ($sum<$day_limit) { if ($is_blocked==1) { print ("ip is blocked.. i'm removing it...\n"); $runstr="sudo iptables -D FORWARD -s ".$ip_address." -j DROP"; print ($runstr); system($runstr); $query="update ip_list set is_blocked=0 where ip_address='".$ip_address."';\n"; $query_handle = $connect->prepare($query); $query_handle->execute(); } } print ("\n"); } #while $queryip_handle->finish; $connect->disconnect;
echo “5 * * * * root /usr/local/bin/trafblock.pl » /var/log/trafblock.log” » /etc/crontab