В Втр, 14/08/2007 в 12:24 +0400, Alexander GQ Gerasiov пишет: > На Mon, 13 Aug 2007 19:12:42 +0400 > "Sapytsky Ilya" <[EMAIL PROTECTED]> записано: > > > 2007/8/11, Nicholas <[EMAIL PROTECTED]>: > > > > > > Sapytsky Ilya wrote: > > > > надо собирать сколько выкачали клиенты с заранее заданными ip и > > > > общий траффик во времени. > > > > > > ntop ? > > > > > спасибо, посмотрел, интересная штука, только не понял как в ней можно > > посмотреть точную сумму в байтах траффика за месяц июль например.... > ты еще обрати внимание, что при перезапуске оно теряем все свои данные.
вот для слаквари подсчёт чел навалял... Графика пока нет, собрал статистику (bash+crond+bc+iptables): Ниже настроенный под домолинк вариант (внешняя сеть закрыта кроме прокси, открыта локальная.) Комментариев нет. Файервол (bash скрипт): Скрипт нужно запускать после запуска системы (в slackware это /etc/rc.d/rc.local) Код: #!/bin/sh #firewall script echo firewall script started CARD_MASK="192.168.1.2/32" ROUTER="192.168.1.1/32" BVF="84.17.243.19/32" RANGE1="77.45.128.0/255.255.128.0" RANGE2="80.82.32.0/255.255.224.0" RANGE3="88.83.192.0/255.255.224.0" FREE[0]=$RANGE1 FREE[1]=$RANGE2 FREE[2]=$RANGE3 FREE[3]="" KILL[0]="80.82.32.10/32" KILL[1]="80.82.32.19/32" KILL[2]="" PAID[0]="80.82.32.27/32" PAID[1]="80.82.32.11/32" PAID[2]="" LOCAL="127.0.0.1/32" iptables --flush iptables -X iptables -N local_in iptables -N local_out iptables -N extern_in iptables -N extern_out iptables -N total_in iptables -N total_out iptables -N kill_in iptables -N kill_out iptables -N kill_all iptables -N extern_all iptables -N local_all iptables -N total_all iptables -A local_all -j ACCEPT iptables -A extern_all -j ACCEPT #следущую строчку можно закомментить #если не требуется отладить файерволл iptables -A kill_all -j LOG iptables -A kill_all -j REJECT --reject-with icmp-net-prohibited iptables -A kill_all -j DROP iptables -A total_all -j RETURN iptables -A total_in -g total_all iptables -A total_out -g total_all iptables -A local_in -g local_all iptables -A local_out -g local_all iptables -A extern_in -g extern_all iptables -A extern_out -g extern_all iptables -A kill_in -g kill_all iptables -A kill_out -g kill_all iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP iptables -A INPUT -s $LOCAL -d $LOCAL -i lo -j ACCEPT iptables -A OUTPUT -s $LOCAL -d $LOCAL -o lo -j ACCEPT iptables -A INPUT -p all -s $ROUTER -d $CARD_MASK -j ACCEPT iptables -A INPUT -p all -s $CARD_MASK -d $CARD_MASK -j ACCEPT iptables -A OUTPUT -p all -s $CARD_MASK -d $ROUTER -j ACCEPT #iptables -A OUTPUT -p all -s $CARD_MASK -d $CARD_MASK -j ACCEPT i=0 while [ "${KILL[$i]}" != "" ] do iptables -A INPUT -p all -s ${KILL[$i]} -j kill_in iptables -A OUTPUT -p all -d ${KILL[$i]} -j kill_out i=$(($i+1)) done iptables -A INPUT -p all -j total_in iptables -A OUTPUT -p all -j total_out iptables -A INPUT -p tcp -s $BVF -d $CARD_MASK -j local_in iptables -A OUTPUT -p all -s $CARD_MASK -d $BVF -j local_out i=0 while [ "${PAID[$i]}" != "" ] do iptables -A INPUT -p all -s ${PAID[$i]} -j extern_in iptables -A OUTPUT -p all -d ${PAID[$i]} -j extern_out i=$(($i+1)) done i=0 while [ "${FREE[$i]}" != "" ] do iptables -A INPUT -p all -s ${FREE[$i]} -d $CARD_MASK -j local_in iptables -A OUTPUT -p all -s $CARD_MASK -d ${FREE[$i]} -j local_out i=$(($i+1)) done iptables -A INPUT -p all -j kill_in iptables -A OUTPUT -p all -j kill_out #iptables -A INPUT -p icmp -j ACCEPT #iptables -A POSTROUTING -p all -s 127.0.0.1 -d 80.82.32.27 CARD_MASK="" RANGE1="" RANGE2="" RANGE3="" LOCAL="" Учетчик траффика. Должен быть установлен в /usr/lib/vsi-traf Если устанавливался в др место, нужно изменить переменную BASE на "правильный путь" файл должен называться traffic.sh Код: #!/bin/sh #this script is provided "as is" with no warranty of any kind. #this script can be freely distributed on the terms of GPL license;) #Made by ErV ([EMAIL PROTECTED]) BASE=/usr/lib/vsi-traf DATA=$BASE/data HOUR=`date +%H` DAY=`date +%d` WEEK=`date +%W` WEEK=$(($WEEK%4)) MONTH=`date +%m` YEAR=`date +%Y` LOCK_FILE="$BASE/lock" MONTH_DIR="$YEAR/$MONTH" WEEK_DIR="$MONTH_DIR/weeks" DAY_DIR="$MONTH_DIR/$DAY" BYTES_HOUR="$DAY_DIR/$HOUR:00-$HOUR:59" BYTES_DAY="$MONTH_DIR/$DAY.total" BYTES_WEEK="$WEEK_DIR/$WEEK.total" BYTES_MONTH="$YEAR/$MONTH.total" BYTES_YEAR="$YEAR.total" CURRENT_HOUR="this_hour" CURRENT_DAY="this_day" CURRENT_WEEK="this_week" CURRENT_MONTH="this_month" CURRENT_YEAR="this_year" GET_BYTES=$BASE/iptable.pl CHAINS[0]="extern_in" CHAINS[1]="extern_out" CHAINS[2]="local_in" CHAINS[3]="local_out" CHAINS[4]="total_in" CHAINS[5]="total_out" CHAINS[6]="" force_directory(){ #echo "$1" if [ ! -r "$1" ]; then mkdir "$1"; fi; } #arg 1 - fuction that accepts chain name for_each_chain(){ i=0; while [ "${CHAINS[$i]}" != "" ]; do $1 ${CHAINS[$i]}; i=$(($i+1)) done; } check_chain_dir(){ force_directory "$DATA/$1" force_directory "$DATA/$1/$YEAR" force_directory "$DATA/$1/$MONTH_DIR" force_directory "$DATA/$1/$WEEK_DIR" force_directory "$DATA/$1/$DAY_DIR" } force_counter(){ if [ ! -r "$1" ]; then echo "0" > "$1"; fi # if [ `cat "$1"` == "" ]; then # echo "0" > "$1"; # fi } check_chain_counters(){ CHAIN_DIR="$DATA/$1" force_counter "$CHAIN_DIR/$BYTES_HOUR" force_counter "$CHAIN_DIR/$BYTES_DAY" force_counter "$CHAIN_DIR/$BYTES_WEEK" force_counter "$CHAIN_DIR/$BYTES_MONTH" force_counter "$CHAIN_DIR/$BYTES_YEAR" ln -s -f "$CHAIN_DIR/$BYTES_HOUR" "$CHAIN_DIR/$CURRENT_HOUR" ln -s -f "$CHAIN_DIR/$BYTES_DAY" "$CHAIN_DIR/$CURRENT_DAY" ln -s -f "$CHAIN_DIR/$BYTES_WEEK" "$CHAIN_DIR/$CURRENT_WEEK" ln -s -f "$CHAIN_DIR/$BYTES_MONTH" "$CHAIN_DIR/$CURRENT_MONTH" ln -s -f "$CHAIN_DIR/$BYTES_YEAR" "$CHAIN_DIR/$CURRENT_YEAR" } check(){ force_directory $DATA for_each_chain check_chain_dir for_each_chain check_chain_counters } #$1 is a counter file $2 is a value to add inc_counter(){ PREV_BYTES=0 if [ -s $1 ]; then PREV_BYTES=`cat $1`; fi echo "$PREV_BYTES + $2"|bc > $1; } #$1 is a chain name, $2 is a new added value chain_inc_counters(){ BYTES="$2" CHAIN_DIR="$DATA/$1" inc_counter "$CHAIN_DIR/$BYTES_HOUR" "$BYTES" inc_counter "$CHAIN_DIR/$BYTES_DAY" "$BYTES" inc_counter "$CHAIN_DIR/$BYTES_WEEK" "$BYTES" inc_counter "$CHAIN_DIR/$BYTES_MONTH" "$BYTES" inc_counter "$CHAIN_DIR/$BYTES_YEAR" "$BYTES" } chain_update_normal(){ BYTES=`$GET_BYTES $1` chain_inc_counters "$1" "$BYTES" } lock(){ echo "0" > "$LOCK_FILE" } unlock(){ rm "$LOCK_FILE" } update_normal(){ if [ ! -r "$LOCK_FILE" ]; then lock; check; for_each_chain chain_update_normal; unlock; else echo another instance already working fi; } case $1 in 'check') check;; 'update') update_normal;; 'unlock') unlock;;#use only after system restart!!! 'lock') lock;; *) echo unknown argument echo "usage traf [update|check|lock|unlock]" esac Перл-скрипт, который должен находится в папке с учетчиком. (имя должное быть iptable.pl). Пойдет любая другая утилита, которая берет в качестве параметров имя цепочки iptables и возвращает число байт, попутно обнуляя счетчик. Скрипт изначально не мой, копирайты сохранены. Код: #!/usr/bin/perl ## ## This is a quick perl script to ## pull bandwidth usage from iptables chains ## ## If you use/optimize this script, please let me know. ## Brian Stanback : brian [at] stanback [dot] net # ## Example iptables rule for web bandwidth usage: ## > iptables -N WWW ## > iptables -A WWW -j ACCEPT ## > iptables -A INPUT -p tcp -m tcp --dport 80 -j WWW ## > iptables -A OUTPUT -p tcp -m tcp --sport 80 -j WWW ## ## Run "iptables.pl WWW" as root to test, note that you can ## combine more than one protocol into a single chain. ## ## Sudo Configuration (/etc/sudoers) ## > www-data ALL = NOPASSWD: /usr/share/cacti/scripts/iptables.pl ## ## The Input String should be set to "sudo <path_cacti>/scripts/iptables.pl <chain>" ## and you will need to setup an input field so that the <chain> argument can be passed. ## ## The data input type should be set to COUNTER ## # # # modified by: Paul Campbell <[EMAIL PROTECTED]> # Now returns a seperate entry for each rule. Output for a # 3 rule chain might now be: # rule1:123 rule2:456 rule3:789 # # Modified by ErV. Now outputs number of bytes only. if ($ARGV[0]) { $chains = `/usr/sbin/iptables --line-number -xnvL $ARGV[0]`; `/usr/sbin/iptables --zero $ARGV[0]`; @chains = split(/\n/, $chains); shift(@chains); shift(@chains); foreach( @chains ) { /(\d+)\W+[0-9]+\W+([0-9]+)\W+/; # print " rule$1:$2"; print"$2"; } print "\n"; #$chains[2] =~ /[\W+]?[0-9]+\W+([0-9]+)\W+/; } else { print "Usage: $0 Chain\n"; } Скрипт traffic.sh должен иметь право на запись в той папке, в которой он установлен (например, chmod g+s) Для работы счетчика на машине должен быть установлен bc - для подсчета количества байт с высокой точностью (без ограничения на количество цифр - в iptables есть лимит в 936мб). Скрипт не быстрый (из-за bc). Для моей конфигурации (6 цепочек) он занимает где-то секунду. Для работы нужно запихнуть вызов скрипта при запуске системы с параметром unlock (traffic.sh unlock) - на случай маловероятного сбоя из-за отключения питания в момент работы скрипта Далее, нужно запихнуть в cron вызов скрипта с параметром update (то есть traffic.sh update), например, каждые 5 минут и на 59 минуте каждого часа. Минимум вызов нужен 1 раз в час (на 59 минуте, например), можно сделать его чаще, чтобы статистика активнее обновляляась. Пример линии из crontab: Код: */5,59 * * * * /usr/bin/bash /usr/lib/vsi-traf/traffic.sh update > /dev/null Также необходим один вызов скрипта с параметром update при выключении системы (для сохранения статистики). После запуска скрипт создаст подкаталог дата, раскидает статистику по папка. В простейшем виде - в текстовом файле, в котором будте храниться число скачанных байт за период, которому файл соответствует. Т.е. типичный вариант каталогов: chain_name/2007.total - число байт прошедших сквозь отслеживаемую цепочку (chain_name) за этот год. chain_name/2007 - каталог с данным по месяцам для этой цепочки. chain_name/2007/04.total - общее число байт за апрель chain_name/2007/04/ - папка с данными по апрелю chain_name/2007/04/weeks - понедельная статистика за апрель chain_name/2007/04/08 - почасовая статистика за 8е апреля. chain_name/2007/04/08.total - общее число байт за 8е апреля (обновляется в процессе работы) chain_name/2007/04/08/23:00-23:59 - число байт за час до полуночи, 8го апреля 2007. Кроме этого в корне chain_name будут ярлыки на статистику за текущий день, месяц, неделю, год и час. Ярлыки будут обновляться автоматом. (т.е. пока cron вызывает скрипт, они будут указывать на корректные файлы). Вариант не самый "красивый" внешне, но наиболее гибкий и пуленепробиваемый для подсчета месечного/недельного/годового обьема траффика. Скрипты легко модифицируются. Если кому-то нужны красивые таблички с отчетами, то для них можно накатать Perl/Html генератор. ------ Добавлено. Скрипт firewall'а отличается от того, что был изначально выложен на u-antona.vrn.ru. Добавлено: 1) "#iptables -A OUTPUT -p all -s $CARD_MASK -d $CARD_MASK -j ACCEPT" Может потребоваться только если нужно разрешить сетевухе отправлять запросы самой себе. Поэтому закомментировано. 2) "iptables -A kill_all -j LOG" Это строчка полезна, если нужно просмотреть список "убитых" пакетов (т.е. тех, что сквозь файерволл не прошли). Информацию о убитых пакетах можно прочитать, вызвав dmesg. Если отсекать надо много, то лучше закомментировать эту строку, иначе лог-файл может быстро вырасти. --- Возникавшие вопросы: Q: что нужно добавить к скрипту файрволла, чтобы асю разрешить? A.: (ответ не полный, просто "указатель направления") Либо тут: Код: PAID[0]="80.82.32.27/32" PAID[1]="80.82.32.11/32" PAID[2]="" Пробуем добавить объявление login.icq.com или его ip-адреса (лучше ip адрес, так как иначе при запуске скрипт может обломаться из-за невозможности разрешить DNS - если интернет выключен) По типу: Код: PAID[0]="80.82.32.27/32" PAID[1]="80.82.32.11/32" PAID[2]="64.12.200.89/32" PAID[3]="" Это разрешит все соединения с login.icq.com, на все порты. Либо после этого: Код: i=0 while [ "${PAID[$i]}" != "" ] do iptables -A INPUT -p all -s ${PAID[$i]} -j extern_in iptables -A OUTPUT -p all -d ${PAID[$i]} -j extern_out i=$(($i+1)) done Добавляем прямое объявление доступа к асе. Только нужно будет jump'ы соответствующие добавить, чтобы траффик считался. По типу (не тестил, проверяйте ): Код: i=0 ICQIP="64.12.200.89/32" ICQPORT="5190" iptables -A INPUT -p all -s $ICQIP --sport $ICQPORT -j extern_in iptables -A OUTPUT -p all -d $ICQIP --dport $ICQPORT -j extern_out Это разрешит соединения ТОЛЬКО с портом 5190 на login.icq.com (адрес взял nslookup'ом). Если не пашет, надо порыть, к чему ещё ася коннектится (и в какую сторону с каким портом) и открыть доступ аналогичным методом. Да, и чуть не забыл. Скрипт предоставляется "как есть", без гарантий, и может быть распространен на базе GPL с соблюдением исходного авторства. По вопросам установки в специфический дистрибутив лезем либо в документацию, либо в гугл -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]