Настройка сбора и обработки NetFlow-потоков

Долго собирался доделать — и все-таки у меня получилось)
Если интересно — прошу под кат:

Что имеем:

[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.subr
name=softflowd
 rcvar=softflowd_enable
start_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"
 fi
load_rc_config $name
softflowd_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

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.