Surveiller un serveur avec iptraf et rrdtools

Nota Bene : pour toute remarque ou question, merci d’utiliser le fil de discussion prévu à cet effet.

Ce T&A est très simple, j’avais juste envie de partager un petit outil de surveillance pratique et facile à mettre en place.

Vos idées pour l’amélioration de ce “tableau de bord” sont les bienvenues

Une des tâche les plus importantes d’un administrateur, c’est de surveiller l’activité réseau…
Deux outils simples et personnalisables à l’infini, permettent de visualiser simplement votre activité réseau : iptraf et rrdttols !

Prérequis : Avoir un serveur Http opérationnel.

Installation :

# apt-get install iptraf rrdtool

Configuration de iptraf :

# iptraf

Veillez à ajouter les ports que vous souhaitez surveillers
Veillez à vérifier que la résolution de nom est désactivée (un peu lourd et inutile dans notre cas)
Veillez à régler l’intervalle du “logging”; J’ai opté pour 5 minutes.

Lancement d’iptraf en tâche de fond

iptraf -s eth0 -B

Lancement automatique de iptraf (en tâche de fond) au démarrage de la machine (à placer dans /etc/init.d/ + # update-rc.d iptraf defaults)

[code]#!/bin/sh

Demarrage de Iptraf

case “$1” in
‘start’)
iptraf -s eth0 -B
;;
‘stop’)
;;
*)
echo “Usage: $0 { start | stop }”
;;
esac
exit 0[/code]
Le script sera nommé “iptraf” et sera rendu exécutable avec la commande : # chmod +x /etc/init.d/iptraf

Configuer rrd (round-robin database):

[code]# mkdir /var/lib/rrd

cd /var/lib/rrd

rrdtool create tcp_services.rrd DS:9922_in:COUNTER:600:U:12500000 DS:9922_out:COUNTER:600:U:12500000 DS:25_in:COUNTER:600:U:12500000 DS:25_out:COUNTER:600:U:12500000 DS:995_in:COUNTER:600:U:12500000 DS:995_out:COUNTER:600:U:12500000 DS:80_in:COUNTER:600:U:12500000 DS:80_out:COUNTER:600:U:12500000 DS:119_in:COUNTER:600:U:12500000 DS:119_out:COUNTER:600:U:12500000 DS:443_in:COUNTER:600:U:12500000 DS:443_out:COUNTER:600:U:12500000 RRA:AVERAGE:0.5:1:600 RRA:AVERAGE:0.5:6:700 RRA:AVERAGE:0.5:24:775 RRA:AVERAGE:0.5:288:797 RRA:MAX:0.5:1:600 RRA:MAX:0.5:6:700 RRA:MAX:0.5:24:775 RRA:MAX:0.5:288:797

lol:/var/lib/rrd# ls
tcp_services.rrd
lol:/var/lib/rrd#[/code]

C’est un peu la commande “de la mort qui tue”…
Cette base enregistrera toutes les entrées et sorties de 6 ports tcp: 9922 :mrgreen: (ssh) 25 (smtp) 995 (pop3s) 80 (http) 119 (nntp) et 443 (https).

Précision de Syam : viewtopic.php?p=274918#p274918 :
Alloue une taille fixe de donnée, et utilise cet espace de stockage à la manière d’un buffer circulaire : quand il arrive « à la fin » du fichier, il continue en écrasant progressivement ce qui se trouve au début.

La taille de la base fait dans les 500 kilos, et ne changera pas !

Je ne rentre pas trop dans les détails, vous trouverez toute la documentation nécessaire pour créer la base qui vous convient, et le détail des options possibles, innombrables…

Il nous faut maintenant un script pour collecter les données et remplir la rrd.

[code]#!/usr/bin/perl -l

update the round robin database

use strict;
use warnings;

use IO::File;
use Time::Local;

my @PORTS = qw ( 10122 25 995 80 119 443 );
my $LAST = rrdtool last /var/lib/rrd/tcp_services.rrd;
chomp $LAST;

my $fh = IO::File->new(’/var/log/iptraf/tcp_udp_services-eth0.log’)
or die “Can’t open logfile”;

while (<$fh>) {
if ( m/service monitor started/ ) { reset( $ ); }
next unless ( m/^***/ );
my $hash = parse( $, $fh );
_update( $hash ) if ( $hash );
}

translate iptraf’s time string into unixtime

sub get_time {
my ($input) = @
;

my ($day, $month, $date, $hour, $minute, $second, $year) = 
        split( /\s+|:/, $input );

$month = $month eq 'Jan' ? 0  :
         $month eq 'Feb' ? 1  :
         $month eq 'Mar' ? 2  :
         $month eq 'Apr' ? 3  :
         $month eq 'May' ? 4  :
         $month eq 'Jun' ? 5  :
         $month eq 'Jul' ? 6  :
         $month eq 'Aug' ? 7  :
         $month eq 'Sep' ? 8  :
         $month eq 'Oct' ? 9  :
         $month eq 'Nov' ? 10 :
         $month eq 'Dec' ? 11 : undef;

die "Bad date $input" unless defined ( $month );

return timelocal( $second, $minute, $hour, $date, $month, $year );

}

parse the log to the end. small race condition if we start reading

log file while iptraf is writing?

sub parse {
my ($header, $fh) = @
;

my %hash;
$hash{_time} = _get_time( ($header =~ m/generated (.*)/)[0] );

return unless $hash{_time} > $LAST + 60;

while (<$fh>) {
    last if ( m/^Running/ );
    next if ( m/^\s*$/ );

    ## read data for tcp packets
    my ($proto) = $_ =~ m/^([^\/]+)/;
    next unless $proto eq 'TCP';
    my ($port, $packs, $bytes, $pack_in, $byte_in, $pack_out, $byte_out) =
        $_ =~ m/(\d+)/g;

    $hash{$port} = [$byte_in, $byte_out];
}

return \%hash;

}

iptraf has restarted, put ‘U’ (unknown) in db.

sub reset {
my ($line) = @
;

my %hash;
$hash{_time} = _get_time( (split( /;/, $line))[0] );
_update( \%hash );

}

send update to the db

sub update {
my ($hash) = @
;

return unless $hash->{_time} > $LAST + 60;

system( "/usr/bin/rrdtool", 
            "update",
            "/var/lib/rrd/tcp_services.rrd",
            join(":", $hash->{_time},
                    map { ref($hash->{$_}) ? @{$hash->{$_}} : qw( U U ) }
                        @PORTS ) );

}[/code]

Fichier que j’ai placé dans le dossier /var/lib/rrd/rrd.d
Et qui doit être lancé régulièrement par crontab (toutes les 5 minutes fera l’affaire)

0,5,10,15,20,25,30,35,40,45,50,55 * * * * /var/lib/rrd/rrd.d/iptraf.sh

Crétaion d’un fichier rcgi qui affichera les graphiques dans le navigateur :

lol:/var/lib/rrd# cd /var/www
lol:/var/www# mkdir rrd-iptraf/
lol:/var/www# cd rrd-iptraf/
lol:/var/www/rrd-iptraf# nano tcp_services.rcgi
#!/usr/bin/rrdcgi
<html>
<head>
    <title>tcp_services</title>
    <META HTTP-EQUIV=Refresh CONTENT="120"/>
</head>
<body>
<p><b>Trafic par service</b><br/>
Dernière MAJ:
<RRD::TIME::LAST /var/lib/rrd/tcp_services.rrd "%A, %B %d, %Y %I:%M%p"><br/>
<span style='color: #00FF00;'>&mdash;&mdash; vers</span>
&nbsp; &nbsp;
<span style='color: #0000FF;'>&mdash;&mdash; de</span>
</p>

<p><b>ssh</b><br/>
<RRD::GRAPH tcp_services-9922-6hr.png
        -s -6h5min -e -5min
        -v 'Bits per second'
        DEF:in=/var/lib/rrd/tcp_services.rrd:9922_in:AVERAGE
        DEF:out=/var/lib/rrd/tcp_services.rrd:9922_out:AVERAGE
        CDEF:out_bits=out,8,*
        CDEF:in_bits=in,8,*
        AREA:in_bits#00FF00
        LINE1:out_bits#0000FF>
</p>

<p><b>mail</b><br/>
<RRD::GRAPH tcp_services-25-6hr.png
        -s -6h5min -e -5min
        -v 'Bits per second'
        DEF:in=/var/lib/rrd/tcp_services.rrd:25_in:AVERAGE
        DEF:out=/var/lib/rrd/tcp_services.rrd:25_out:AVERAGE
        CDEF:out_bits=out,8,*
        CDEF:in_bits=in,8,*
        AREA:in_bits#00FF00
        LINE1:out_bits#0000FF>
</p>

<p><b>fetchmail pop3s</b><br/>
<RRD::GRAPH tcp_services-995-6hr.png
        -s -6h5min -e -5min
        -v 'Bits per second'
        DEF:in=/var/lib/rrd/tcp_services.rrd:995_in:AVERAGE
        DEF:out=/var/lib/rrd/tcp_services.rrd:995_out:AVERAGE
        CDEF:out_bits=out,8,*
        CDEF:in_bits=in,8,*
        AREA:in_bits#00FF00
        LINE1:out_bits#0000FF>
</p>

<p><b>web</b><br/>
<RRD::GRAPH tcp_services-80-6hr.png
        -s -6h5min -e -5min
        -v 'Bits per second'
        DEF:in=/var/lib/rrd/tcp_services.rrd:80_in:AVERAGE
        DEF:out=/var/lib/rrd/tcp_services.rrd:80_out:AVERAGE
        CDEF:out_bits=out,8,*
        CDEF:in_bits=in,8,*
        AREA:in_bits#00FF00
        LINE1:out_bits#0000FF>
</p>

<p><b>news</b><br/>
<RRD::GRAPH tcp_services-119-6hr.png
        -s -6h5min -e -5min
        -v 'Bits per second'
        DEF:in=/var/lib/rrd/tcp_services.rrd:119_in:AVERAGE
        DEF:out=/var/lib/rrd/tcp_services.rrd:119_out:AVERAGE
        CDEF:out_bits=out,8,*
        CDEF:in_bits=in,8,*
        AREA:in_bits#00FF00
        LINE1:out_bits#0000FF>
</p>

<p><b>https</b><br/>
<RRD::GRAPH tcp_services-443-6hr.png
        -s -6h5min -e -5min
        -v 'Bits per second'
        DEF:in=/var/lib/rrd/tcp_services.rrd:443_in:AVERAGE
        DEF:out=/var/lib/rrd/tcp_services.rrd:443_out:AVERAGE
        CDEF:out_bits=out,8,*
        CDEF:in_bits=in,8,*
        AREA:in_bits#00FF00
        LINE1:out_bits#0000FF>
</p>

</body>
</html>[/code]

Le fichier doit appartenir à apache et être exécutable
[code]lol:/var/www# chown -R www-data: /var/www/rrd-iptraf
lol:/var/www# cd rrd-iptraf/
lol:/var/www/rrd-iptraf# chmod 755 tcp_services.rcgi

Apache doit reconnaître notre fichier rcgi : Ajoutez à /etc/apache2/httpd.conf

AddHandler cgi-script .rcgi

Ajoutez le dossier contenant le rcgi dans /etc/apache2/sites-available/default

<Directory /var/www/rrd-iptraf/> Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch AllowOverride All Order allow,deny allow from all </Directory>

Redémarrez apache

lol:/var/www# /etc/init.d/apache2 restart Restarting web server: apache2 ... waiting .

Rendez-vous dans votre navigateur : localhost/rrd-iptraf/tcp_services.rcgi


J’espère ne pas avoir laissé trop de boulettes :wink:

Edit : Pour ceux qui ne peuvent veut pas exécuter du rcgi sur leur serveur, un script de Antalgeek ici : viewtopic.php?p=275309#p275309
(Le script crée le PNG dans le répertoire où se trouve le cgi et il est affiché dans une balise img. )

Edit2 : Antalgeek a écrit un srcipt qui permet de choisir la période de présentation !!! Merci !
C’est ici : viewtopic.php?p=276366#p276366

Nota Bene : pour toute remarque ou question, merci d’utiliser le fil de discussion prévu à cet effet.