Redondance entre FAI et lignes ADSL multiples

AiguillageNous installons assez souvent de multiples lignes Internet chez nos clients en réalisant du partage de charge sortant pour la navigation web.

Je me suis retrouvé dernièrement dans le cas d’une architecture sous contraintes :

  • proxy Linux 2.4.x Squid disposant de 2 interfaces Ethernet vers :
    • une ligne ADSL, via un routeur bas de gamme
    • le réseau interne et sa ligne institutionnelle (= historique).
  • par défaut le traffic de navigation web doit sortir par l’ADSL
  • en cas de coupure du service (au niveau du routeur, de la ligne ADSL, du FAI, etc..) , le proxy doit alors utiliser l’ancienne ligne avec une remontée d’alerte.

J’aurais pu utiliser les fonctionnalités avancées de iproute2 et nano : il existe une abondante litterature à ce sujet (je vous conseille d’ailleurs cette introduction), mais cela était rendu difficile par la vieille version du noyau, l’impossibilité de le patcher (système en production) et ….. le temps compté.

Je me suis donc contenté d’écrire un script Perl réalisant un test HTTP sur 5 sites majeurs, basculant si besoin (en détectant l’état actuel : nominal ou backup) par manipulation de la table de routage et générant un mail d’alarme en cas de bascule. C’est ma façon de réaliser un système supportant la Dead gateway detection (DGD) dans un cas actif/passif (master/backup) !

Je vous livre ici « brut de fonderie » ce script Perl1

#!/usr/bin/perl -w
# Auteur : SR
# 20 Avril 2007
use Net::Ping;
use Net::SMTP;

my @hosts=("www.yahoo.fr",
"www.google.fr",
"www.tf1.fr",
"www.free.fr",
"www.randco.fr");

# Renseigner ci-dessous les @IP de vos 2 passerelles
# nominale et secours
my $backup_gw="10.0.a.b";
my $main_gw="10.0.c.d";

# Renseigner ci-dessous les paramètres pour l email d'alerte
my ($smtp_server,$mail_dest,$mail_cc)=("smtp.mycompany.fr",
"user1@mycompany.fr" ,
"user2@mycompany.fr , user3@mycompany.fr");

# Activer debug a  1 pour obtenir des messages de debug
my $debug=0;

my ($success,$fail)=(0,0);
my $p = Net::Ping->new("syn");
$p->{port_num} = getservbyname("http", "tcp");

foreach $host (@hosts) {
   sleep(5);
   if ($p->ping($host)) {
     while (($host,$rtt,$ip) = $p->ack) {
     print "HOST: $host [$ip] a répondu en $rtt secondes n" if ($debug);
   };
   $success++;

   } else {
      $fail++;
      print "$host est injoignable n" if ($debug);
   }
};

$p->close();

if ($success > $fail) {
    # On determine les routes par defaut a  modifier
    my $failover_cmd = parse_route_table($main_gw,$backup_gw);
    ## on verifie s'il existe des routes à effacer
    if ($failover_cmd=~/routesdeletes/) {
       $msg="Basculement sur la passerelle de backup $backup_gw !!n";
       print $msg;
       print $failover_cmd;
       system($failover_cmd);
       mail($smtp_server,$mail_dest,$mail_cc,$msg)
    } else {
       print "On est déja  sur la passerelle de backup $backup_gw !!n";
    };
};

#-- Contenu des fonctions ------------------------
sub parse_route_table {

# on recupere en variables les gw main et backup
my ($mgw,$bgw)=@_;
my $cmd="";
open (TABLE, "/sbin/route -n |") or
    die "Impossible d'obtenir la table de routage n";

while ($l=<TABLE>) {
    ## on ne traite que les routes par defaut
    next unless ($l=~/^(0.0.0.0)s*([0-9.]*)s*(0.0.0.0)/);
    ## on verifie qu'on est pas deja sur le secours !!
    next if $2=~/^$bgw$/;
    $cmd.="/sbin/route delete default gw $2;" if defined $2;
    };

close TABLE;
# on applique la nouvelle route par defaut

$cmd.="/sbin/route add default gw $backup_gwn";
return $cmd;
}

sub mail {

my ($smtp_server,$mail_dest,$mail_cc,$msg)=@_;
my $smtp = Net::SMTP->new($smtp_server);

$smtp->mail("shipper@mycompany.fr");
$smtp->to($mail_dest);
$smtp->cc($mail_cc);
$smtp->data();
$smtp->datasend("From: $mail_destn");
$smtp->datasend("To: $mail_destn");
$smtp->datasend("Cc: $mail_ccn");
$smtp->datasend("Subject: ADSL: Script Bascule FAI n $msgn");
$smtp->datasend("n");
$smtp->datasend($msg);
$smtp->dataend();
$smtp->quit;

print "Mail parti...n";

}

Il ne reste plus qu’à insérer ceci dans la crontab pour effectuer un test toutes les 5 minutes de 7h à 23h tous les jours de semaine :

    */5 7-23 * * 2-5 /chemin/complet/ISP_test.pl

икони


  1. si les modules Net::Ping et Net::SNMP ne sont pas installés, le faire ainsi à partir du shell :

    perl -MCPAN -e shell

    puis

    install Net::Ping
    install Net::SNMP

    [back]

Post to Twitter

About SR

Expert Réseau et Sécurité. Vous pouvez me contacter sur sreytan.(at).randco.fr
This entry was posted in . Bookmark the permalink.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>