Hoi allemaal,
Ik ben de laatste twee avonden bezig geweest met een perl script waarmee je dataverkeer voor specifieke ip's en voor een network devices (eth0) in een grafiek kan zetten. Ik heb besloten dit script voor mezelf te maken omdat er heel weinig lichtgewicht scripts te vinden zijn om voor individuele ip's dataverkeer te loggen.
Het script genereert grafieken voor verschilende timespans,namelijk grafieken van de laatste:
- dag
- maand
- week
- jaar
Verder wordt er voor iedere maand een grafiek bewaard met daarin vermeld het totale bandreedte gebruik over de betreffende maand.
De code is overigens gemaakt op RH9 en getest op Fedora Core 2 en Debian.
Een vroegere versie van dit script al eerder hier gepost, maar omdat ik besloten heb mijn script verder uit te breiden en omdat mijn post beter in P&W past heb ik besloten hem maar hier te posten.
Dit script sheb ik gepost omdat ik graag wat opbouwende kritiek op de code zou krijgen, zodat ik het script kan verbeteren en eventueel uitbreiden. Het leek me verder ook een nuttig script voor eventuele mede-tweakers die naar een dergelijk script op zoek zijn
. Dit is overigens mijn eerste perl script dat meer dan 4 regels code bevat, omdat het enigszins op php lijkt heb ik gelukkig weinig problemen gehad
Er is wordt ook voor iedere individuele maand een apart grafiekje aangemaakt met het totaal aan dataverkeer van die maand. Handig als je een datalimiet hebt dus
Edit1: Bug #1 aangewezen door Oezie Woezie opgelost. - v0.1.3a
Edit2: Bugje gefixt met het verwerken van de iptables packet counter - v0.1.4a
Edit3: Bugje #3 gefixt met de jaarwisseling en 0based maand tellers - v0.1.5a
Edit4: Bugje met $span gefixt - v0.1.6a
Voorbeeld van maandelijkse graph:

Ik ben de laatste twee avonden bezig geweest met een perl script waarmee je dataverkeer voor specifieke ip's en voor een network devices (eth0) in een grafiek kan zetten. Ik heb besloten dit script voor mezelf te maken omdat er heel weinig lichtgewicht scripts te vinden zijn om voor individuele ip's dataverkeer te loggen.
Het script genereert grafieken voor verschilende timespans,namelijk grafieken van de laatste:
- dag
- maand
- week
- jaar
Verder wordt er voor iedere maand een grafiek bewaard met daarin vermeld het totale bandreedte gebruik over de betreffende maand.
De code is overigens gemaakt op RH9 en getest op Fedora Core 2 en Debian.
Een vroegere versie van dit script al eerder hier gepost, maar omdat ik besloten heb mijn script verder uit te breiden en omdat mijn post beter in P&W past heb ik besloten hem maar hier te posten.
Dit script sheb ik gepost omdat ik graag wat opbouwende kritiek op de code zou krijgen, zodat ik het script kan verbeteren en eventueel uitbreiden. Het leek me verder ook een nuttig script voor eventuele mede-tweakers die naar een dergelijk script op zoek zijn
Er is wordt ook voor iedere individuele maand een apart grafiekje aangemaakt met het totaal aan dataverkeer van die maand. Handig als je een datalimiet hebt dus
Edit1: Bug #1 aangewezen door Oezie Woezie opgelost. - v0.1.3a
Edit2: Bugje gefixt met het verwerken van de iptables packet counter - v0.1.4a
Edit3: Bugje #3 gefixt met de jaarwisseling en 0based maand tellers - v0.1.5a
Edit4: Bugje met $span gefixt - v0.1.6a
Voorbeeld van maandelijkse graph:

code:
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
| #!/usr/bin/perl -w
##########################################################################################
#
# IP specific and network device bandwidth grapher using rrdtool, iptables and ifconfig.
#
# v0.1.6a by Frozen - www.overdriveirc.net - irc.overdriveirc.net
#
##########################################################################################
#
# Todo
# - Add traffic logs graphs for individual ports.
# - Add html generator thingy for all the graphs.
#
##########################################################################################
# Usage
# ----------------------------------------------------------------------------------------
# ./bandmon.pl <switch> [parameter]
#
#
# Switches
# ----------------------------------------------------------------------------------------
# -i : Flush old iptables rules, create fresh ones.
# This command should be in /etc/rc.local and should be called at least
# once before using any other command if ipgraph is enabled.
#
# -c : Clears all iptable entries related to bandmon.
#
# -a <ip> : Add iptables rules for an ip and create the rrd if it doesnt exist.
# This command also adds the ip to ips.txt.
#
# -A <device> : Add traffic logging for a network device (eth0).
# This command also adds the ip to devices.txt.
#
# -G : Create the graphs for all ips in ips.txt.
#
# -U : Update rrd databases for all ips.
#
#
# Notes
# ----------------------------------------------------------------------------------------
# - "/full/path/to/bandmon.pl -U" Should be on a 5min cron.
# - This script needs an rrdtool "make site-perl-install" instead of just "make install".
# - With thanks to martybugs.net and Wupsje@GoT for their scripts that got me started =].
# - Day specific graphs
#
##########################################################################################
#
# Configuration
#
##########################################################################################
#The location of ips.txt and devices.txt
my $workPath = '/root/bandmon';
#The location of the rrd databases
my $rrd = '/root/bandmon/rra';
#The location where the graphs should be written
my $img = '/root/bandmon/img';
#The servername
my $servername = 'Fragma';
#Create graphs for network devices in devices.txt?
my $ethgraph = 1;
#Create graphs for ips in ips.txt?
my $ipgraph = 1;
#Update graphs after updating the rrd automatically?
my $autograph = 1;
##########################################################################################
#
# Code (Don't edit unless you know what you're doing).
#
##########################################################################################
use RRDs;
use Getopt::Std;
use Time::Local;
use POSIX qw(strftime);
my %options;
&getopts('a:A:cGiU',\%options);
if (! -e "$workPath/ips.txt") {
print "Required file ips.txt didnt exist. Created empty file: $workPath/ips.txt\n";
system "touch $workPath/ips.txt";
}
if (! -e "$workPath/devices.txt") {
print "Required file devices.txt didnt exist. Created empty file: $workPath/devices.txt\n";
system "touch $workPath/devices.txt";
}
if (! -d "$workPath") {
die "Fatal: Workpath \"$workPath\" doesn't exist. Edit this file with a text editor such as vi.\n";
}
if (! -d "$img") {
die "Fatal: Image directory \"$img\" doesn't exist. Edit this file with a text editor such as vi.\n";
}
if (! -d "$rrd") {
die "Fatal: RRD directory \"$rrd\" doesn't exist. Edit this file with a text editor such as vi.\n";
}
#Set the date variables
#($day,$month,$year) = (localtime(time))[3,4,5]; #Use this if you need $day
($month,$year) = (localtime(time))[4,5];
$year+=1900;
$month+=1;
if ($month < 10) {
$month_2digit = "0".$month;
}
else {
$month_2digit = $month;
}
if ($options{i}) {
&Init;
}
if ($options{a}) {
#Add the ip to ips.txt
print "Adding $options{a} to ips.txt...\n";
open (FILE,">>$workPath/ips.txt");
print FILE "$options{a}\n";
close FILE;
if ($ipgraph) {
#Add an iptables rule for this ip.
&AddIpRules($options{a});
}
else {
print "IP added to ips.txt but iptables rule is not added! Graphing for individual ip's is disabled.\n";
}
}
if ($options{A}) {
#Add the device to devices.txt
print "Adding $options{A} to devices.txt...\n";
open (FILE,">>$workPath/devices.txt\n");
print FILE "$options{A}\n";
close FILE;
}
if ($options{c}) {
&CleanIpTables;
}
if ($options{G}) {
&GraphAll;
}
if ($options{U}) {
&UpdateAllRrds($options{U});
}
sub Init {
&CleanIpTables;
#Only add iptables rules if we're in fact graphing for individual ip's.
if ($ipgraph) {
print "Adding iptables rules and checking if all the rrd's exist.\n";
#Create fresh BMONI and BMONO chains.
system "/sbin/iptables -N BMONI";
system "/sbin/iptables -N BMONO";
#Add rules to the BMON chains to return the package to the originating chain
system "/sbin/iptables -A BMONI -j RETURN";
system "/sbin/iptables -A BMONO -j RETURN";
#Forward all packets to the BMON chains.
system "/sbin/iptables -I INPUT 1 -j BMONI";
system "/sbin/iptables -I OUTPUT 1 -j BMONO";
#Short explanation of what'll happen:
#Packets go from INPUT or OUTPUT, to BMONI or BMONO and then get returned back to INPUT or OUTPUT.
#But WHY? The packets will be counted in the BMON chains for the specified ip's.
#Add iptable rules for the ips in ips.txt.
open (FILE,"$workPath/ips.txt");
@file = <FILE>;
close FILE;
foreach (@file) {
(@ip) = split(" ",$_);
chomp($ip[0]);
if (length($ip[0]) >0) { &AddIpRules($ip[0]); }
}
}
else {
print "Skipping iptable rules since we're not logging for individual ip's.\n";
}
}
sub CleanIpTables {
print "Cleaning old iptable entries. (may show some errors/warnings)\n";
#Delete possibly previously set jump lines to BMONI and BMONO.
if (`iptables -L INPUT -n | head -n 3 | tail -n 1` =~ /BMON/) { system "/sbin/iptables -D INPUT 1"; }
if (`iptables -L OUTPUT -n | head -n 3 | tail -n 1` =~ /BMON/) { system "/sbin/iptables -D OUTPUT 1"; }
#Flush and delete the BMONI and BMONO chains if they exist.
if (`iptables -L BMONI -n | head -n 1` =~ /Chain/) { #This still shows an error to stdout if the chain doesnt exist :\
system "/sbin/iptables -F BMONI"; #But I guess 1 is better than 4
system "/sbin/iptables -F BMONO";
system "/sbin/iptables -X BMONI";
system "/sbin/iptables -X BMONO";
}
}
sub AddIpRules {
#Add the rules in the BMON chains which will count the data for the specified ip.
print "Adding iptable rules for $_[0]\n";
system "/sbin/iptables -I BMONI 1 -d $_[0] -j RETURN"; # Packets heading to the specified ip.
system "/sbin/iptables -I BMONO 1 -s $_[0] -j RETURN"; # Packets originating from the specified ip.
}
sub UpdateRrdForIp {
#Get the amount of transmitted bytes only 1 ip chomp remove double " " get the 2nd word
my $in = `/sbin/iptables -L BMONI -nvx | /bin/grep $_[0] | sed 's/^[ \t]*//' | /bin/sed "s/ */ /g" | /bin/cut -d " " -f2`;
my $out = `/sbin/iptables -L BMONO -nvx | /bin/grep $_[0] | sed 's/^[ \t]*//' | /bin/sed "s/ */ /g" | /bin/cut -d " " -f2`;
#Remove whitespace
chomp($in);
chomp($out);
#Update the rrd database
&UpdateRrd($_[0],$in,$out);
}
sub UpdateRrdForDev {
#Get network interface info
my $in = `/sbin/ifconfig $_[0] |/bin/grep bytes|/bin/cut -d":" -f2|/bin/cut -d" " -f1`;
my $out = `/sbin/ifconfig $_[0] |/bin/grep bytes|/bin/cut -d":" -f3|/bin/cut -d" " -f1`;
#Remove eol chars
chomp($in);
chomp($out);
#Update the rrd database
&UpdateRrd($_[0],$in,$out);
}
sub UpdateRrd {
print "Updating rrd for $_[0] with in: $_[1] out: $_[2] \n";
#Create the rrd database if it doesn't exist
if (! -e "$rrd/$_[0].rrd") {
print "Creating rrd database for $_[0]\n";
RRDs::create "$rrd/$_[0].rrd",
"-s 300",
"DS:in:DERIVE:600:0:12500000",
"DS:out:DERIVE:600:0:12500000",
"RRA:AVERAGE:0.5:1:576",
"RRA:AVERAGE:0.5:6:672",
"RRA:AVERAGE:0.5:24:732",
"RRA:AVERAGE:0.5:144:1460";
if ($ERROR = RRDs::error) { print "RRD ERROR: $ERROR\n"; }
}
#Update the rrd file
RRDs::update "$rrd/".$_[0].".rrd",
"-t", "in:out",
"N:$_[1]:$_[2]";
if ($ERROR = RRDs::error) { die "FATAL RRD ERROR: $ERROR\n"; }
}
sub UpdateAllRrds {
if ($ipgraph) {
open (FILE,"$workPath/ips.txt");
@file = <FILE>;
close FILE;
foreach (@file) {
(@ip) = split(" ",$_);
chomp($ip[0]);
if (length($ip[0]) >0) { &UpdateRrdForIp($ip[0]); }
}
}
if ($ethgraph) {
open (FILE,"$workPath/devices.txt");
@file = <FILE>;
close FILE;
foreach (@file) {
(@dev) = split(" ",$_);
chomp($dev[0]);
if (length($dev[0]) >0) { &UpdateRrdForDev($dev[0]); }
}
}
#Create the graph if autographing is enabled.
if ($autograph) { &GraphAll; }
}
sub DoGraphs {
if (-e "$rrd/$_[0].rrd") {
print "Creating graphs for $_[0]\n";
#Create empty graph with monthly totals $month-1: 0 based month counter
my $monthstart = strftime("%s",localtime(timelocal(0,0,1,1,$month-1,$year)));
if ($month==12) {
$monthend = strftime("%s",localtime((timelocal(0,0,1,1,0,$year+1)-1)));
}
else { $monthend = strftime("%s",localtime((timelocal(0,0,1,1,$month,$year)-1))); }
my $span = ($monthend - $monthstart); #Seconds of the month
my $monthtxt = lc(`/bin/date +%B`);
chomp($monthtxt);
#Create the month-only graph
RRDs::graph "$img/$_[0]"."_month_".$year."-".$month_2digit.".png",
"-s $monthstart",
"-e $monthend",
"-t ".ucfirst($monthtxt)." only graph, for $servername :: $_[0]",
"--lazy",
"-h", "160", "-w", "600",
"-l 0",
"-a", "PNG",
"-v bytes/sec",
"DEF:in=$rrd/$_[0].rrd:in:AVERAGE",
"DEF:out=$rrd/$_[0].rrd:out:AVERAGE",
"CDEF:out_neg=out,-1,*",
"CDEF:totalin=in,UN,0,in,$span,*,IF",
"CDEF:totalout=out,UN,0,out,$span,*,IF",
"AREA:in#32CD32:Incoming",
"LINE1:in#336600",
"GPRINT:in:MAX: Max\\: %5.1lf %s",
"GPRINT:in:AVERAGE: Avg\\: %5.1lf %S",
"GPRINT:in:LAST: Current\\: %5.1lf %Sbytes/sec",
"GPRINT:totalin:AVERAGE:".ucfirst($monthtxt)." total\\: %.2lf %s\\n",
"AREA:out_neg#4169E1:Outgoing",
"LINE1:out_neg#0033CC",
"GPRINT:out:MAX: Max\\: %5.1lf %s",
"GPRINT:out:AVERAGE: Avg\\: %5.1lf %S",
"GPRINT:out:LAST: Current\\: %5.1lf %Sbytes/sec",
"GPRINT:totalout:AVERAGE:".ucfirst($monthtxt)." total\\: %.2lf %s";
if ($ERROR = RRDs::error) { die "FATAL RRD ERROR: $ERROR\n"; }
&CreateGraph($_[0],"day");
&CreateGraph($_[0],"week");
&CreateGraph($_[0],"month");
&CreateGraph($_[0],"year");
}
else {
print "Error: rrd database for $_[0] doesn't exist.\n";
}
}
sub GraphAll {
if ($ipgraph) {
open (FILE,"$workPath/ips.txt");
@file = <FILE>;
close FILE;
foreach (@file) {
(@ip) = split(" ",$_);
chomp($ip[0]);
if (length($ip[0]) >0) { &DoGraphs($ip[0]); }
}
}
if ($ethgraph) {
open (FILE,"$workPath/devices.txt");
@file = <FILE>;
close FILE;
foreach (@file) {
(@dev) = split(" ",$_);
chomp($dev[0]);
if (length($dev[0]) >0) { &DoGraphs($dev[0]); }
}
}
}
sub CreateGraph {
RRDs::graph "$img/$_[0]_last_$_[1].png",
"-s -1$_[1]",
"-t traffic on $servername :: $_[0]",
"--lazy",
"-h", "160", "-w", "600",
"-l 0",
"-a", "PNG",
"-v bytes/sec",
"DEF:in=$rrd/$_[0].rrd:in:AVERAGE",
"DEF:out=$rrd/$_[0].rrd:out:AVERAGE",
"CDEF:out_neg=out,-1,*",
"AREA:in#32CD32:Incoming",
"LINE1:in#336600",
"GPRINT:in:MAX: Max\\: %5.1lf %s",
"GPRINT:in:AVERAGE: Avg\\: %5.1lf %S",
"GPRINT:in:LAST: Current\\: %5.1lf %Sbytes/sec\\n",
"AREA:out_neg#4169E1:Outgoing",
"LINE1:out_neg#0033CC",
"GPRINT:out:MAX: Max\\: %5.1lf %s",
"GPRINT:out:AVERAGE: Avg\\: %5.1lf %S",
"GPRINT:out:LAST: Current\\: %5.1lf %Sbytes/sec",
"HRULE:0#000000";
if ($ERROR = RRDs::error) { die "RRD ERROR: Unable to generate graph for $_[0]: $ERROR\n"; }
} |
[ Voor 210% gewijzigd door JasperE op 25-09-2005 17:12 ]