Долго собирался доделать — и все-таки у меня получилось)
Если интересно — прошу под кат:
Что имеем:
[root@broken.ufanet.ru:~]#ifconfig
re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=389b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_UCAST,WOL_MCAST,WOL_MAGIC>
ether 00:12:34:56:78:90
inet 10.PP.II.SS netmask 0xffffff00 broadcast 10.PP.II.255
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
ral0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 2290
ether 00:09:87:65:43:21
media: IEEE 802.11 Wireless Ethernet autoselect mode 11g <hostap>
status: running
ste0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=82008<VLAN_MTU,WOL_MAGIC,LINKSTATE>
ether 00:11:22:33:44:55
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
plip0: flags=8810<POINTOPOINT,SIMPLEX,MULTICAST> metric 0 mtu 1500
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=3<RXCSUM,TXCSUM>
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x5
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
bridge0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether 00:33:55:77:99:99
inet 192.168.99.1 netmask 0xffffff00 broadcast 192.168.99.255
id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
maxage 20 holdcnt 6 proto rstp maxaddr 100 timeout 1200
root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0
member: ste0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
ifmaxaddr 0 port 3 priority 128 path cost 55
member: wlan0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
ifmaxaddr 0 port 7 priority 128 path cost 370370
wlan0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether
00:09:87:65:43:21
media: IEEE 802.11 Wireless Ethernet autoselect mode 11g <hostap>
status: running
ssid MY_SSID channel 6 (2437 MHz 11g) bssid 00:19:5b:6e:96:a1
country US authmode WPA2/802.11i privacy MIXED deftxkey 2
TKIP 2:128-bit TKIP 3:128-bit txpower 0 scanvalid 60 protmode CTS
dtimperiod 1 -dfs
ng0: flags=89d1<UP,POINTOPOINT,RUNNING,NOARP,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1400
inet XY.ZA.RT.CV --> XY.ZA.QE.U netmask 0xffffffff
pflog0: flags=141<UP,RUNNING,PROMISC> metric 0 mtu 33200
Маки, IP’ы и SSID поменял, не имеют значения, кроме сети моей локалки)
Итак, начнем:
Переходим в папку с портом и компилируем flow-tools
cd /usr/ports/net-mgmt/flow-tools
Затем простое и понятное
make
┌───────── flow-tools-0.68_7 ────────────┐ │ ┌────────────────────────────────────┐ │ │ │ [ ] MYSQL Enable MySQL support │ │ │ │ [ ] OPENSSL Enable OpenSSL support │ │ │ │ [ ] PGSQL Enable PostgreSQL support│ │ │ └────────────────────────────────────┘ │ ├────────────────────────────────────────┤ │ < OK > <Cancel> │ └────────────────────────────────────────┘
Нам поддержки DB и SSL не нужны, поэтому и не ставим.
Теперь собираем SoftFlowd:
cd /usr/ports/net-mgmt/softflowd && make install clean
Теперь готовим место, куда будем складывать потоки netflow/ Я заморачиваться не стал, и кладу их на резервный раздел :)
mkdir -p /backup/flows/bridge0/ /backup/flows/ng0/ && chown -R flowtools /backup/flows
Теперь нужно включить и настроить коллекторы и сенсоры в rc.conf
Содержимое /etc/rc.conf
softflowd_enable="YES" softflowd_interfaces="ng0 bridge0" softflowd_ng0_collector="127.0.0.1:9999" softflowd_bridge0_collector="127.0.0.1:9998"
flow_capture_enable="YES" flow_capture_localip="127.0.0.1" flow_capture_remoteip="127.0.0.1" flow_capture_profiles="ng0 bridge0"flow_capture_ng0_datadir="/backup/flows/ng0" flow_capture_ng0_port="9999" flow_capture_ng0_flags="-n 287 -N 3"flow_capture_bridge0_datadir="/backup/flows/bridge0" flow_capture_bridge0_port="9998" flow_capture_bridge0_flags="-n 287 -N 3"
Немного опишу строчки:
Включаем flow_capture:flow_capture_enable="YES"
Указываем локальный IP, на котором будем слушатьflow_capture_localip="127.0.0.1"
Указываем удаленный IP, с которого будем принимать потоки:flow_capture_remoteip="127.0.0.1"
Указываем профили, которые описываются чуток ниже:flow_capture_profiles="ng0 bridge0"
Показываем, куда надо складывать потокиflow_capture_ng0_datadir="/backup/flows/ng0"
Порт, на котором будем слушатьflow_capture_ng0_port="9999"
И флаги:flow_capture_ng0_flags="-n 287 -N 3"
-n rotations Configure the number of times flow-capture will create a new file per day. The default is 95, or every 15 minutes.
Короче тут указывается сколько раз ротировать файлы потоков - у меня стоит 287 - то есть каждые 5 минут
-N nesting_level Configure the nesting level for storing flow files. The default is 0. -3 YYYY/YYYY-MM/YYYY-MM-DD/flow-file -2 YYYY-MM/YYYY-MM-DD/flow-file -1 YYYY-MM-DD/flow-file 0 flow-file 1 YYYY/flow-file 2 YYYY/YYYY-MM/flow-file 3 YYYY/YYYY-MM/YYYY-MM-DD/flow-file
А тут указывается вид того, как будут лежать файлы)
Включаем softflowd:softflowd_enable="YES"
Описываем интерфейсы, с которых нужно снимать поток:softflowd_interfaces="ng0 bridge0"
Указываем куда слать:softflowd_ng0_collector="127.0.0.1:9999" softflowd_bridge0_collector="127.0.0.1:9998"
В разных источниках пишутся странные вещи, типа у softflowd нет нормального rc-скрипта, хотя у меня был нормальный, на всякий случай приведу его здесь:
#!/bin/sh
# $FreeBSD: ports/net-mgmt/softflowd/files/softflowd.in,v 1.5 2012/11/17 06:00:38 svnexp Exp $# (c) 2010 Tom Judge# PROVIDE: softflowd # REQUIRE: LOGIN # KEYWORD: shutdown# softflowd_enable="YES" # softflowd_interfaces="em0 em1" # softflowd_em0_collector="collector:1234" # softflowd_em1_collector="collector:1235" # softflowd_em0_timeouts="-t maxlife=300" # softflowd_em1_timeouts="-t maxlife=600" # softflowd_em0_max_states="16000" # softflowd_em1_max_states="17000" # softflowd_em0_extra_args # softflowd_em1_extra_args. /etc/rc.subrname=softflowd rcvar=softflowd_enablestart_precmd="softflowd_precommand $@" stop_precmd="softflowd_precommand $@" status_precmd="softflowd_precommand $@" poll_precmd="softflowd_precommand $@" rcvar_precmd="softflowd_precommand $@" stop_cmd="softflowd_stop" command="/usr/local/sbin/softflowd" _pidprefix="/var/run/softflowd" if [ -n $2 ]; then pidfile="${_pidprefix}.${2}.pid" fiload_rc_config $namesoftflowd_enable=${softflowd_enable:-"NO"} softflowd_timeouts="-t maxlife=300" softflowd_max_states="16000"softflowd_precommand () { if [ -n "$2" ]; then profile="$2" ctlfile="${_pidprefix}.${profile}.ctl" eval apache22_flags="\${apache22_${profile}_flags:-${apache22_flags}}" eval softflowd_collector="\${softflowd_${profile}_collector}" if [ "x${softflowd_collector}" = "x" ]; then echo "ERROR: You must specify a collector to send data to." exit 1 fi eval softflowd_timeouts="\${softflowd_${profile}_timeouts:-${softflowd_timeouts}}" eval softflowd_max_states="\${softflowd_${profile}_max_states:-${softflowd_max_states}}" eval softflowd_extra_args="\${softflowd_${profile}_extra_args:-${softflowd_extra_args}}" command_args="-i ${profile} -n ${softflowd_collector} -m ${softflowd_max_states} -p ${pidfile} -c ${ctlfile} ${softflowd_timeouts} ${softflowd_extra_args}" else if [ "x${softflowd_interfaces}" != "x" ]; then for profile in ${softflowd_interfaces}; do echo "===> softflowd profile: ${profile}" /usr/local/etc/rc.d/softflowd $1 ${profile} retcode="$?" if [ "0${retcode}" -ne 0 ]; then failed="${profile} (${retcode}) ${failed:-}" else success="${profile} ${success:-}" fi done fi exit 0 fi }softflowd_stop() { /usr/local/sbin/softflowctl -c ${ctlfile} shutdown }run_rc_command "$1"
И самое вкусное, для чего все это делалось :)
mkdir /usr/local/scripts
Создаем файлик stat-flow.acl с таким содержанием:
ip access-list standard localnet permit 192.168.99.0 0.0.0.255 ip access-list standard localnet permit $MY_WHITE_IP 0.0.0.0 ip access-list standard localnet deny any
ip access-list standard internet deny 192.168.99.0 0.0.0.255 ip access-list standard internet deny $MY_WHITE_IP 0.0.0.0 ip access-list standard internet permit any
Вместо $MY_WHITE_IP - Вписываем свой статический белый IP адрес, либо, если у вас его нет - удаляем строку Дополнение - если вы хотите поместить какой-либо белый адрес в "бесплатную зону", то его нужно поместить в зону internet с префиксом deny
Теперь делаем файлик stat-internet.conf
stat-report internet type ip-source-address output format ascii sort +flows options +header,+xheader,+totals fields -flows
stat-definition internet report internet
И stat-localnet.conf
stat-report localnet type ip-destination-address output format ascii sort +flows options +header,+xheader,+totals fields -flows,
stat-definition localnet report localnet
И самое главное - скрипты, жующие файлы потоков и на выходе выплевывающие статистику: stat_daily.sh
#!/bin/sh
# Получаем вчерашнюю дату RPT_Y=`/bin/date -v-1d +%Y` RPT_M=`/bin/date -v-1d +%m` RPT_D=`/bin/date -v-1d +%d` #RPT_D=`/bin/date +%d`# Путь для хранения отчётов RPT_DIR="/usr/local/www/apache22/data/flow-reports/daily"# Дата отчёта RPT_DATE=${RPT_Y}-${RPT_M}-${RPT_D}# Файл с отчётом RPT_NAMEbr=${RPT_DIR}/${RPT_DATE}"_bridge0.html" RPT_NAMEbrfull=${RPT_DIR}/${RPT_DATE}"_bridge0_full.html" RPT_NAMEng=${RPT_DIR}/${RPT_DATE}"_ng0.html" RPT_NAMEngfull=${RPT_DIR}/${RPT_DATE}"_ng0_full.html"# Директория с логами FLOW_DIRbr="/backup/flows/bridge0/" FLOW_DIRng="/backup/flows/ng0/"# Если вдруг директория для отчётов не существует - она будет создана mkdir -p ${RPT_DIR}# Создаём шапку отчёта echo -e "<HTML><HEAD><TITLE>${RPT_DATE}</TITLE></HEAD><BODY><H1>${RPT_DATE}</H1>" > ${RPT_NAMEbr} echo -e "<HTML><HEAD><TITLE>${RPT_DATE}</TITLE></HEAD><BODY><H1>${RPT_DATE}</H1><pre>" > ${RPT_NAMEbrfull} echo -e "<HTML><HEAD><TITLE>${RPT_DATE}</TITLE></HEAD><BODY><H1>${RPT_DATE}</H1>" > ${RPT_NAMEng} echo -e "<HTML><HEAD><TITLE>${RPT_DATE}</TITLE></HEAD><BODY><H1>${RPT_DATE}</H1><pre>" > ${RPT_NAMEngfull} # Создаём отчёт # # Утилита flow-cat "выбрасывает" на стандартный вывод данные из логов # # утилита flow-filter выделяет из логов определённые данные. # С помощью ключа -f указывается файл со списками доступа # С помощью ключа -S указывается список, описывающий источник трафика # С помощью ключа -D указывается список, описывающий получателя трафика # (нашу локальную сеть) # # Утилита flow-report создаёт отчёт, используя один из предопределённых отчётов. # Файл со список отчётов задаётся с помощью ключа -s, # а конкретный отчёт - с помощью ключа -S # # Утилита flow-rptfmt форматирует отчёт, полученный с помощью flow-report. # Ключ -f задаёт формат, а ключ -H отключает вывод заголовка со служебной информацией flow-cat ${FLOW_DIRbr}/${RPT_Y}/${RPT_Y}-${RPT_M}/${RPT_Y}-${RPT_M}-${RPT_D} | \ /usr/local/bin/flow-filter -f /usr/local/scripts/stat-flow.acl -S internet -D localnet | \ /usr/local/bin/flow-report -s /usr/local/scripts/stat-localnet.conf -S localnet | \ /usr/local/bin/flow-rptfmt -f html -H >> ${RPT_NAMEbr} flow-cat ${FLOW_DIRbr}/${RPT_Y}/${RPT_Y}-${RPT_M}/${RPT_Y}-${RPT_M}-${RPT_D} | \ /usr/local/bin/flow-filter -f /usr/local/scripts/stat-flow.acl -D localnet -S internet | \ flow-print -f 3 >> ${RPT_NAMEbrfull} flow-cat ${FLOW_DIRng}/${RPT_Y}/${RPT_Y}-${RPT_M}/${RPT_Y}-${RPT_M}-${RPT_D} | \ /usr/local/bin/flow-filter -f /usr/local/scripts/stat-flow.acl -S internet -D localnet | \ /usr/local/bin/flow-report -s /usr/local/scripts/stat-internet.conf -S internet | \ /usr/local/bin/flow-rptfmt -f html -H >> ${RPT_NAMEng} flow-cat ${FLOW_DIRng}/${RPT_Y}/${RPT_Y}-${RPT_M}/${RPT_Y}-${RPT_M}-${RPT_D} | \ /usr/local/bin/flow-filter -f /usr/local/scripts/stat-flow.acl -D localnet -S internet | \ flow-print -f 3 >> ${RPT_NAMEngfull} # Закрываем HTML-тэги в отчёте echo -e "</BODY></HTML>" >> ${RPT_NAMEbr} echo -e "</pre></BODY></HTML>" >> ${RPT_NAMEbrfull} echo -e "</BODY></HTML>" >> ${RPT_NAMEng} echo -e "</pre></BODY></HTML>" >> ${RPT_NAMEngfull}
Не забываем дать права на исполнение файлу!
Теперь можно запихнуть все это в крон:
10 0 * * * root /usr/local/scripts/stat_daily.sh # Flow-reports