ng_ipacct — Netgraph IP accounting
Для работы этого примера необходимо иметь подгруженные модули:
- ng_ipacct.ko
- ng_ipfw.ko
- ng_ksocket.ko
Убедиться в их наличии можно командой:
/sbin/kldstat
Id Refs Address Size Name
1 11 0xc0400000 35e5f8 kernel
...
3 1 0xc4ceb000 3000 ng_ipacct.ko
4 1 0xc4cee000 4000 ng_ksocket.ko
5 1 0xc4d6d000 2000 ng_ipfw.ko
Если модули не загружены, то можно пересобрать ядро добавив следующее:
options NETGRAPH
options NETGRAPH_ETHER
options NETGRAPH_SOCKET
options NETGRAPH_TEE
options IPFIREWALL
options IPFIREWALL_DEFAULT_TO_ACCEPT
options IPFIREWALL_FORWARD
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=1000
либо загрузить это модулями:
/sbin/kldload /boot/kernel/ng_ipfw.ko
/sbin/kldload /boot/kernel/ng_ipacct.ko
/sbin/kldload /boot/kernel/ng_ksocket.ko
Устанавливаем порт /usr/ports/net-mgmt/ng_ipacct:
cd /usr/ports/net-mgmt/ng_ipacct
make install clean
В /etc/rc.conf добавляем:
ng_ipacct_enable="YES"
ng_ipacct_modules_load="YES"
Для примера будем собирать трафик для подсети 172.16.5.0/24 с интерфейса bge1
Итак сам скрипт на PERL, пусть он находится в папке /scripts и называется ipacctd_ng.pl
#! /usr/bin/perl
$rul=64000; #номер начального правила в файере
$iface="bge1"; #интерфейс
$threshold=100000; #максимальное количество записей
$verbose="1"; #расширенная статистика
$savetime="1"; #метка юникс тайма в файл статистики
$nodename=sprintf("ipacct_%s",$iface); #имя ноды
$hookprefix=$iface; #крючочки (хуки) в нетграф ;-)
if($ARGV[0] ne "start" and $ARGV[0] ne "show" and $ARGV[0] ne "stop" and $ARGV[0] ne "restart"){
error();
}else{
if($ARGV[0] eq "stop"){ #stop
stop_ng_ipacctd($nodename);
}elsif($ARGV[0] eq "show"){ #дампим трафик в файл
#проверяем загружен ли ipacctd
if(check_ipacctd($iface,$rul)==0){
stop_ng_ipacctd($nodename);
`/bin/sleep 3`;
start_ng_ipacctd($nodename,$hookprefix,$rul,$iface,$verbose,$threshold,$savetime);
}else{
$cmd=sprintf("/usr/local/sbin/ipacctctl %s:%s checkpoint",$nodename,$hookprefix);
`$cmd`;
$cmd=sprintf("/usr/local/sbin/ipacctctl %s:%s show",$nodename,$hookprefix);
`$cmd`;
$cmd=sprintf("/usr/local/sbin/ipacctctl %s:%s clear",$nodename,$hookprefix);
`$cmd`;
}
}elsif($ARGV[0] eq "start"){
start_ng_ipacctd($dbh,$nodename,$hookprefix,$rul,$iface,$verbose,$threshold,$savetime);
}elsif($ARGV[0] eq "restart"){
stop_ng_ipacctd($nodename);
`/bin/sleep 3`;
start_ng_ipacctd($dbh,$nodename,$hookprefix,$rul,$iface,$verbose,$threshold,$savetime);
}
}
###функция выводящая аргументы запуска==============================
sub error{
printf "\nUsage: (start|stop|restart|show)";
exit;
}
###функция start==================================================
sub start_ng_ipacctd{
$net="172.16.5.0/24";
#проверяем загруженность модулей
@modules=("ng_ipacct.ko","ng_ipfw.ko","ng_ksocket.ko");
foreach(@modules){
if(chk_mdl($_)==0){
`/sbin/kldload $_`;
}
}
#формирование ноды нетграфа
$cmd_ng=sprintf("/usr/sbin/ngctl -f- <<-SEQ
mkpeer ipacct ctl ctl
name .:ctl %s
mkpeer %s: ksocket %s_in inet/raw/divert
name %s:%s_in %s_in
msg %s_in: bind inet/0.0.0.0:3021
mkpeer %s: ksocket %s_out inet/raw/divert
name %s:%s_out %s_out
msg %s_out: bind inet/0.0.0.0:3022
rmhook .:ctl",$nodename,$nodename,$hookprefix,$nodename,$hookprefix,$nodename,$nodename,$nodename,$hookprefix,$nodename,$hookprefix,$nodename,$nodename);
`$cmd_ng`;
$cmd=sprintf("/usr/local/sbin/ipacctctl %s:%s dlt RAW",$nodename,$hookprefix);
`$cmd`;
$cmd=sprintf("/usr/local/sbin/ipacctctl %s:%s verbose %s",$nodename,$hookprefix,$verbose);
`$cmd`;
$cmd=sprintf("/usr/local/sbin/ipacctctl %s:%s threshold %s",$nodename,$hookprefix,$threshold);
`$cmd`;
$cmd=sprintf("/usr/local/sbin/ipacctctl %s:%s savetime %s",$nodename,$hookprefix,$savetime);
`$cmd`;
#формируем правила в фаирволе IPFW для перенаправления трафика в ноду нетграфа
$cmd=sprintf("/sbin/ipfw add %s divert 3021 ip from %s to any",$rul,$net);
`$cmd`;
$cmd=sprintf("/sbin/ipfw add %s divert 3022 ip from any to %s",$rul,$net);
`$cmd`;
print "ipacct has started..\n";
}
###функция stop==================================================
sub stop_ng_ipacctd{
`sh /etc/rc.firewall`;
$cmd=sprintf("/usr/sbin/ngctl shutdown %s:",$nodename);
`$cmd`;
print "ipacct has stoped..\n";
}
###функция проверки загрузки модулей================================
sub chk_mdl{
$chk=`/sbin/kldstat | /usr/bin/awk '/$_/ {print 1}'`;
if(!$chk){
return 0;
}else{
return 1;
}
}
###функция проверки ipacctd========================================
sub check_ipacctd{
$ch1=$ch2=$ch3=0;
$cmd=sprintf("/usr/sbin/ngctl list | grep %s_in",$iface); #проверяем входящий хук нетграфа
$check=`$cmd`;
if($check){
$ch1=1;
}
$cmd=sprintf("/usr/sbin/ngctl list | grep %s_out",$iface); #проверяем исходящий хук нетграфа
$check=`$cmd`;
if($check){
$ch2=1;
}
$cmd=sprintf("/sbin/ipfw show | grep divert"); #проверяем наличие правил в файерволе
$check=`$cmd`;
if($check){
$ch3=1;
}
$all_ch=$ch1+$ch2+$ch3;
if ($all_ch < 3){
return 0; #чего-то явно не хватает
}else{
return 1; #все ОК!
}
}
После старта мы можем посмотреть правила в фаирволе:
/sbin/ipfw show 64000
64000 1551459105 504714065010 divert 3021 ip from 172.16.5.0/24 to any
64000 2103320289 2367292643626 divert 3022 ip from any to 172.16.5.0/24
По команде:
/usr/sbin/ngctl list
можем посмотреть ноды и хуки нетграфа:
There are 7 total nodes:
Name: ngctl12701 Type: socket ID: 000c36ff Num hooks: 0
Name: ipacct_bge1_out Type: ksocket ID: 00097d52 Num hooks: 1
Name: ipacct_bge1_in Type: ksocket ID: 00097d51 Num hooks: 1
Name: ipacct_bge1 Type: ipacct ID: 00097d50 Num hooks: 2
Name: ipfw Type: ipfw ID: 0005f4a3 Num hooks: 0
Name: bge1 Type: ether ID: 00000002 Num hooks: 0
Name: bge0 Type: ether ID: 00000001 Num hooks: 0
Сделаем еще один маленький скриптик, который будет нам складывать статистику в файл.
Назовем его trafgen.pl
#!/usr/bin/perl
$tmp="/usr/local/var/trafd/tmp"; #папка для логов
opendir DIR,$tmp or mkdir $tmp;
closedir DIR;
$log=sprintf("%s/ipacctd.log",$tmp);
system("/scripts/ipacctd_ng.pl show >> $log"); #вызываем наш предыдущий скрипт с аргументом show
в /etc/crontab добавляем строчку:
*/5 * * * * root /scripts/trafgen.pl >/dev/null
Формат данны файла статистики при включенных опциях verbose=1 и savetime=1:
src_IP src_Port dst_IP dst_Port Proto packets bytes unixtime
Пример данных в фале:
172.16.5.211 57349 95.132.7.128 19904 6 1069 822400 1239961920
172.16.5.102 2208 217.118.24.17 7777 6 321 14958 1239961920
172.16.5.91 64835 92.100.50.249 59039 6 426 596900 1239961920
172.16.5.209 64829 77.41.95.94 43768 17 1 58 1239961923
172.16.5.76 1425 195.218.181.123 80 6 4 976 1239961924
172.16.5.188 61651 195.50.197.187 63375 6 1 48 1239961925
172.16.5.220 28988 94.179.59.61 20473 6 5 747 1239961929
....
80.252.240.202 11417 172.16.5.108 60682 17 1 47 1239961922
78.37.156.14 1451 172.16.5.220 28988 6 6 685 1239961922
97.84.143.186 17834 172.16.5.209 64829 17 2 134 1239961922
77.234.8.71 36523 172.16.5.220 28988 17 1 95 1239961924
195.189.47.2 2987 172.16.5.220 28988 17 1 131 1239961925
195.230.112.239 63403 172.16.5.220 28988 6 6 801 1239961930
60.220.156.222 27808 172.16.5.157 34613 17 4 504 1239961932
93.186.239.96 80 172.16.5.101 2720 6 3 358 1239961933
Обратите внимание, что сначала идет трафик исходящий и лишь затем входящий!!!
Все, дальше зависит только от полета Вашей фантазии (или извращенности 🙂 )
Вы можете обрабатывать файлы и складировать их в БД (напрмер MySQL) и т.п.
Плюсы от использования ng_ipacct:
- держит большие объемы трафика
- меньшая загрузка cpu по сравнению с обычным ipacct (/usr/ports/net-mgmt/ipacctd)
P.S. После пересборки ядра обязательно пересобрать порт /usr/ports/net-mgmt/ng_ipacct (если он был установлен до этого)
Чтиво:
- man 4 ipacct
- man 8 ipfw
- man 4 netgraph
- man 4 ng_ipfw
З.Ы. При копировании статьи ссылка на источник ОБЯЗАТЕЛЬНА !
Автор: Folio
Похожие статьи:
- Не найдено
Добавить комментарий
Вам следует авторизоваться для размещения комментария.