par JaDiuM » 18 Mars 2004 15:57
Bonjour,
<BR>
<BR>Aprés avoir lu à plusieurs reprise le mal de certain à relancer leurs connections VPN (Dyndns): voici ce qui va vous changer la vie.
<BR>et vous évitera ce message:
<BR>
<BR>"packet from IP:500: initial Main Mode message received on IP:500 but no connection has been authorized"
<BR>
<BR>
<BR>Voici, le script "ipsecmon.pl" perl à installer dans /usr/local/bin/ :
<BR>
<BR>#------------------couper ici-------------------------------
<BR>#!/usr/bin/perl
<BR>
<BR># ipsec_monitor for FreeS/WAN
<BR># Copyright (C) 2003 by Tim Niemueller <tim@niemueller.de>
<BR># Website: <!-- BBCode auto-link start --><a href="http://www.niemueller.de/software/perl/ipsecmonitor" target="_blank">http://www.niemueller.de/software/perl/ipsecmonitor</a><!-- BBCode auto-link end -->
<BR>#
<BR># This program is free software; you can redistribute it and/or modify
<BR># it under the terms of the GNU General Public License as published by
<BR># the Free Software Foundation; either version 2 of the License, or
<BR># (at your option) any later version.
<BR>#
<BR># This program is distributed in the hope that it will be useful,
<BR># but WITHOUT ANY WARRANTY; without even the implied warranty of
<BR># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
<BR># GNU General Public License for more details.
<BR>
<BR>
<BR>#### Modules
<BR>use strict;
<BR>use Getopt::Long;
<BR>use POSIX qw(setsid);
<BR>use Fcntl ':flock';
<BR>
<BR>#### Constants, just to make code readable
<BR>my $VERSION="0.1";
<BR>my $ipsec="/usr/sbin/ipsec"; ########## Fonction de votre distrib
<BR>
<BR>#### Get parameters
<BR>my %params=();
<BR>GetOptions("conn=s" => $params{'conn'},
<BR> "host=s" => $params{'host'},
<BR> "script:s" => $params{'script'},
<BR> "t:i" => $params{'t'},
<BR> "d" => $params{'d'},
<BR> "s" => $params{'s'},
<BR> ) or usage();
<BR>if ( ($params{'conn'} eq "") || ($params{'host'} eq "") ) {
<BR> usage();
<BR>}
<BR>if ( ($params{'script'} ne "") && (! -x $params{'script'}) ) {
<BR> failure_exit("The script file does not exist or is not executable.");
<BR>}
<BR>if ($params{'t'} eq "") {
<BR> $params{'t'} = 180;
<BR>}
<BR>
<BR>if ($params{'s'}) {
<BR> use Sys::Syslog qw(:DEFAULT setlogsock);
<BR> setlogsock('unix');
<BR> openlog("ipsec_monitor($params{'conn'})", "", "authpriv");
<BR>}
<BR>
<BR># Where should we create the lock file?
<BR>my $lockfile = "/var/lock/ipsec_monitor.$params{'conn'}.lock";
<BR>
<BR>#### Signals
<BR>$SIG{'TERM'} = &terminate_daemon;
<BR>$SIG{'HUP'} = &check_status;
<BR>
<BR>#### Globals to make it quick and dirty
<BR>my $oldaddr = "";
<BR>
<BR>#### Main Program, main() like
<BR>
<BR>daemonize();
<BR>create_lock();
<BR>
<BR>while (1) {
<BR> my $oa = $oldaddr;
<BR> my $na = check_status();
<BR> # logmsg("debug", "IP checked: ".join(".", unpack('C4', $oa))." -> ".join(".", unpack('C4', $na)));
<BR> sleep $params{'t'};
<BR>}
<BR>
<BR>
<BR>#### Subs related to time handling and alarms
<BR>sub check_status {
<BR> my $newaddr=gethostbyname($params{'host'});
<BR> if ($newaddr ne $oldaddr) {
<BR> # Address has changed, replace connection
<BR> logmsg("info", "IP change detected: ".join(".", unpack('C4', $oldaddr))." -> ".join(".", unpack('C4', $newaddr)));
<BR> if ($oldaddr ne "") {
<BR> # On Startup this is empty of course...
<BR> logmsg("info", "Replacing connection");
<BR> system("$ipsec auto --replace $params{'conn'}");
<BR> if ($params{'script'}) {
<BR> # We have a script file, wait 60 seconds and then excute it
<BR> sleep 60;
<BR> system($params{'script'});
<BR> }
<BR> }
<BR> $oldaddr = $newaddr;
<BR> }
<BR> return $newaddr;
<BR>}
<BR>
<BR>
<BR>#### Subs related to basic program stuff (daemon, fifo, lock etc.)
<BR>
<BR># Could be modified to syslog for example
<BR>sub logmsg {
<BR> my $priority = shift;
<BR> my $msg = shift;
<BR>
<BR> if ($params{'d'}) {
<BR> my $now=localtime();
<BR> print "$now ($priority): ".printf($msg, @_)."n";
<BR> } else {
<BR> if ($params{'s'}) {
<BR> syslog($priority, $msg, @_);
<BR> }
<BR> }
<BR>}
<BR>
<BR># logs the errors and exits the program
<BR>sub failure_exit {
<BR> logmsg($_[0]);
<BR> die $_[0];
<BR>}
<BR>
<BR>
<BR># Disconnects from console
<BR>sub daemonize {
<BR> if (! $params{'d'}) {
<BR> my $pid;
<BR> chdir '/' or failure_exit("Can't chdir to /: $!");
<BR> open STDIN, '/dev/null' or failure_exit("daemonize: Can't read /dev/null: $!");
<BR> open STDOUT, '>/dev/null' or failure_exit("daemonize: Can't write to /dev/null: $!");
<BR> defined($pid = fork) or failure_exit("Can't fork: $!");
<BR> exit 0 if $pid;
<BR> setsid() or failure_exit("Can't start a new session: $!");
<BR> print LOCK $$;
<BR> logmsg("info", "Started successfully");
<BR> }
<BR>}
<BR>
<BR># creates the lockfile
<BR>sub create_lock {
<BR> open(LOCK, ">$lockfile");
<BR> my $ok = flock(LOCK, LOCK_EX | LOCK_NB);
<BR> failure_exit("It seems that another instance is already running") if (! $ok);
<BR>}
<BR>
<BR>
<BR># removes the lockfile
<BR>sub remove_lock {
<BR> flock(LOCK, LOCK_UN);
<BR> close(LOCK);
<BR> unlink $lockfile;
<BR>}
<BR>
<BR># Terminates daemon closing ISDN connection,
<BR># used as signal handler
<BR>sub terminate_daemon {
<BR> alarm 0; # Stop timer
<BR> remove_lock();
<BR> logmsg("info", "Stopped");
<BR> if ($params{'s'}) {
<BR> closelog();
<BR> }
<BR> exit;
<BR>}
<BR>
<BR># prints some basic usage message
<BR>sub usage {
<BR> print "ipsec_monitor v$VERSIONn",
<BR> "Copyright (C) 2003 by Tim Niemuellernn",
<BR> "Monitors a hostname and when it changes replaces the IPSecn",
<BR> "connection (FreeS/WAN style) to get the link up againnn",
<BR> "Usage: ipsec_monnitor --conn=CONNECTIONNAME n",
<BR> " --host=HOSTNAME [options]n",
<BR> "where options are:n",
<BR> "--conn=CONN: FreeS/WAN Connection namen",
<BR> "--host=HOST: Hostname of the connection to be monitoredn",
<BR> "--script=..: Path to an additional script that is executed 1 minuten",
<BR> " after the connection has been replaced. For example routingn",
<BR> " stuff that needs to be done. Script must be executable!n",
<BR> "-t t : check every t seconds if connection parameters have changedn",
<BR> " Dafault: 180 secondsn",
<BR> "-d : Debug mode. Do not fork to background, log output to STDOUTn",
<BR> "-s : Use Syslog for logging. Default is no logging.n",
<BR> "n";
<BR> exit 1;
<BR>}
<BR>#--------------------------------couper ici-------------------------------------------------
<BR>
<BR>Donc voila une fois le script installé, il faut le rendre executable (chmod 755 ipsecmon.pl).
<BR>
<BR>
<BR>Voici un script "reload.sh" qui va relancer une conn vpn, à ajouter dans /usr/local/bin
<BR>
<BR>#----------------------couper ici---------------------------------------
<BR>#!/bin/sh
<BR> echo "redemarrage ipsec vpnclient1";
<BR> /usr/sbin/ipsec auto --replace vpnclient1
<BR> /usr/sbin/ipsec auto --rereadsecrets
<BR> /usr/sbin/ipsec auto --up vpnclient1
<BR>
<BR> exit 0
<BR>#------------------------couper ici--------------------------------------
<BR>
<BR>rendre le script executable (chmod 755 reload.sh)
<BR>VPNCLIENT1 est le nom du --conn dans ipsec.conf.
<BR>
<BR>
<BR>Voici la syntaxe à utiliser sur le serveur VPN:
<BR>
<BR>perl /usr/local/bin/ipsemon.pl --conn VPNCLIENT1 --host=toto.riri.tata --script=/usr/local/bin/reload.sh -s
<BR>
<BR>--HOST: c'est l'adresse de type dyndns (ou static), de votre VPNCLIENT1
<BR>
<BR>
<BR>
<BR>
<BR>Voila il reste plus qu'a reproduire fonction du nombre de client (VPNCLIENT2, VPNCLIENT3 etc...), et recreer un reload.sh par client (reload1.sh, reload2.sh etc...)
<BR>
<BR>
<BR>
<BR>
<BR>Voila en esperant que cela réponde à un besoin.
<BR>
<BR>
<BR>
<BR>Cdt
<BR>
<BR>
<BR>
<BR>
<BR>
<BR>
<BR>
" Quand on ne sait pas où l'on va, tous les chemins mènent à nulle part." [Kissinger]