[Linux-bruxelles] Contrôle de volume internet mensuel, par ordinateur, dans un petit WLAN.

Jean-Charles de Longueville jean-charles at de-longueville.eu
Sam 28 Nov 00:14:58 CET 2009


Nicolas Jungers a écrit :

> On 22/11/09 21:08, Xavier Jacques wrote:
>   
>> Bonjour,
>>
>> Je fournis internet dans une maison d'étudiants.
>> Nous partageons une ligne ADSL2+ via un routeur et un AP Cisco qui 
>> dialoguent avec les ordis filtrés par MAC address.
>>
>> Selon les conditions générales, mes cokoteurs et cokoteuses 
>> "s'engagent à utiliser honnêtement un compteur de trafic internet".
>> Le hic, c'est qu'il n'y en a qu'un seul qui est honnête.
>> Les autres préfèrent quitter leur compteur pour télécharger à gogo.
>>
>> Marc Arnoldy eut la gentillesse d'entamer une recherche à ce sujet dès 
>> cet après-midi, chez FIJ.
>> Mais il m'a aussi et surtout conseillé de poster sur la liste !
>>
>> Quelqu'un parmi vous a-t-il déjà pu résoudre ce problème ?
>> Via le routeur ou via un serveur ?
>>     
>
> La solution simple passe par iptables. Je l'ai fait il y a une dizaine 
> d'année. Si tu contrôles le routeur c'est assez facile. Tu assignes un 
> compteur par IP source. Tu relèves les compteurs régulièrement pour ne 
> pas perdre les informations lors d'un reboot consécutifs à une "panne" 
> de courant. Tu verrouilles bien les IP sur les adresses MAC et tu ne 
> laisses pas passer d'autres IP. Maintenant, à l'époque j'ai fait ça "à 
> la main" et je ne saurais plus le faire, mais de nos jours il doit y 
> avoir de jolies interfaces graphiques à disposition.
je viens de mette en place la solution suggérée par Nicolas:

1/ préparer le routeur à surveiller

2/ préparer la DB qui va recueillir les mesures

3/ scripter la lecture des compteurs et leurs reports vers la DB

4/ lancer le script par cron

5/ enjoy!

1/ préparer le routeur à surveiller sur base de 
http://rtg.sourceforge.net/ et y ajouter

for i in 193 194 195 
do
iptables -t mangle -A PREROUTING -s 89.106.241.$i/32 -i eth0 -m mark ! --mark $i
iptables -t mangle -A POSTROUTING -o eth0 -d 89.106.241.$i/32 -m mark ! --mark $i
done

2/ préparer la DB qui va recueillir les mesures

on ajoute a RTG un routeur "dummy" de numéro (rid) 2; définit ayant une 
vitesse de 100Mbps.
Chaque IP à surveiller sera un interface du dummy au sens de RTG.

#!/usr/bin/perl
use DBI;
use DBD::mysql;
use Socket;

$database = "rtg";
$hostname = "mykel.hellea.net";
$login    = "user";
$mdp      = "******";
$debug    = 0;

$dsn = "DBI:mysql:database=$database;host=$hostname";
$dbh = DBI->connect($dsn, $login, $mdp) or die "Echec connexion";
if ($debug) {print "Connexion à la DB $dsn \n";}
$rid   = '2';
$speed = '100000000';
for ($i = 196; $i < 255; $i++) {
    $adrr = sprintf("89.106.241.%d",$i);
    $iadr = inet_aton($adrr);
    $name  = gethostbyaddr($iadr, AF_INET);
    @nums  = split('[.]',$adrr);
    $num   = $nums[3];
    if ($debug) {print "VALUES ( $num, $name, $rid, $speed, $adrr, 'active' );\n";}
    $requete="INSERT INTO interface ( id , name , rid , speed , description , status ) VALUES ( $num, '$name', $rid, $speed, '$a
drr', 'active' ); ";
    $sth = $dbh->prepare($requete);
    $sth->execute();
    $sth -> finish;
}
$dbh -> disconnect;
if ($debug) {print "Déconnexion de la DB OK\n";}

3/ scripter la lecture des compteurs et leurs reports vers la DB

#!/usr/bin/perl
### /usr/local/sbin/ipcounts.perl
use DBI;
use DBD::mysql;

$database = "rtg";
$hostname = "mykel.hellea.net";
$login    = "user";
$mdp      = "******";
$debug    = 0;

$dsn = "DBI:mysql:database=$database;host=$hostname";
$dbh = DBI->connect($dsn, $login, $mdp) or die "Echec connexion";
if ($debug) {print "Connexion à la DB $dsn \n";}
while (<>) {
  @items = split(/:/);
  if ($items[0] == ""){
    if ($debug) {print "aborted : no pkts [@items]\n";}
    next;
  }
  $pkts  = $items[0];
  $bytes = $items[1];
  $src   = $items[2];
  $dst   = $items[3];
  $flow  = "error";
  if (($dst == "0.0.0.0/0")) {
    $flow = 1;
    $adrr  = $src;
  } 
  if (($src == "0.0.0.0/0")){
    $flow = 0;
    $adrr  = $dst;
  }
  @nums = split(/[.]/,$adrr);
  $num = $nums[3];
  if ($num == "0/0") {
    if ($debug) {print "aborted : because num is $num [$flow - $adrr]\n";}
    next;
  }
  if ($flow) {
    $requete="INSERT INTO ifInUcastPkts_2 ( id , dtime , counter ) VALUES ( $num, NOW(), $pkts );";
    $sth = $dbh->prepare($requete);
    $sth->execute();
    $sth -> finish;
    $requete="INSERT INTO ifInOctets_2 ( id , dtime , counter ) VALUES ( $num, NOW(), $bytes );";
    $sth = $dbh->prepare($requete);
    $sth->execute();
    $sth -> finish;
    if ($debug) {print "record for: $num, $flow, $adrr, $pkts, $bytes \n";}
    next;
  } else {
    $requete="INSERT INTO ifOutUcastPkts_2 ( id , dtime , counter ) VALUES ( $num, NOW(), $pkts );";
    $sth = $dbh->prepare($requete);
    $sth->execute();
    $sth -> finish;
    $requete="INSERT INTO ifOutOctets_2 ( id , dtime , counter ) VALUES ( $num, NOW(), $bytes );";
    $sth = $dbh->prepare($requete);
    $sth->execute();
    $sth -> finish;
    if ($debug) {print "record for: $num, $flow, $adrr, $pkts, $bytes \n";}
    next;
  }
}
$dbh -> disconnect;
if ($debug) {print "Déconnexion de la DB OK\n";}

4/ lancer le script par cron

iptables -t mangle -vnxL | gawk '/MARK/ {print $1":"$2":"$7":"$8":"}' | /usr/bin/perl /usr/local/sbin/ipcounts.perl

5/ enjoy!

https://www.hellea.net/rtg/view.php?rid=2




Plus d'informations sur la liste de diffusion Linux-bruxelles