Go to content Go to menu Go to search

Скрипт сбора статистики bind9

Задача

В Bind9 имеется возможность записывать в лог-файл все поступившие запросы. Грех не использовать эту возможность для сбора статистики. Ниже приведенный скрипт обрабатывает query-лог bind-9 и генерирует вот такую текстовую страницу:

Requests by hour:
Hour    | TOTAL | A     | MX    | PTR   | TXT   | CNAME | NS    | AAAA  | SRV   | ANY   | SOA   | A6    | AXFR  | IXFR  | 
00      | 98k   | 55k   | 12k   | 12k   | 4561  | 168   | 2331  | 9007  | 47    | 159   | 520   |       |       |       | 
01      | 89k   | 48k   | 8847  | 11k   | 5778  | 129   | 1913  | 10k   | 31    | 140   | 787   |       |       |       | 
02      | 95k   | 53k   | 9261  | 10k   | 5640  | 145   | 2540  | 9968  | 47    | 661   | 636   |       |       |       | 
03      | 104k  | 53k   | 12k   | 10k   | 9306  | 180   | 3225  | 10k   | 51    | 678   | 367   |       | 1     |       | 
04      | 142k  | 80k   | 13k   | 11k   | 11k   | 237   | 4964  | 12k   | 33    | 885   | 278   |       |       |       | 
05      | 115k  | 65k   | 11k   | 8963  | 10k   | 102   | 3929  | 8734  | 26    | 718   | 236   |       |       |       | 
06      | 119k  | 61k   | 11k   | 9883  | 12k   | 132   | 3678  | 9162  | 24    | 573   | 160   |       |       |       | 
07      | 99k   | 54k   | 12k   | 9650  | 6360  | 98    | 3829  | 10k   | 27    | 441   | 125   |       |       |       | 
08      | 103k  | 59k   | 11k   | 9435  | 6272  | 79    | 3469  | 9979  | 33    | 328   | 136   |       |       |       | 
09      | 102k  | 56k   | 12k   | 10k   | 5019  | 99    | 2562  | 10k   | 40    | 1400  | 116   |       |       |       | 
10      | 98k   | 53k   | 12k   | 9607  | 5897  | 103   | 2573  | 9728  | 44    | 2055  | 114   |       |       |       | 
11      | 96k   | 51k   | 12k   | 9980  | 5513  | 88    | 2573  | 9918  | 53    | 1418  | 108   |       |       |       | 
12      | 84k   | 45k   | 10k   | 9120  | 4422  | 81    | 2065  | 9660  | 55    | 1091  | 118   |       |       |       | 
13      | 96k   | 51k   | 11k   | 9359  | 7155  | 104   | 3488  | 9657  | 39    | 802   | 112   |       |       |       | 
14      | 95k   | 52k   | 10k   | 9028  | 6873  | 89    | 3504  | 9892  | 35    | 395   | 104   |       |       |       | 
15      | 85k   | 46k   | 10k   | 9324  | 4478  | 82    | 2282  | 10k   | 44    | 228   | 110   |       |       |       | 
16      | 79k   | 44k   | 8341  | 8073  | 4951  | 92    | 2509  | 9781  | 41    | 190   | 108   |       |       |       | 
17      | 79k   | 43k   | 9237  | 8368  | 3640  | 119   | 1862  | 10k   | 43    | 208   | 415   |       |       |       | 
18      | 91k   | 53k   | 9278  | 8954  | 5105  | 76    | 2161  | 10k   | 55    | 190   | 429   |       | 1     |       | 
19      | 87k   | 48k   | 8287  | 9280  | 5004  | 128   | 2084  | 10k   | 54    | 157   | 500   |       |       |       | 
20      | 89k   | 51k   | 8417  | 10k   | 3812  | 114   | 2109  | 10k   | 41    | 159   | 455   |       |       |       | 
21      | 85k   | 47k   | 8442  | 10k   | 3331  | 163   | 2061  | 10k   | 48    | 182   | 558   |       |       |       | 
22      | 108k  | 60k   | 13k   | 14k   | 4851  | 134   | 2300  | 9905  | 52    | 210   | 683   |       |       |       | 
23      | 145k  | 80k   | 24k   | 18k   | 6353  | 140   | 2726  | 10k   | 51    | 175   | 598   |       | 1     |       |

TOP 20 Clients:
Client IP       | TOTAL | A     | MX    | PTR   | TXT   | CNAME | NS    | AAAA  | SRV   | ANY   | SOA   | A6    | AXFR  | IXFR  | 
192.168.1.87    | 799k  | 548k  | 25k   | 30k   | 111k  |       | 46k   | 5     |       |       |       |       |       |       | 
192.168.1.91    | 172k  | 39k   | 2     | 61k   |       |       |       | 71k   |       |       |       |       |       |       | 
192.168.1.83    | 139k  | 80k   | 37k   | 21k   |       |       |       |       |       |       |       |       |       |       | 
192.168.77.15   | 104k  | 62k   | 5     | 31k   | 1350  |       |       | 9169  | 20    |       | 4     |       |       |       | 
192.168.77.70   | 70k   | 4     |       | 70k   |       |       |       |       |       |       |       |       |       |       | 
192.168.1.85    | 58k   | 43k   | 12k   | 2918  |       |       |       |       |       |       |       |       |       |       | 
192.168.1.82    | 43k   | 11k   | 31k   | 105   |       |       |       |       |       |       |       |       |       |       | 
192.168.1.32    | 38k   | 4561  | 1694  | 2     | 14k   |       |       |       |       |       |       |       |       |       | 
192.168.1.84    | 30k   | 15k   | 2     | 15k   |       |       |       |       |       |       |       |       |       |       | 
192.168.77.13   | 26k   | 23k   | 1     | 1455  | 14    |       |       | 1875  | 13    |       | 3     |       |       |       | 
74.116.90.15    | 19k   | 4     | 19k   |       |       |       |       |       |       |       |       |       |       |       | 
172.17.0.5      | 11k   |       |       | 11k   |       |       |       |       |       |       |       |       |       |       | 
64.202.161.41   | 9369  | 4476  | 4713  |       | 166   |       | 14    |       |       |       |       |       |       |       | 
199.59.148.218  | 6589  | 2229  | 4296  |       |       |       |       | 64    |       |       |       |       |       |       | 
69.252.96.24    | 6068  | 3462  | 2     |       | 2     |       | 15    | 2523  | 63    |       |       |       |       |       | 
69.252.96.22    | 5907  | 3348  | 1     |       | 1     |       | 16    | 2464  | 77    |       |       |       |       |       | 
40.139.112.2    | 5870  | 5606  | 1     |       | 9     | 9     |       | 231   |       |       | 14    |       |       |       | 
130.207.54.131  | 5531  | 5478  |       |       |       |       |       | 53    |       |       |       |       |       |       | 
130.207.54.130  | 5403  | 5317  |       |       |       |       |       | 86    |       |       |       |       |       |       | 
67.225.185.56   | 5353  | 2323  | 712   |       |       |       |       |       |       | 1946  | 372   |       |       |       |

TOP 20 Domains:
Domain                  | TOTAL | A     | MX    | PTR   | TXT   | CNAME | NS    | AAAA  | SRV   | ANY   | SOA   | A6    | AXFR  | IXFR  | 
spamhaus.org            | 267k  | 256k  |       |       | 11k   |       |       |       |       |       |       |       |       |       | 
propertyminder.com      | 262k  | 133k  | 6568  |       | 6835  | 294   | 3395  | 107k  | 87    | 317   | 14    |       |       |       | 
in-addr.arpa            | 249k  | 9     |       | 249k  |       |       |       |       |       |       |       |       |       |       | 
google.com              | 68k   | 64k   | 64    |       | 890   |       | 29    | 1647  |       |       |       |       |       |       | 
spamcop.net             | 44k   | 22k   |       |       | 21k   |       |       |       |       |       |       |       |       |       | 
mailspike.net           | 32k   | 32k   |       |       |       |       |       |       |       |       |       |       |       |       | 
propertyminder.colo     | 28k   | 26k   | 4     |       |       |       |       | 1808  |       |       |       |       |       |       | 
surbl.org               | 26k   | 26k   |       |       |       |       |       |       |       |       |       |       |       |       | 
isvr.net                | 22k   | 9765  | 5     |       | 5     |       | 351   | 12k   |       | 6     | 1     |       |       |       | 
juliakeady.com          | 21k   | 7916  | 13k   |       |       |       | 500   | 45    |       | 1     | 9     |       |       |       | 
gmail.com               | 19k   | 177   | 17k   |       | 865   |       |       | 5     |       |       |       |       |       |       | 
7jet.biz                | 18k   | 18k   |       |       |       |       |       |       |       |       |       |       |       |       | 
yahoodns.net            | 17k   | 17k   |       |       |       |       | 3     | 8     |       |       |       |       |       |       | 
habeas.com              | 16k   |       |       |       | 16k   |       |       |       |       |       |       |       |       |       | 
bondedsender.org        | 16k   |       |       |       | 16k   |       |       |       |       |       |       |       |       |       | 
uribl.com               | 16k   | 16k   |       |       |       |       |       |       |       |       |       |       |       |       | 
support-intelligence.net        | 15k   | 15k   |       |       |       |       |       |       |       |       |       |       |       |       | 
barracudacentral.org    | 15k   | 15k   |       |       |       |       |       |       |       |       |       |       |       |       | 
geoplugin.net           | 13k   | 6867  |       |       |       |       |       | 6867  |       |       |       |       |       |       | 
manitu.net              | 13k   | 13k   |       |       |       |       |       |       |       |       |       |       |       |       |

TOP 20 Requests:
TYPE    | TOTAL | Request       
PTR     | 70k   | 70.10.10.10.in-addr.arpa      
A       | 31k   | ns2.propertyminder.com        
A       | 31k   | ns1.propertyminder.com        
A       | 22k   | isvr.net      
AAAA    | 22k   | mx.propertyminder.com 
MX      | 21k   | juliakeady.com        
A       | 18k   | myhost5.7jet.biz      
PTR     | 18k   | 2.1.168.192.in-addr.arpa      
MX      | 18k   | gmail.com     
PTR     | 17k   | 32.1.168.192.in-addr.arpa     
A       | 17k   | mobile-api8.propertyminder.com        
A       | 17k   | propertyminder.com    
A       | 16k   | amq1.propertyminder.com       
AAAA    | 15k   | static.propertyminder.com     
AAAA    | 13k   | www.geoplugin.net     
ANY     | 11k   | prudentialnorthland.com       
MX      | 11k   | samanthaannuzzi.com   
MX      | 10k   | yahoo.com     
A       | 10k   | natellena.com 
AAAA    | 10k   | mail.propertyminder.com

Подготовка

Необходимо настроить bind, что бы он писал query-log в файл. Примерно следующим образом (в /enc/named.conf):

logging {
   channel query_log {
       file "/var/log/bind/query.log";
       severity dynamic;
       print-time yes;
   };
   category queries { query_log; };
}

Скрипт сохраним в /root/bin/make-bind-stat.pl
Скрипт имеет смысл запускать из logrotate скрипта.
Пример конфига для logrotate (скрипт создает файл со статистикой в каталоге /var/www/html/bind-stat/, а так же отправляет его по почте):

/var/log/bind/*log {
    missingok
    notifempty
    compress
    rotate 7
    daily
    sharedscripts
    prerotate
    DATE=`date +%Y-%m-%d`; /root/bin/make-bind-stat.pl > /var/www/html/bind-stat/$DATE.txt; cat /var/www/html/bind-stat/$DATE.txt | /usr/bin/uuencode $DATE.txt | /bin/mailx -s "named stats from NS1.minder.com" admins@minder.com
    endscript
    postrotate
        /sbin/service named reload  2> /dev/null > /dev/null || true
    endscript
}

Скрипт make-bind-stat.pl

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#! /usr/bin/perl
use strict;

#
# This script parses bind9 query log, and print stats in text format on stdout
#
# To use set $BIND_QUERY_LOG variable and run from logrotate or cron like this: 
# make-bind-stat_v02.pl > /var/www/html/bind-stat-`date +%Y-%m-%d`-.txt
#
# You should configure bind to log queries before use.
# set logging channel like in example:
# 
# logging {
#    channel query_log {
#        file "/var/log/bind/query.log";
#        severity dynamic;
#        print-time yes;
#    };
#    category queries { query_log; };
# }
#
# version 0.1, copyright: Valynkin Pavel, 2015
#

# <==== config ====>
my $BIND_QUERY_LOG="/var/log/bind/query.log";
my $TOP = 20; # how many lines in tables
my @QUERY_TYPES=("A","MX","PTR","TXT","CNAME","NS","AAAA","SRV","ANY","SOA","A6","AXFR","IXFR"); # query types to output in tables
# <==== end of config ====>

my %totals_by_hour;         my %totals_by_hour_details;
my %host_total_requests;    my %host_details;
my %domain_total_requests;  my %domain_details;
my %query_total_requests;   my %query_type;

open (IN, "<$BIND_QUERY_LOG");

#
# parse log and count conters
#
while ( <IN> ) {
    chomp;
    my $line=$_;

    # Extract data from line
    $line =~ /^[0-9]+-[A-z]+-[0-9]+ ([0-9][0-9])+:[0-9][0-9]:[0-9][0-9]\..+client ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)#[0-9]+: query: (.+) IN ([A-Z]+) .+/;
    next if ( !$4 ); # next if parsing failed
    my $hour = $1;
    my $client_ip = $2;
    my $query = $3;
    my $query_type = $4;
    $query =~ /(?:[^\.]+\.)*?([^\.]+\.[^\.]+)$/;
    my $domain = $1;

    # count counters
    $totals_by_hour{$hour}++;
    $totals_by_hour_details{$hour."-".$query_type}++;
    $host_total_requests{$client_ip}++;
    $host_details{$client_ip."-".$query_type}++;
    $domain_total_requests{$domain}++;
    $domain_details{$domain."-".$query_type}++;
    $query_total_requests{$query}++;
    $query_type{$query} = $query_type;
}
close IN;

my ($sorted_keys,$sorted_values);
#
# output queries by hour table
#
print "Requests by hour:\n";
print "Hour\t| TOTAL\t| ";
foreach (@QUERY_TYPES) { print $_,"\t| "; }
print "\n";
foreach my $hour(sort keys %totals_by_hour){
    print $hour,"\t| ";
    print &format_value($totals_by_hour{$hour}),"\t| ";
    foreach (@QUERY_TYPES) { print &format_value($totals_by_hour_details{$hour."-".$_}),"\t| "; }
    print "\n";
}

#
# output TOP Clients table
#
($sorted_keys,$sorted_values) = &sort_hash_by_values(\%host_total_requests);
#print head 
print "\nTOP $TOP Clients:\n";
print "Client IP\t| TOTAL\t| ";
foreach (@QUERY_TYPES) { print $_,"\t| "; }
print "\n";
# print data
for (my $i=0; $i < $TOP; $i++) {
    print $sorted_keys->[$i],"\t| ";
    print &format_value($sorted_values->[$i]),"\t| ";
    foreach (@QUERY_TYPES) { print &format_value($host_details{$sorted_keys->[$i]."-".$_}),"\t| "; }
    print "\n";
}

#
# output TOP domains table
#
($sorted_keys,$sorted_values) = &sort_hash_by_values(\%domain_total_requests);
#print head 
print "\nTOP $TOP Domains:\n";
print "Domain\t\t\t| TOTAL\t| ";
foreach (@QUERY_TYPES) { print $_,"\t| "; }
print "\n";
# print data
for (my $i=0; $i < $TOP; $i++) {
    print $sorted_keys->[$i],"\t";
    print "\t" if ( length($sorted_keys->[$i]) < 16 );
    print "| ";
    print &format_value($sorted_values->[$i]),"\t| ";
    foreach (@QUERY_TYPES) { print &format_value($domain_details{$sorted_keys->[$i]."-".$_}),"\t| "; }
    print "\n";
}

#
# output TOP requests table
#
($sorted_keys,$sorted_values) = &sort_hash_by_values(\%query_total_requests);
#print head 
print "\nTOP $TOP Requests:\n";
print "TYPE\t| TOTAL\t| Request\t";
print "\n";
# print data
for (my $i=0; $i < $TOP; $i++) {
    print $query_type{$sorted_keys->[$i]},"\t| ";
    print &format_value($sorted_values->[$i]),"\t| ";
    print $sorted_keys->[$i],"\t";
    print "\n";
}

#
# Subroutines
#
sub sort_hash_by_values {
    my ($hash) = @_;
    my $i=0;
    my @keys; my @values;
    foreach my $key(sort {$hash->{$b} <=> $hash->{$a}} keys %$hash) {
        #print $key,'=',$hash->{$key},"\n";
        $keys[$i]=$key;
        $values[$i]=$hash->{$key};
        $i++; last if ($i == $TOP);
    }
    return \@keys, \@values;
}

sub sort_hash_by_key {
    my ($hash) = @_;
    my $i=0;
    my @keys; my @values;
    foreach my $key(sort keys %{$hash}){
        #print "$key => ",$hash->{$key},"\n"; #отсортирует в алфавитном порядке по значениям ключа
        $keys[$i]=$key;
        $values[$i]=$hash->{$key};
        $i++; last if ($i == $TOP);
    }
    #print %sorted_hash;
    return \@keys, \@values;
}

sub format_value {
    my $value = @_[0];
    $value = int($value/1000)."k" if ( $value >= 10000 && $value < 1000000 );
    $value = int($value/1000000)."m" if ( $value > 100000 );
    return $value;
}

Enjoy!


при публикации материалов с данного сайта обратная ссылка на сайт обязательна.
valynkin.ru © no rights reserved