check_honeynet v2.0.a2

Release 2.0.a2 (Alpha quality) for check_honeynet is here :-) , go check it out!

PERL:
  1. #!/usr/bin/perl
  2. # $Id: check_honeynet.pl 801 2008-06-03 20:40:53Z remko $
  3. ###########################################################################
  4.  
  5. ###########################################################################
  6. # Copyright (C) 2005-2008, Remko Lodder <remko@FreeBSD.org>. All rights reserved.
  7. #
  8. # Redistribution and use in source and binary forms, with or without
  9. # modification, are permitted provided that the following conditions
  10. # are met:
  11. # 1. Redistributions of source code must retain the above copyright
  12. #    notice, this list of conditions and the following disclaimer.
  13. # 2. Redistributions in binary form must reproduce the above copyright
  14. #    notice, this list of conditions and the following disclaimer in the
  15. #    documentation and/or other materials provided with the distribution.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  21. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. # SUCH DAMAGE.
  28. ###########################################################################
  29.  
  30. ###########################################################################
  31. # Contributors:
  32. # Ivo Naninck, (Language), Marc Plaisier (language), Mart vd Wege (Mailer
  33. # suggestion),
  34. # Lance Spitzner (the most valueable feedback regarding the script).
  35. # Richard Arends (suggested the actual perl mailer; and gave a good example
  36. # on how to use the module),
  37. # Robert Blacquiere (showed me Simple::Config, which I am using now to
  38. # obtain configuration informatin, as well as write statistics to a
  39. # temporary file)
  40. #
  41. # Script:
  42. # This is a stand alone script written for honeynet.org. It's purpose is
  43. # to check the listed mirrors to see which one is outdated and notify
  44. # the administrator of the outdated mirror if needed. This way the
  45. # mirrors will always be within a certain timeframe and can be removed
  46. # if they are too outdated.
  47. #
  48. # Written in colaboration with Lance Spitzner <lance@honeynet.org>
  49. ###########################################################################
  50.  
  51. ###########################################################################
  52. # Differences between releases, started this between 1.5 and 1.6 sorry
  53. # for the loss of potential usefull information (although I might be able
  54. # to retrieve the missing data from my CVS branches).
  55. # Note that all the three version based versions are just bugfixes to some
  56. # degree.
  57. # Version       Who             What
  58. # 1.1           Remko           Initial script to check the mirrors.
  59. # 1.1->1.2      Remko
  60. # 1.2->1.3      Remko
  61. # 1.3->1.4      Remko
  62. # 1.4->1.5      Remko           Code cleanups, restructure of code; corrected
  63. #                               some bugs between various releases spotted
  64. #                               by Lance.
  65. # 1.5->1.6      Remko           Cleanups, changed structure for timestamp
  66. #                               retrieval; make it human readable and match
  67. #                               on a specific pattern. Made the version dependend
  68. #                               on the configuration version and visa-versa
  69. #                               to be able to make big config changes.
  70. #                               BF-1: Fix the email send options by using the
  71. #                                     correct Net::SMTP commands.
  72. #                               BF-1: Fix the parsing of the new mirrorprobe
  73. #                                     layout.
  74. #                               BF-2: Change the Mailer used to send out the
  75. #                                     report.
  76. # 1.6->1.7      Remko           Implement Config::Simple, makes configuration
  77. #                               much easier!
  78. # 1.7->2.0      Remko           a1: Implement that we can trace various sites with
  79. #                               multiple problems more easily by using a
  80. #                               semi-persisent configuration file.  This brings
  81. #                               the entire branch to an entirely new world.
  82. #                               Which is why we bump the version to 2.0
  83. #                               a2: Implement file-statistics checker, if the
  84. #                               file does not exist yet, we need to make sure
  85. #                               we know and that we can bypass certain readins
  86. #                               so that we are not going to get into trouble
  87. #                               later on.
  88. ###########################################################################
  89.  
  90. use strict;
  91. use warnings;
  92. use LWP::Simple;
  93. use Getopt::Std;
  94. use Mail::Sendmail;
  95. use Config::Simple;
  96.  
  97. ###########################################################################
  98. # variables. All configurable options are defined below. Please adjust them
  99. # to your need.
  100. ###########################################################################
  101.  
  102. # Version, author and script specific behaviour
  103. my $author              = 'Remko Lodder <remko@FreeBSD.org>';   # Name of the author
  104. my $name                = __FILE__;                             # Our scriptname.
  105. my $MAJOR               = '2';                                  # Our major version
  106. my $MINOR               = '0';                                  # Our minor version
  107. my $PATCHLEVEL          = 'a2';                                 # Our patchlevel
  108. my $version             = "$MAJOR.$MINOR.$PATCHLEVEL";          # Our version.
  109.  
  110. ###########################################################################
  111. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  112. # Do not edit anything below this line unless you know what you are doing.
  113. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  114. ###########################################################################
  115.  
  116. ###########################################################################
  117. # Prototypes, specify upfront what we are going to use if globally needed
  118. # and prototype arrays, hashes and functions.
  119. ###########################################################################
  120.  
  121. # create the option hash, we will use that later to add our option flags.
  122. my %option              = ();
  123.  
  124. # Template our arrays
  125. my (@MIRRORS);
  126.  
  127. # Template some standard variables
  128. my ($CONFIGFILE, $status, $reporthost, $timestamp,$target,
  129.     $enable_mail, $cfg, $cfg_out, $outfile, $alert_max,
  130.     $alert_min, $alert_mid, $mail_from, $mail_bcc, $mail_cc);
  131.  
  132. # Prototype functions
  133. sub fetch_data ($$);
  134. sub email_report ($$$);
  135. sub convert_input ($);
  136. sub process_mirrors (@);
  137. sub create_timestamp ($);
  138.  
  139. ###########################################################################
  140. # Script itself
  141. ###########################################################################
  142.  
  143. getopts("cC:f:F:hpR:tv", \%option);
  144.  
  145. my $config_flag   = 1 if $option{f};
  146. my $config_option = $option{f};
  147.  
  148. my $create_flag   = 1 if $option{c};
  149. my $help_flag     = 1 if $option{h};
  150. my $process_flag  = 1 if $option{p};
  151. my $test_flag     = 1 if $option{t};
  152. my $convert_flag  = 1 if $option{C};
  153. my $fetch_flag    = 1 if $option{F};
  154. my $retrieve_flag = 1 if $option{R};
  155.  
  156. # Simply assign the contents of the configuration parameter to the
  157. # configuration file variable, otherwise overrule it with the
  158. # default value
  159.  
  160. $CONFIGFILE     = $config_option || "./honeynet.cf";
  161.  
  162. # Read in current configuration.
  163. # This should always succeed, in case it doesn't then we cannot do
  164. # anything at all.
  165.  
  166. $cfg            = new Config::Simple($CONFIGFILE);
  167.  
  168. #####
  169. ##### Global variable assignment after reading config
  170. #####
  171.  
  172. # Read in some variales upfront, so that we can more
  173. # easily use them later on.
  174.  
  175. @MIRRORS        = $cfg->param('CONFIG.mirrors');
  176. $outfile        = $cfg->param('CONFIG.outfile');
  177. $enable_mail    = $cfg->param('CONFIG.enable_mail');
  178. $alert_max      = $cfg->param('CONFIG.alert_max');
  179. $alert_mid      = $cfg->param('CONFIG.alert_mid');
  180. $alert_min      = $cfg->param('CONFIG.alert_min');
  181. $mail_from      = $cfg->param('CONFIG.fromaddr');
  182. $mail_bcc       = $cfg->param('CONFIG.ccaddr');
  183. $mail_cc        = $cfg->param('CONFIG.mirroradmin');
  184.  
  185. if (-e "$outfile")
  186. {
  187.  
  188.         # Read in the statistics from our last run
  189.         $cfg_out        = new Config::Simple($outfile);
  190.  
  191.         # Make an instant backup before we do a new run.
  192.         $cfg_out->write("$outfile.orig");
  193. }
  194. else
  195. {
  196.         # Create the statistics file for our entire run
  197.         $cfg_out        = new Config::Simple(syntax=>'ini');
  198. }
  199.  
  200. # Make sure that there us a version statement in the configuration file, so that we can see whether we are
  201. # compabible or not.
  202.  
  203. if (!$cfg->param('CONFIG.version'))
  204. {
  205.         print "It appears that you do not have a version statement in your configuration file. This means that the version you are using now is
  206. too old, make sure that you obtain the latest one and update that to your needs.";
  207.         exit(1);
  208. }
  209.  
  210. if ($cfg->param('CONFIG.version'))
  211. {
  212.         my($version_def_major,$version_def_minor) = $cfg->param('CONFIG.version') =~ /(\d+)\.(\d+)/;
  213.  
  214.         # the script can defer between MAJOR and MINOR releases; bugfixes aka patchlevels are
  215.         # not affected by this and can thus be ignored.
  216.         # TODO: This check should be made more flexible in the future, version 1.4 and 1.5 share
  217.         # the same configuration file and should both pass.
  218.  
  219.         if(($version_def_major lt $MAJOR) or ($version_def_minor lt $MINOR))
  220.         {
  221.                 print "You appear to be using an older configuration file that might not be compatible with the current version of the
  222. script, please validate that you have the latest options included and copy over the version statement from the latest available configuration
  223. file. Make sure that the old version statement is overwritten!
  224. The current script runs on version: $version, while the configuration is for version $cfg->param('CONFIG.version')\n";
  225.                 exit(1);
  226.         }
  227. }
  228.  
  229. # Create a new timestamp that will be fed into the mirrors, which we can use to test the
  230. # age of the mirror.
  231.  
  232. if ($create_flag) {
  233.         create_timestamp($cfg->param('CONFIG.probefile'));
  234. }
  235.  
  236. elsif ($process_flag) {
  237.         # Process the mirrors using the hash we have for them.
  238.         process_mirrors(@MIRRORS);
  239. }
  240.  
  241. # test mode, printout information on screen.
  242. elsif($test_flag)
  243. {
  244.         # In test mode we dont send out emails.
  245.         $enable_mail = 0;
  246.  
  247.         print("$name: Starting\n");
  248.         print("$name: Processing mirrors\n");
  249.  
  250.         # Process the mirrors using the hash we have for them.
  251.         process_mirrors(@MIRRORS);
  252.  
  253.         print("$name: Finishing\n");
  254. }
  255.  
  256. # convert input from unixtime to human readable time.
  257. elsif($convert_flag)
  258. {
  259.         print "$option{C} resolves to " . convert_input($option{C}) . "\n";
  260. }
  261.  
  262. # fetch the mirrorprobe file from the given host
  263. elsif($fetch_flag)
  264. {
  265.         my $result = fetch_data($option{F}, $cfg->param('CONFIG.sourcefile'));
  266.         open(OUT, "> $cfg->param('CONFIG.outdir')/$option{F}.timestamp");
  267.                 print OUT $result;
  268.         close(OUT);
  269. }
  270.  
  271. # Fetch the mirror timestamp and parse it. Print the output back on the screen.
  272. elsif($retrieve_flag)
  273. {
  274.         my $result = fetch_data($option{R}, $cfg->param('CONFIG.sourcefile'));
  275.         print("$option{R} was last modified " . convert_input($result) . "\n");
  276. }
  277.  
  278. # People expect a help option, provide it for them.
  279. elsif ($help_flag)
  280. {
  281.         print_help();
  282. }
  283.  
  284. # No valid options had been given, fallback to the help information.
  285. else
  286. {
  287.         print_help();
  288. }
  289.  
  290. # print_help: expects no input, just prints the help information on how
  291. # the application should work.
  292. sub print_help
  293. {
  294.         print("Usage:\t$name [ -c ] [ -C <value> ] [ -f <configurationfile> ] [ -F <host> ] [ -h ] [ -p ] [ -R <host> ] [ -t ]
  295. \t-c\tCreate the timestamp for the localmachine. This timestamp can be used to determine when the mirror was last updated.
  296. \t-C\t<value> converts the unix timestamp to human readable format
  297. \t-f\t<filename> Use the specified configuration file
  298. \t-F\t<host> fetch the timestamp for an external host, for example: www.honeynet.nl
  299. \t-h\tprint this help.
  300. \t-p\tCheck the status of the mirrors, and report the output to us
  301. \t-t\tTest mode, does not send out emails, but prints the information on the screen.
  302. Version: $version
  303. Originally written by Remko Lodder <remko\@FreeBSD.org, for the honeynet project.\n");
  304. }
  305.  
  306. # create_timestamp: expects a variable filled with where we should store
  307. # the unixtime (for remote mirrors).
  308. sub create_timestamp ($)
  309. {
  310.         my $probefile = shift;
  311.         open(F_OUT, "> $probefile");
  312.                 print F_OUT "Mirrorprobe time: " . time() . "
  313. Local time: " . convert_input(time());
  314.         close F_OUT;
  315. }
  316.  
  317. # convert_input: expects unixtime and converts it to human readable time.
  318. sub convert_input ($)
  319. {
  320.         my $output      = scalar localtime(shift);
  321.         return $output;
  322. }
  323.  
  324. # fetch_data: gets two variables as input, one with the fqdn of the remote host and one
  325. # with the location of where we expect the remote file. XXX: This looks a bit ugly at the
  326. # moment.
  327. sub fetch_data ($$)
  328. {
  329.         my $source      = shift;
  330.         my $sourcefile  = shift;
  331.  
  332.         my $return_data = ();
  333.         my $data        = get("http://$source$sourcefile");
  334.  
  335.         # IF the remote data is present, take out the numberic time value and return that
  336.         # ELSE obscure the data, which will revert to 1969/1970 (depending on what the machine
  337.         # considers EPOCH).
  338.         if ($data)
  339.         {
  340.                 chomp $data;
  341.  
  342.                 $return_data = $data;
  343.                 $return_data =~ s/\n/\ /;
  344.                 if ($return_data =~ /\S+ \S+ (\d+) \S+/)
  345.                 {
  346.                         $return_data = $1;
  347.                 }
  348.                 return $return_data;
  349.         }
  350.  
  351.         else
  352.         {
  353.                 $data = 0;
  354.                 return $data;
  355.         }
  356. }
  357.  
  358. # proccess_mirrors: gets an array as input with all the mirrors in it. It will walk through all hosts
  359. # and do specific actions with them, like printing out a report, or emailing it to the remote
  360. # administrator. It keeps a record of the current statustime.
  361. sub process_mirrors (@) {
  362.         my %mirror_time;
  363.         my @mirror_list = @_;
  364.  
  365.         for my $target(@mirror_list)
  366.         {
  367.                 $mirror_time{$target} = fetch_data($target,$cfg->param('CONFIG.sourcefile'));
  368.  
  369.                 # We should probably dont need to use this since it is implied in the routine itself.
  370.                 if(!$mirror_time{$target})
  371.                 {
  372.                         $mirror_time{$target} = 0;
  373.                 }
  374.  
  375.                 # declare our local time before continueing.
  376.                 my $honeynet_ctime      = time();
  377.                 my $mirror_ctime        = $mirror_time{$target};
  378.                 my $mirror_difftime     = $honeynet_ctime - $mirror_time{$target};
  379.  
  380.                 # If the resulting number is less then zero, the remote host is outdated.
  381.                 my $mirror_timediff     = $cfg->param('CONFIG.timeout') - $mirror_difftime;
  382.  
  383.                 # Everything that has a calculated time which is bigger then the timeout is
  384.                 # on the right track, everything that isn't, gets either notified or the
  385.                 # output will be present on screen.
  386.                 if ($mirror_timediff gt "0")
  387.                 {
  388.                         if($cfg->param('CONFIG.verbose') ne "0")
  389.                         {
  390.                                 $status = "OK";
  391.                                 $timestamp = scalar localtime($mirror_time{$target});
  392.                                 $reporthost = $target;
  393.                                 write;          # Write out our template.
  394.                         }
  395.                                 next;
  396.                 }
  397.                 else
  398.                 {
  399.                         my $info = $cfg_out->param("mirrors.$target");
  400.                         if (defined $info && $info gt 0)
  401.                         {
  402.                                 if ($info eq $alert_max || $info eq $alert_mid || $info eq $alert_min)
  403.                                 {
  404.                                         # The email option is enabled and we found an outdated mirror
  405.                                         # jump to the email_report function.
  406.                                         if($enable_mail)
  407.                                         {
  408.                                                 email_report($target,$mirror_time{$target},$info);
  409.                                         }
  410.                                 }
  411.  
  412.                                 # Update our local statistics first before anything else
  413.                                 $cfg_out->param("mirrors.$target", $info+1);
  414.                                 $cfg_out->param("checktime.$target", scalar localtime($mirror_time{$target}));
  415.                         }
  416.                         else
  417.                         {
  418.                                 # The email option is enabled and we found an outdated mirror
  419.                                 # jump to the email_report function.
  420.                                 if ($enable_mail)
  421.                                 {
  422.                                         email_report($target,$mirror_time{$target}, $alert_min);
  423.                                 }
  424.  
  425.                                 # Begin our statistics with 1.
  426.                                 $cfg_out->param("mirrors.$target", 1);
  427.                                 $cfg_out->param("checktime.$target", scalar localtime($mirror_time{$target}));
  428.                         }
  429.  
  430.  
  431.                         if($cfg->param('CONFIG.verbose') ne "0")
  432.                         {
  433.                                 $status = "FAIL";
  434.                                 $timestamp = scalar localtime($mirror_time{$target});
  435.  
  436.                                 # Only override if the message has the old timestamp and thus is broken.
  437.                                 if($timestamp =~ /19[6-7]\d/)
  438.                                 {
  439.                                         $timestamp = "Mirrorprobe file problems!";
  440.                                 }
  441.                                 $reporthost = $target;
  442.                                 write;          # Write out our template.
  443.                         }
  444.                 }
  445.         }
  446.  
  447. # Specify how our output is going to look like. This generates a nice overview
  448. # on the current status of the various mirrors.  This is only being used if we
  449. # print verbose.
  450. # Below: HEADER
  451. format STDOUT_TOP =
  452. ----------------------------------------------------------------------------
  453. --------------------------- Honeynet Check results -------------------------
  454. ----------------------------------------------------------------------------
  455. Status  Site                                    Last changed
  456. .
  457.  
  458. # Format specifier for the content of the printout.
  459. format STDOUT =
  460. @<<<<  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<<<<<<<<<<<<
  461. $status, $reporthost,                           $timestamp
  462. .
  463. }
  464.  
  465. # email_report: expects a target and a mirror_time, sends out an email to
  466. # the desired administrator and informs them about the current status of
  467. # the mirror.
  468. sub email_report ($$$)
  469. {
  470.         my $status      = ();
  471.         my $alert_msg   = ();
  472.         my $target      = shift;
  473.         my $mirror_time = shift;
  474.         my $alert       = shift;
  475.         my $recipient   = $cfg->param("MIRRORS.$target") || $mail_cc;
  476.  
  477.         # Make the mirror time a human parseable time, if this matches the beginning of time
  478.         # (For computers at least). Tell that there is a problem.
  479.         $mirror_time    = scalar localtime($mirror_time);
  480.  
  481.         if ($mirror_time =~ /19[6-7]\d/)
  482.         {
  483.                 $status = "Your mirror seems to have troubles fetching the mirrorprobe file.";
  484.         }
  485.         else
  486.         {
  487.                 $status = "At this moment it seems that your mirror was last updated on $mirror_time.";
  488.         }
  489.         if ($alert eq $alert_max)
  490.         {
  491.                 $alert_msg = "NOTE WELL: This is the final warning you will be receiving.  Please repair the mirror as soon as possible. In the meantime we will remove your mirror.";
  492.         }
  493.         else
  494.         {
  495.                 $alert_msg = "NOTE WELL: This is alert number $alert for your host. Please be advised that our current maximum is at $alert_max.\n";
  496.         }
  497.  
  498.         my $message = "Hello $recipient,
  499. You are recieving this email because your Honeynet Project mirror ($target) seems to be outdated.
  500. $status
  501. Could you please check whether everything is working as expected?
  502. If there is something wrong or you do no longer wish to be a mirror, please notify $mail_cc
  503. Thanks for supporting the Honeynet Project!
  504. If you have questions or concerts, please do not hesitate to contact us!
  505. $alert_msg
  506. --
  507. The Honeynet Project Mirror Admins";
  508.  
  509.         # Fill our mailhash with information that we are going to send.
  510.         my %mail = (
  511.                 To              => "$recipient",
  512.                 From            => "$mail_from",
  513.                 Bcc             => "$mail_bcc",
  514.                 # only addresses are extracted from Bcc, real names disregarded
  515.                 Cc              => "$mail_cc",
  516.                 # Cc will appear in the header. (Bcc will not)
  517.                 Subject         => "$target seems to be outdated, please investigate",
  518.                 'X-Mailer'      => "$name $version using Mail::Sendmail version $Mail::Sendmail::VERSION",
  519.                 message         => "$message",
  520.         );
  521.  
  522.         # Add an additional header so that we can show that this is our thing.
  523.         $mail{'Honeynet.org : '} = "http://www.honeynet.org";
  524.  
  525.         # Send out the mail, if succesfull print that we did OK else
  526.         # give error.
  527.         if (sendmail %mail)
  528.         {
  529.                 print "Mail alert sent OK.\n";
  530.         }
  531.         else
  532.         {
  533.                 print "Error sending mail: $Mail::Sendmail::error \n"
  534.         }
  535. }
  536.  
  537. # And as a final action make sure we write out our configuration file.
  538. # Temporary to write out the exact config to our statistics file, later we will use this to write
  539. # down our run-time statistics into a "peristent" file.
  540.  
  541. $cfg_out->write($outfile);
  542.  
  543. # End of the script.

Tagged with:
 

Check_Honeynet v1.7

Here is Check_Honeynet v1.7

check_honeynet.pl:

PERL:
  1. #!/usr/bin/perl
  2. # $Id: check_honeynet.pl,v 1.48.2.3 2008/03/24 14:46:14 remko Exp $
  3. ###########################################################################
  4.  
  5. ###########################################################################
  6. # Copyright (C) 2005-2008, Remko Lodder <remko@FreeBSD.org>. All rights reserved.
  7. #
  8. # Redistribution and use in source and binary forms, with or without
  9. # modification, are permitted provided that the following conditions
  10. # are met:
  11. # 1. Redistributions of source code must retain the above copyright
  12. #    notice, this list of conditions and the following disclaimer.
  13. # 2. Redistributions in binary form must reproduce the above copyright
  14. #    notice, this list of conditions and the following disclaimer in the
  15. #    documentation and/or other materials provided with the distribution.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  21. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. # SUCH DAMAGE.
  28. ###########################################################################
  29.  
  30. ###########################################################################
  31. # Contributors:
  32. # Ivo Naninck, (Language)
  33. # Marc Plaisier, (Language)
  34. # Mart van de Wege, (suggested a different mailer in 2006, told me that it
  35. # should run on a high level interface as easy as possible, I discarded
  36. # the idea back then, till Richard came with a good idea).
  37. # Lance Spitzner (the most valueable feedback regarding the script).
  38. # Richard Arends (suggested the actual perl mailer; and gave a good example
  39. # on how to use the module)
  40. # Robert Blacquiere (showed me Simple::Config, which I am using now to
  41. # obtain configuration informatin, as well as write statistics to a
  42. # temporary file)
  43. #
  44. # Script:
  45. # This is a stand alone script written for honeynet.org. It's purpose is
  46. # to check the listed mirrors to see which one is outdated and notify
  47. # the administrator of the outdated mirror if needed. This way the
  48. # mirrors will always be within a certain timeframe and can be removed
  49. # if they are too outdated.
  50. #
  51. # A while ago Mart vd Wege told me that a higher level mail module would be
  52. # much easier to cope with. This had been implemented as of version 1.6.2
  53. #
  54. # Written in colaboration with Lance Spitzner <lance@honeynet.org>
  55. ###########################################################################
  56.  
  57. ###########################################################################
  58. # Differences between releases, started this between 1.5 and 1.6 sorry
  59. # for the loss of potential usefull information (although I might be able
  60. # to retrieve the missing data from my CVS branches).
  61. # Note that all the three version based versions are just bugfixes to some
  62. # degree.
  63. # Version       Who             What
  64. # 1.1           Remko           Initial script to check the mirrors.
  65. # 1.1->1.2      Remko
  66. # 1.2->1.3      Remko
  67. # 1.3->1.4      Remko
  68. # 1.4->1.5      Remko           Code cleanups, restructure of code; corrected
  69. #                               some bugs between various releases spotted
  70. #                               by Lance.
  71. # 1.5->1.6      Remko           Cleanups, changed structure for timestamp
  72. #                               retrieval; make it human readable and match
  73. #                               on a specific pattern. Made the version dependend
  74. #                               on the configuration version and visa-versa
  75. #                               to be able to make big config changes.
  76. #                               BF-1: Fix the email send options by using the
  77. #                                     correct Net::SMTP commands.
  78. #                               BF-1: Fix the parsing of the new mirrorprobe
  79. #                                     layout.
  80. #                               BF-2: Change the Mailer used to send out the
  81. #                                     report.
  82. # 1.6->1.7      Remko           Implement Config::Simple, makes configuration
  83. #                               much easier!
  84. ###########################################################################
  85.  
  86. use strict;
  87. use warnings;
  88. use LWP::Simple;
  89. use Getopt::Std;
  90. use Mail::Sendmail;
  91. use Config::Simple;
  92.  
  93. ###########################################################################
  94. # variables. All configurable options are defined below. Please adjust them
  95. # to your need.
  96. ###########################################################################
  97.  
  98. # Hash to store our entire configuration in.
  99. my %CONFIG              = ();
  100.  
  101. # create the option hash, we will use that later to add our option flags.
  102. my %option              = ();
  103.  
  104. # Template some standard variables
  105. my ($CONFIGFILE, $status, $reporthost, $timestamp,$target, @MIRRORS, $enable_mail, $cfg);
  106.  
  107. # Prototype functions
  108. sub fetch_data ($$);
  109. sub email_report ($$);
  110. sub convert_input ($);
  111. sub process_mirrors (@);
  112. sub create_timestamp ($);
  113.  
  114. # Version, author and script specific behaviour
  115. my $author              = 'Remko Lodder <remko@FreeBSD.org>';   # Name of the author, respect the license.
  116. my $name                = __FILE__;                             # Our scriptname.
  117. my $MAJOR               = '1';                                  # Our major version number
  118. my $MINOR               = '7';                                  # Our minor version number
  119. my $PATCHLEVEL          = '0';                                  # Our patchlevel
  120. my $version             = "$MAJOR.$MINOR.$PATCHLEVEL";          # Our version.
  121.  
  122. ###########################################################################
  123. # Do not edit anything below this line unless you know what you are doing.
  124. ###########################################################################
  125.  
  126. getopts("cC:f:F:hpR:t", \%option);
  127.  
  128. my $config_flag   = 1 if $option{f};
  129. my $config_option = $option{f};
  130.  
  131. my $create_flag   = 1 if $option{c};
  132. my $help_flag     = 1 if $option{h};
  133. my $process_flag  = 1 if $option{p};
  134. my $test_flag     = 1 if $option{t};
  135. my $convert_flag  = 1 if $option{C};
  136. my $fetch_flag    = 1 if $option{F};
  137. my $retrieve_flag = 1 if $option{R};
  138.  
  139. # Simply assign the contents of the configuration parameter to the
  140. # configuration file variable, otherwise overrule it with the
  141. # default value
  142.  
  143. $CONFIGFILE = $config_option || "./honeynet.cf";
  144.  
  145. $cfg = new Config::Simple($CONFIGFILE);
  146.  
  147. %CONFIG = $cfg->vars();
  148. @MIRRORS = $cfg->param('CONFIG.mirrors');
  149.  
  150. $enable_mail = $cfg->param('CONFIG.enable_mail');
  151.  
  152. # Temporary to write out the exact config to our statistics file, later we will use this to write
  153. # down our run-time statistics into a "peristent" file.
  154. $cfg->write($cfg->param('CONFIG.statisticsfile'));
  155.  
  156. # Make sure that there us a version statement in the configuration file, so that we can see whether we are
  157. # compabible or not.
  158.  
  159. if (!$cfg->param('CONFIG.version'))
  160. {
  161.         print "It appears that you do not have a version statement in your configuration file. This means that the version you are using now is
  162. too old, make sure that you obtain the latest one and update that to your needs.";
  163.         exit(1);
  164. }
  165.  
  166. if ($cfg->param('CONFIG.version'))
  167. {
  168.         my($version_def_major,$version_def_minor) = $cfg->param('CONFIG.version') =~ /(\d+)\.(\d+)/;
  169.  
  170.         # the script can defer between MAJOR and MINOR releases; bugfixes aka patchlevels are
  171.         # not affected by this and can thus be ignored.
  172.         # TODO: This check should be made more flexible in the future, version 1.4 and 1.5 share
  173.         # the same configuration file and should both pass.
  174.  
  175.         if(($version_def_major lt $MAJOR) or ($version_def_minor lt $MINOR))
  176.         {
  177.                 print "You appear to be using an older configuration file that might not be compatible with the current version of the
  178. script, please validate that you have the latest options included and copy over the version statement from the latest available configuration
  179. file. Make sure that the old version statement is overwritten!
  180. The current script runs on version: $version, while the configuration is for version $cfg->param('CONFIG.version')\n";
  181.                 exit(1);
  182.         }
  183. }
  184.  
  185. # Create a new timestamp that will be fed into the mirrors, which we can use to test the
  186. # age of the mirror.
  187.  
  188. if ($create_flag) {
  189.         create_timestamp($cfg->param('CONFIG.probefile'));
  190. }
  191.  
  192. elsif ($process_flag) {
  193.         # Process the mirrors using the hash we have for them.
  194.         process_mirrors(@MIRRORS);
  195. }
  196.  
  197. # test mode, printout information on screen.
  198. elsif($test_flag)
  199. {
  200.         # In test mode we dont send out emails.
  201.         $enable_mail = 0;
  202.  
  203.         print("$name: Starting\n");
  204.         print("$name: Processing mirrors\n");
  205.  
  206.         # Process the mirrors using the hash we have for them.
  207.         process_mirrors(@MIRRORS);
  208.  
  209.         print("$name: Finishing\n");
  210. }
  211.  
  212. # convert input from unixtime to human readable time.
  213. elsif($convert_flag)
  214. {
  215.         print "$option{C} resolves to " . convert_input($option{C}) . "\n";
  216. }
  217.  
  218. # fetch the mirrorprobe file from the given host
  219. elsif($fetch_flag)
  220. {
  221.         my $result = fetch_data($option{F}, $cfg->param('CONFIG.sourcefile'));
  222.         open(OUT, "> $cfg->param('CONFIG.outdir')/$option{F}.timestamp");
  223.                 print OUT $result;
  224.         close(OUT);
  225. }
  226.  
  227. # Fetch the mirror timestamp and parse it. Print the output back on the screen.
  228. elsif($retrieve_flag)
  229. {
  230.         my $result = fetch_data($option{R}, $cfg->param('CONFIG.sourcefile'));
  231.         print("$option{R} was last modified " . convert_input($result) . "\n");
  232. }
  233.  
  234. # People expect a help option, provide it for them.
  235. elsif ($help_flag)
  236. {
  237.         print_help();
  238. }
  239.  
  240. # No valid options had been given, fallback to the help information.
  241. else
  242. {
  243.         print_help();
  244. }
  245.  
  246. sub print_help
  247. {
  248.         print("Usage:\t$name [ -c ] [ -C <value> ] [ -f <configurationfile> ] [ -F <host> ] [ -h ] [ -p ] [ -R <host> ] [ -t ]
  249. \t-c\tCreate the timestamp for the localmachine. This timestamp can be used to determine when the mirror was last updated.
  250. \t-C\t<value> converts the unix timestamp to human readable format
  251. \t-f\t<filename> Use the specified configuration file
  252. \t-F\t<host> fetch the timestamp for an external host, for example: www.honeynet.nl
  253. \t-h\tprint this help.
  254. \t-p\tCheck the status of the mirrors, and report the output to us
  255. \t-t\tTest mode, does not send out emails, but prints the information on the screen.
  256. Version: $version
  257. Originally written by Remko Lodder <remko\@FreeBSD.org, for the honeynet project.\n");
  258. }
  259.  
  260. sub create_timestamp ($)
  261. {
  262.         my $probefile = shift;
  263.         open(F_OUT, "> $probefile");
  264.                 print F_OUT "Mirrorprobe time: " . time() . "
  265. Local time: " . convert_input(time());
  266.         close F_OUT;
  267. }
  268.  
  269. sub convert_input ($)
  270. {
  271.         my $output      = scalar localtime(shift);
  272.         return $output;
  273. }
  274.  
  275. sub fetch_data ($$)
  276. {
  277.         my $source      = shift;
  278.         my $sourcefile  = shift;
  279.  
  280.         my $return_data = ();
  281.         my $data        = get("http://$source$sourcefile");
  282.  
  283.         # IF the remote data is present, take out the numberic time value and return that
  284.         # ELSE obscure the data, which will revert to 1969/1970 (depending on what the machine
  285.         # considers EPOCH).
  286.         if ($data)
  287.         {
  288.                 chomp $data;
  289.  
  290.                 $return_data = $data;
  291.                 $return_data =~ s/\n/\ /;
  292.                 if ($return_data =~ /\S+ \S+ (\d+) \S+/)
  293.                 {
  294.                         $return_data = $1;
  295.                 }
  296.                 return $return_data;
  297.         }
  298.  
  299.         else
  300.         {
  301.                 $data = 0;
  302.                 return $data;
  303.         }
  304. }
  305.  
  306. sub process_mirrors (@) {
  307.         my %mirror_time;
  308.         my @mirror_list = @_;
  309.  
  310.         for my $target(@mirror_list)
  311.         {
  312.                 $mirror_time{$target} = fetch_data($target,$cfg->param('CONFIG.sourcefile'));
  313.  
  314.                 # We should probably dont need to use this since it is implied in the routine itself.
  315.                 if(!$mirror_time{$target})
  316.                 {
  317.                         $mirror_time{$target} = 0;
  318.                 }
  319.  
  320.                 # declare our local time before continueing.
  321.                 my $honeynet_ctime      = time();
  322.                 my $mirror_ctime        = $mirror_time{$target};
  323.                 my $mirror_difftime     = $honeynet_ctime - $mirror_time{$target};
  324.  
  325.                 # If the resulting number is less then zero, the remote host is outdated.
  326.                 my $mirror_timediff     = $cfg->param('CONFIG.timeout') - $mirror_difftime;
  327.  
  328.                 if ($mirror_timediff gt "0")
  329.                 {
  330.                         if($cfg->param('CONFIG.verbose') ne "0")
  331.                         {
  332.                                 $status = "OK";
  333.                                 $timestamp = scalar localtime($mirror_time{$target});
  334.                                 $reporthost = $target;
  335.                                 write;
  336.                         }
  337.                                 next;
  338.                 }
  339.                 else
  340.                 {
  341.                         # The email option is enabled and we found an outdated mirror
  342.                         # jump to the email_report function.
  343.  
  344.                         if($enable_mail)
  345.                         {
  346.                                 email_report($target,$mirror_time{$target});
  347.                         }
  348.  
  349.                         if($cfg->param('CONFIG.verbose') ne "0")
  350.                         {
  351.                                 $status = "FAIL";
  352.                                 $timestamp = scalar localtime($mirror_time{$target});
  353.  
  354.                                 # Only override if the message has the old timestamp and thus is broken.
  355.                                 if($timestamp =~ /19[6-7]\d/)
  356.                                 {
  357.                                         $timestamp = "Mirrorprobe file problems!";
  358.                                 }
  359.                                 $reporthost = $target;
  360.                                 write;
  361.                         }
  362.                 }
  363.         }
  364.  
  365. format STDOUT_TOP =
  366. ----------------------------------------------------------------------------
  367. --------------------------- Honeynet Check results -------------------------
  368. ----------------------------------------------------------------------------
  369. Status  Site                                    Last changed
  370. .
  371.  
  372. format STDOUT =
  373. @<<<<  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<<<<<<<<<<<<
  374. $status, $reporthost,                           $timestamp
  375. .
  376. }
  377.  
  378. sub email_report ($$)
  379. {
  380.         my $status      = ();
  381.         my $target      = shift;
  382.         my $mirror_time = shift;
  383.         my $recipient   = $cfg->param("MIRRORS.$target") || "$cfg->param('CONFIG.ccaddr')";
  384.  
  385.         # Make the mirror time a human parseable time, if this matches the beginning of time
  386.         # (For computers at least). Tell that there is a problem.
  387.         $mirror_time    = scalar localtime($mirror_time);
  388.         if ($mirror_time =~ /19[6-7]\d/)
  389.         {
  390.                 $status = "Your mirror seems to have troubles fetching the mirrorprobe file.";
  391.         }
  392.         else
  393.         {
  394.                 $status = "At this moment it seems that your mirror was last updated on $mirror_time.";
  395.         }
  396.  
  397.         my $message = "Hello $recipient,
  398. You are recieving this email because your Honeynet Project mirror ($target) seems to be outdated.
  399. $status
  400. Could you please check whether everything is working as expected?
  401. If there is something wrong or you do no longer wish to be a mirror, please notify $cfg->param('CONFIG.mirroradmin')
  402. Thanks for supporting the Honeynet Project!
  403. If you have questions or concerts, please do not hesitate to contact us!
  404. --
  405. The Honeynet Project Mirror Admins";
  406.  
  407.         my %mail = (
  408.                 To              => "$recipient",
  409.                 From            => "$cfg->param('CONFIG.fromaddr')",
  410.                 Bcc             => "$cfg->param('CONFIG.ccaddr')",
  411.                 # only addresses are extracted from Bcc, real names disregarded
  412.                 Cc              => "$cfg->param('CONFIG.mirroradmin')",
  413.                 # Cc will appear in the header. (Bcc will not)
  414.                 Subject         => "$target seems to be outdated, please investigate",
  415.                 'X-Mailer'      => "$name $version using Mail::Sendmail version $Mail::Sendmail::VERSION",
  416.                 message         => "$message",
  417.         );
  418.  
  419.         $mail{'Honeynet.org : '} = "http://www.honeynet.org";
  420.  
  421.         if (sendmail %mail)
  422.         {
  423.                 print "Mail alert sent OK.\n";
  424.         }
  425.         else
  426.         {
  427.                 print "Error sending mail: $Mail::Sendmail::error \n"
  428.         }
  429. }

configuration file:

PERL:
  1. # $Id: honeynet.cf,v 1.24 2008/03/24 11:36:29 remko Exp $
  2. #
  3. # Used to automate the checking of Honeynet Project website mirrors.
  4. #
  5. # Config last updated 14 June, 2006
  6. #
  7. #
  8. [CONFIG]
  9. # Version information to see whether the current script can run with the
  10. # current configuration file. Do note that this has three digits to match
  11. # the least available update, normally this should only be matched on the
  12. # second version because of dramatic changes, but you never know :)
  13. version = 1.7
  14.  
  15. # Misc config, site settings, location of the probe file and the local path to the
  16. # probe file.
  17. source = http://www.honeynet.org
  18. sourcefile = /misc/mirrorprobe.txt
  19. probefile = /var/www/html/misc/mirrorprobe.txt
  20. # Time is 10 days. (Seconds).
  21. timeout = 864000
  22. # Settings regarding output and details on screen.
  23. verbose = 1
  24. statisticsfile = ./honeynet-statistics.cf
  25.  
  26. # Mail config
  27. enable_mail = 1
  28. # The email addresses of the administrator(s).
  29. mirroradmin = Lance Spitzner <lance@honeynet.org>
  30. fromaddr = Hostmaster <hostmaster@honeynet.org>
  31. ccaddr = Remko Lodder <remko@elvandar.org>
  32. mirrors = honeynet.lss.hr, honeynet.startx.fr, honeynet.fh.net, honeynet.securityinfos.com, www.honeynet.nl
  33.  
  34. # Mirror details
  35. [MIRRORS]
  36. www.honeynet.nl = remko@elvandar.org

 

We released another version for the Honeynet check script. It includes a better reporting template, reporting when the mirrorprobe file fetch failed; some style cleanups and some few feature changes. Checkout the file below to obtain more information. You can also request a ''diff'' file from me to update your local version (use the contactform for that, or normalise the email address in the script) (more...)

 

honeynet mirror check script v1.3

The lacking features of v1.2 had been integrated into v1.3, we now support a configuration file not only for the configureable items but also for the listed mirrors. You can now easily define the mirrors and their administrators which should give you much more flexibility. You can see the script down here, included is a sample configuration file with the configureable options. Comments? Please let me know!

#!/usr/bin/perl
###########################################################################
# $Id: check_honeynet.pl,v 1.8 2006/02/20 07:40:25 remko Exp $
###########################################################################

###########################################################################
# Copyright (C) 2005, Remko Lodder <remko @ FreeBSD.org>. All rights reserved.
# Copyright (C) 2006, Remko Lodder <remko @ FreeBSD.org>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# Contributors:
# Ivo Naninck,
# Marc Plaisier,
# Mart van de Wege
#
# Script:
# This is a stand alone script written for honeynet.org. It's purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
#
# Mart van de Wege recently told me that it would be nice to have a
# higher level mail module.  I do not want to do so because i think
# this script should be as low level as possible, requiring as less
# modules as possible.  Making it easier to run this on various
# machines without needing to install the entire CPAN to function.
#
# Written in colaboration with Lance Spitzner <lance @ honeynet.org>
###########################################################################

use strict;
use warnings;
use Net::SMTP;
use Getopt::Std;
use LWP::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# create two hashes which can be used to read our config variables from the
# configuration file. Devided between configuration items and mirror
# information.

my %CONFIG              = ();
my %MIRRORS             = ();

# create the option hash, we will use that later to add our option flags.
my %option              = ();

# Version, author and script specific behaviour
my $CONFIGFILE          = "./honeynet.cf";
my $author              = 'Remko Lodder <remko @ FreeBSD.org>';           # Name of the author, respect the license.
my $name                = 'check_honeynet.pl';                          # Our scriptname.
my $version             = '1.3';                                        # Our version.
my $honeynet_ctime      = time();

###########################################################################
# Do not edit anything below this line unless you know what you are doing.
###########################################################################

# Read the configuration before we will use anything else.
open (CONF, "< $CONFIGFILE") || die "Unable to open $CONFIGFILE: $!\n";

my ($config,$mirrors);

while (<CONF>) {
        chomp;
        if ( /\[CONFIG\]/ )
        {
                $config = 1;
                $mirrors = 0;
                next;
        }

        if ( /\[MIRRORS\]/ )
        {
                $config = 0;
                $mirrors = 1;
                next;
        }

        s/#.*//;
        s/^\s+//;
        s/\s+$//;
        next unless length;
        my ($var, $value) = split(/\s*=\s*/, $_, 2);

        if ( $config eq "1" )
        {
                $CONFIG{$var} = $value;
        }

        elsif ( $mirrors eq "1" )
        {
                $MIRRORS{$var} = $value;
        }

        else
        {
                print "It seems that your configurationfile is empty, please investigate\n";
        }
}
close CONF;

getopts("chpt", \%option);

if ($option{c})
{
        if (defined $CONFIG{verbose})
        {
                writeln("$name: Starting");
                writeln("$name: Writing timestamp");
        }

        create_timestamp($CONFIG{probefile});

        if (defined $CONFIG{verbose})
        {
                writeln("$name: Finishing");
        }
}

elsif ($option{p})
{
        if (defined $CONFIG{verbose})
        {
                writeln("$name: Starting");
                writeln("$name: Processing mirrors");
        }

        process_mirrors(%MIRRORS);

        if (defined $CONFIG{verbose})
        {
                writeln("$name: Finishing");
        }
}

# test mode, printout information on screen.
elsif ($option{t})
{
        $CONFIG{enable_mail} = 0;
        writeln("$name: Starting");
        writeln("$name: Processing mirrors");
        process_mirrors(%MIRRORS);
        writeln("$name: Finishing");
}

# People expect a help option, provide it for them.
elsif ($option{h})
{
        print_help();
}
# No valid options had been given, fallback to the help
# information.
else
{
        print_help();
}

sub print_help
{
        writeln("$name");
        writeln("Syntax: $name [-c | -h | -p | -t ]\n");
        writeln("-c");
        writeln("  Create the timestamp for the local machine.  This timestamp");
        writeln("  can be used to determine when the mirrors were last updated.");
        writeln("");
        writeln("-h");
        writeln("  Print this help information");
        writeln("");
        writeln("-p");
        writeln("  Check the status of the mirrors and report that status.");
        writeln("");
        writeln("-t");
        writeln("  Test mode, do not send emails but print the information on");
        writeln("  the screen. This overrides the email settings you might have");
        writeln("  set in the file");
        writeln("Version: $version");
        writeln("Originally written by: $author");
}

sub writeln
{
        # Write the string provided in the function
        my $message     = shift;
        print "$message\n";

}
sub create_timestamp
{
        my $probefile   = shift;

        open(F_OUT, "> $probefile");

        print F_OUT time();

        close F_OUT;
}

sub fetch_data
{
        my $source      = shift;
        my $sourcefile  = shift;

        my $data = get "${source}${sourcefile}";

        if ($data)
        {
                return $data;
        }
        else
        {
                # It seems we encountered an error, give an explaination of what happened
                # and exit the program with an error flag raised.
                writeln("There were problems fetching the status information from $source");
                writeln("We cannot continue right now, the problem will cause the program");
                writeln("to exit.  Please investigate this.");
                exit(1);
        }
}

sub process_mirrors
{
        my %mirror_time;
        my %mirror_list = @_;

        for my $target ( sort keys %mirror_list )
        {
                $mirror_time{$target} = fetch_data($target,$CONFIG{sourcefile});

                my $mirror_ctime        = $mirror_time{$target};
                my $mirror_difftime     = $honeynet_ctime - $mirror_ctime;

                if ($CONFIG{mirror_difftime} < $CONFIG{timeout} )
                {
                        writeln("OK: $target\t\tchanged: ");
                        print scalar localtime($mirror_ctime);
                        writeln("");
                }
                else
                {
                        # The email option is enabled and we found an outdated mirror
                        # jump to the email_report function.
                        if ($CONFIG{enable_mail})
                        {
                                email_report($target,$mirror_ctime);
                        }

                        # We do not want to send a email, print a warning instead.
                        else
                        {
                                writeln("BAD: $target\t\tchanged: ");
                                print scalar localtime($mirror_ctime);
                                writeln("");
                        }
                }
        }
}

sub email_report
{
        my $target              = shift;
        my $mirror_ctime        = shift;
        my $smtp                = Net::SMTP->new("$CONFIG{mailhost}", Hello => "$CONFIG{ehlohost}");

        $mirror_ctime           = scalar localtime($mirror_ctime);

        $smtp->to("$MIRRORS{$target}");

        $smtp->data();
        $smtp->datasend("EHLO $CONFIG{ehlohost}\r\n");
        $smtp->datasend("MAIL FROM: <$CONFIG{fromaddr}>\n");
        $smtp->datasend("RCPT TO: <$MIRRORS{$target}>\n");

        # We need to sleep a little so that all smtp servers can process the email.
        # For example: postfix complains about unauthorized pipelining when this is not defined.
        sleep(2);

        $smtp->datasend("DATA\r\n");
        $smtp->datasend("To: <$MIRRORS{$target}>\n");
        $smtp->datasend("From: $CONFIG{fromaddr}\n");
        $smtp->datasend("Subject: $target seems to be outdated, please investigate\n");
        $smtp->datasend("\n\n");
        $smtp->datasend("Hello $MIRRORS{$target},\n\n");
        $smtp->datasend("You are recieving this email because your mirror ($target) seems to be outdated.\n");
        $smtp->datasend("\n");
        $smtp->datasend("At this moment it seems that your mirror was last updated on $mirror_ctime.\n");
        $smtp->datasend("Could you please check if everything is working as expected?\n\n");
        $smtp->datasend("If there is something wrong or you do no longer wish to be a mirror, please notify $CONFIG{honeyadmin}\n\n");
        $smtp->datasend("--\n");
        $smtp->datasend("Thanks for supporting the efforts of Honeynet\n");
        $smtp->datasend("The Honeynet mirror admins\n");
        $smtp->dataend();

        $smtp->quit;
}

$ cat honeynet.cf
# $Id: honeynet.cf,v 1.3 2006/02/20 08:00:50 remko Exp $

[CONFIG]
# Misc config
source = http://www.honeynet.org
sourcefile = /misc/mirrorprobe.txt
probefile = ./mirrorprobe.txt
# Timeout is one week. (Seconds).
timeout = 604800
verbose = 1

# Mail config
enable_mail = 1
mailhost = caelis.elvandar.org
ehlohost = caelis.elvandar.org
honeyadmin = "Lance Spitzner" <lancename@honeynet.org>
fromaddr = "Remko Lodder" <myname@elvandar.org>

[MIRRORS]
http://www.evilcoder.org = youremail@elvandar.org
http://www.freebsd-nl.org = youremail@elvandar.org

 

honeynet mirror check script v1.2

After feedback and a little development, 1.2 has seen the light.

#!/usr/bin/perl
###########################################################################
# $Id: check_honeynet-evilcoder.pl,v 1.7 2006/02/10 10:59:51 remko Exp $
###########################################################################

###########################################################################
# Copyright (C) 2005, Remko Lodder <remko at FreeBSD.org>. All rights reserved.
# Copyright (C) 2006, Remko Lodder <remko at FreeBSD.org>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# Contributors:
# Ivo Naninck,
# Marc Plaisier,
# Mart van de Wege
#
# Script:
# This is a stand alone script written for honeynet.org. It's purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
#
# Mart van de Wege recently told me that it would be nice to have a
# higher level mail module.  I do not want to do so because i think
# this script should be as low level as possible, requiring as less
# modules as possible.  Making it easier to run this on various
# machines without needing to install the entire CPAN to function.
#
# Written in colaboration with Lance Spitzner <lance at honeynet.org>
###########################################################################

use strict;
use warnings;
use Net::SMTP;
use Getopt::Std;
use LWP::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# create the option hash, we will use that later to add our option flags.
my %option              = ();

# Online resources (not everything is used yet).
my $source              = 'http://www.honeynet.org';
my $sourcefile          = '/path/to/mirrorprobe.txt';
my $totalpath           = "${source}${sourcefile}";

# path to the local mirrorprobe file
my $probefile           = '/path/to/mirrorprobe.txt';

# Timeout and current time declaration
my $timeout             = 60*60*24*7;
my $honeynet_ctime      = time();

# Email settings.
my $enable_mail         = 1;
my $mailhost            = 'caelis.elvandar.org';
my $ehlohost            = "$mailhost";                                  # The EHLO host is the host used
                                                                        # for greeting the other server.
                                                                        # You can use the mailhost, or define
                                                                        # your own.

# Honeynet mirror admins.
my $honeyadmin          = '"Lance Spitzner" <lancename@honeynet.org>';
my $fromaddr            = '"Remko Lodder" <myname@elvandar.org>';       # Change me before production.

# Version, author and script specific behaviour
my $author              = 'Remko Lodder <myname@elvandar.org>';         # Name of the author, respect the license.
my $name                = 'check_honeynet.pl';                          # Our scriptname.
my $version             = '1.2';                                        # Our version.
my $verbose             = 1;                                            # Do we want to have more info when the script runs?

# Example mirror_list.
my %mirror_list = ( 'http://www.evilcoder.org'          => 'youremail@elvandar.org',
                    'http://www.freebsd-nl.org'         => 'youremail@elvandar.org'
                  );

###########################################################################
# Do not edit anything below this line unless you know what you are doing.
###########################################################################
getopts("chpt", \%option);

if ($option{c})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Writing timestamp");
        }

        create_timestamp($probefile);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}

elsif ($option{p})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Processing mirrors");
        }

        process_mirrors(%mirror_list);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}

# test mode, printout information on screen.
elsif ($option{t})
{
        my $enable_mail = 0;
        writeln("$name: Starting");
        writeln("$name: Processing mirrors");
        process_mirrors(%mirror_list);
        writeln("$name: Finishing");
}

# People expect a help option, provide it for them.
elsif ($option{h})
{
        print_help();
}
# No valid options had been given, fallback to the help
# information.
else
{
        print_help();
}

sub print_help
{
        writeln("$name");
        writeln("Syntax: $name [-c | -h | -p | -t ]\n");
        writeln("-c");
        writeln("  Create the timestamp for the local machine.  This timestamp");
        writeln("  can be used to determine when the mirrors were last updated.");
        writeln("");
        writeln("-h");
        writeln("  Print this help information");
        writeln("");
        writeln("-p");
        writeln("  Check the status of the mirrors and report that status.");
        writeln("");
        writeln("-t");
        writeln("  Test mode, do not send emails but print the information on");
        writeln("  the screen. This overrides the email settings you might have");
        writeln("  set in the file");
        writeln("Version: $version");
        writeln("Originally written by: $author");
}

sub writeln
{
        # Write the string provided in the function
        my $message     = shift;
        print "$message\n";

}
sub create_timestamp
{
        my $probefile   = shift;

        open(F_OUT, "> $probefile");

        print F_OUT time();

        close F_OUT;
}

sub fetch_data
{
        my $source      = shift;
        my $sourcefile  = shift;

        my $data = get "${source}${sourcefile}";

        if ($data)
        {
                return $data;
        }
        else
        {
                # It seems we encountered an error, give an explaination of what happened
                # and exit the program with an error flag raised.
                writeln("There were problems fetching the status information from $source");
                writeln("We cannot continue right now, the problem will cause the program");
                writeln("to exit.  Please investigate this.");
                exit(1);
        }
}

sub process_mirrors
{
        my %mirror_time;
        my %mirror_list = @_;

        for my $target ( sort keys %mirror_list )
        {
                $mirror_time{$target} = fetch_data($target,$sourcefile);

                my $mirror_ctime        = $mirror_time{$target};
                my $mirror_difftime     = $honeynet_ctime - $mirror_ctime;

                if ($mirror_difftime < $timeout )
                {
                        writeln("OK: $target\t\tchanged: ");
                        print scalar localtime($mirror_ctime);
                        writeln("");
                }
                else
                {
                        # The email option is enabled and we found an outdated mirror
                        # jump to the email_report function.
                        if ($enable_mail)
                        {
                                email_report($target,$mirror_ctime);
                        }

                        # We do not want to send a email, print a warning instead.
                        else
                        {
                                writeln("BAD: $target\t\tchanged: ");
                                print scalar localtime($mirror_ctime);
                                writeln("");
                        }
                }
        }
}

sub email_report
{
        my $target              = shift;
        my $mirror_ctime        = shift;
        my $smtp                = Net::SMTP->new("$mailhost", Hello => "$ehlohost");

        $mirror_ctime           = scalar localtime($mirror_ctime);

        $smtp->to("$mirror_list{$target}");

        $smtp->data();
        $smtp->datasend("EHLO $ehlohost\r\n");
        $smtp->datasend("MAIL FROM: <$fromaddr>\n");
        $smtp->datasend("RCPT TO: <$mirror_list{$target}>\n");

        # We need to sleep a little so that all smtp servers can process the email.
        # For example: postfix complains about unauthorized pipelining when this is not defined.
        sleep(2);

        $smtp->datasend("DATA\r\n");
        $smtp->datasend("To: <$mirror_list{$target}>\n");
        $smtp->datasend("From: $fromaddr\n");
        $smtp->datasend("Subject: $target seems to be outdated, please investigate\n");
        $smtp->datasend("\n\n");
        $smtp->datasend("Hello $mirror_list{$target},\n\n");
        $smtp->datasend("You are recieving this email because your mirror ($target) seems to be outdated.\n");
        $smtp->datasend("\n");
        $smtp->datasend("At this moment it seems that your mirror was last updated on $mirror_ctime.\n");
        $smtp->datasend("Could you please check if everything is working as expected?\n\n");
        $smtp->datasend("If there is something wrong or you do no longer wish to be a mirror, please notify $honeyadmin\n\n");
        $smtp->datasend("--\n");
        $smtp->datasend("Thanks for supporting the efforts of Honeynet\n");
        $smtp->datasend("The Honeynet mirror admins\n");
        $smtp->dataend();

        $smtp->quit;
}

 

Simple image/movie index generator

One day it became needed for me to generate the most simple index one could find to index some JPG and MOV files (yes capitals), therefor i wrote the below script (really easy). You can use it with the BSD License ofcourse.

 

#!/usr/bin/perl T

use CGI;
use warnings;
use diagnostics;
use strict;

my $CGI = new CGI;
my $file;
my $URI = "http://yourdomain/yoururl";
my $path = "/local/path/to/your/images/and/movies";
my $title = "The title of the generated index file";

opendir(DIR, $path);
my @files = grep { /\.JPG|.MOV$/ } readdir(DIR);
closedir(DIR);

print $CGI->header();
  print $CGI->start_html("$title");
    print $CGI->p({-align=>"center"}, "$title");
    print "<table width='100%'>";
      foreach $file (@files) {
        print "<tr>";
          print "<td align='center'>";
            print $CGI->a({href=>"$URI/$file"},"$file");
          print "</td>";
        print "</tr>";
      }
    print "</table>";
  print $CGI->end_html();

(more...)

 

honeynet mirror check script v1.1

There is a new version available for the honeynet check script. This script is more advanced and more developed. Licensed under the BSD license, written by remko _at_ FreeBSD dot org.

#!/usr/bin/perl -w
###########################################################################
# $Id: check_honeynet.pl,v 1.1 2006/02/05 20:07:41 remko Exp $
###########################################################################

###########################################################################
# Copyright (C) 2005, Remko Lodder <remko@FreeBSD.org>. All rights reserved.
# Copyright (C) 2006, Remko Lodder <remko@FreeBSD.org>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# This is a stand alone script written for honeynet.org. It's purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
# Written in colaboration with Lance Spitzner <lancename@honeynet.org>
###########################################################################

use strict;
use warnings;
use Net::SMTP;
use Getopt::Std;
use LWP::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# create the option hash, we will use that later to add our option flags.
my %option              = ();

# Online resources (not everything is used yet).
my $source              = 'http://www.honeynet.org';
my $sourcefile          = '/path/to/mirrorprobe.txt';
my $totalpath           = "${source}${sourcefile}";

# path to the local mirrorprobe file
my $probefile           = '/path/to/mirrorprobe.txt';

# Timeout and current time declaration
my $timeout             = 60*60*24*7;;
my $honeynet_ctime      = time();

# Email settings.
my $enable_mail         = 1;
my $mailhost            = 'caelis.elvandar.org';
my $ehlohost            = 'caelis.elvandar.org';

# Honeynet mirror admins.
my $honeyadmin          = '"Lance Spitzner" <lancename@honeynet.org>';
my $fromaddr            = '"Remko Lodder" <myname@elvandar.org>';       # Change me before production.

# Version, author and script specific behaviour
my $author              = 'Remko Lodder <myname@elvandar.org';
my $name                = 'check_honeynet.pl';
my $version             = '1.1b';
my $verbose             = 1;                                            # Enable this if you want the
                                                                        # script to ouput something at all.
# Example mirror_list.
my %mirror_list = ( 'http://www.evilcoder.org'          => 'youremail@elvandar.org',
                    'http://www.freebsd-nl.org'         => 'youremail@elvandar.org'
                  );

###########################################################################
# Do not edit anything below this line unless you know what you are doing.
###########################################################################
getopts("chp", \%option);

if ($option{c})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Writing timestamp");
        }

        create_timestamp($probefile);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}
elsif ($option{p})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Processing mirrors");
        }

        process_mirrors(%mirror_list);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}
# People expect a help option, provide it for them.
elsif ($option{h})
{
        print_help();
}
# No valid options had been given, fallback to the help
# information.
else
{
        print_help();
}

sub print_help
{
        writeln("$name");
        writeln("Syntax: $name [-c | -h | -p]\n");
        writeln("-c");
        writeln("  Create the timestamp for the local machine.  This timestamp");
        writeln("  can be used to determine when the mirrors were last updated.");
        writeln("");
        writeln("-h");
        writeln("  Print this help information");
        writeln("");
        writeln("-p");
        writeln("  Check the status of the mirrors and report that status.");
        writeln("");
        writeln("Version: $version");
        writeln("Originally written by: $author");
}

sub writeln
{
        # Write the string provided in the function
        my $message     = shift;
        print "$message\n";

}
sub create_timestamp
{
        my $probefile   = shift;

        open(F_OUT, "> $probefile");

        print F_OUT time();

        close F_OUT;
}

sub process_mirrors
{
        my %mirror_list = @_;

        check_status(%mirror_list);
}

sub fetch_data
{
        my $source      = shift;
        my $sourcefile  = shift;

        my $data = get "${source}${sourcefile}";

        if ($data)
        {
                return $data;
        }
        else
        {
                # It seems we encountered an error, give a explaination of what happened
                # and exit the program with an error flag raised.
                writeln("There were problems fetching the status information from $source");
                writeln("We cannot continue right now, the problem will cause the program");
                writeln("to exit.  Please investigate this.");
                exit(1);
        }
}

sub check_status
{
        my %mirror_time;
        my %mirror_list = @_;

        for my $target ( sort keys %mirror_list )
        {
                $mirror_time{$target} = fetch_data($target,$sourcefile);

                my $mirror_ctime        = $mirror_time{$target};
                my $mirror_difftime     = $honeynet_ctime - $mirror_ctime;

                if ($mirror_difftime < $timeout )
                {
                        writeln("OK: $target\t\tchanged: ");
                        print scalar localtime($mirror_ctime);
                        writeln("");
                }
                else
                {
                        # The email option is enabled and we found an outdated mirror
                        # jump to the email_report function.
                        if ($enable_mail)
                        {
                                email_report($target,$mirror_ctime);
                        }

                        # We do not want to send a email, print a warning instead.
                        else
                        {
                                writeln("BAD: $target\t\tchanged: ");
                                print scalar localtime($mirror_ctime);
                                writeln("");
                        }
                }
        }
}

sub email_report
{
        my $target              = shift;
        my $mirror_ctime        = shift;
        my $smtp                = Net::SMTP->new("$mailhost", Hello => "$ehlohost");

        $mirror_ctime           = scalar localtime($mirror_ctime);

        $smtp->to("$mirror_list{$target}");

        $smtp->data();
        $smtp->datasend("EHLO $ehlohost\r\n");
        $smtp->datasend("MAIL FROM: <$fromaddr>\n");
        $smtp->datasend("RCPT TO: <$mirror_list{$target}>\n");

        # We need to sleep a little so that all smtp servers can process the email.
        # For example: postfix complains about unauthorized pipelining when this is not defined.
        sleep(2);

        $smtp->datasend("DATA\r\n");
        $smtp->datasend("To: <$mirror_list{$target}>\n");
        $smtp->datasend("From: $fromaddr\n");
        $smtp->datasend("Subject: $target seems to be outdated, please investigate\n");
        $smtp->datasend("\n\n");
        $smtp->datasend("Hello $mirror_list{$target},\n\n");
        $smtp->datasend("You are recieving this email because your mirror ($target) seems to be outdated.\n");
        $smtp->datasend("\n");
        $smtp->datasend("At this moment it seems that your mirror was last updated on $mirror_ctime.\n");
        $smtp->datasend("Could you please check if everything is working as expected?\n\n");
        $smtp->datasend("If there is something wrong or you do no longer wish to be a mirror, please notify $honeyadmin\n\n");
        $smtp->datasend("--\n");
        $smtp->datasend("Thanks for supporting the efforts of Honeynet\n");
        $smtp->datasend("The honeynet mirror admins\n");
        $smtp->dataend();

        $smtp->quit;
}

 

Honeynet mirror check script

As people might know, i have a mirror of the www.honeynet.org project at www.honeynet.nl. Recently Lance Spitzner and I reviewed some of the mirrors and since it takes a little time I thought it would be good if there is an automated script available.

Currently the script checks what the last modification time of the index file is (of the official server first) and then scans the other mirrors to see their last modification time. They should be the same after about an week (not sure how we can check that though).

And ofcourse since my script is BSD licensed; i attached it below (click on the read more link).

If you have suggestions on how to make the script better. Please let me know. I will also put this script in the download section and make a reference to an text file so that you can use it.

(more...)

 

dshield-preparser

If you click on the read more button you will find my preparser for dshield pf logging.
(more...)

 

PF statistics into MRTG

Below is a short little script that i wrote with some help of some FreeBSD Perl developers (Thanks mat and siks).

The script should be runned with root permissions, sudo could be used for that:

For example with the follwing information in /usr/local/etc/sudoers (or where your configfile lives)

User_Alias MRTG = mrtg
MRTG NOPASSWD: /sbin/pfctl -si

The script will run /sbin/pfctl -si which will give you statistical output which can be used for processing by mrtg after running pf.pl. Do note that the current markup might not fit on the script. Please click on the Plain text button to see the original script in a new window, which will fit.

PERL:
  1. #!/usr/bin/perl -w
  2.  
  3. # $Id: pf-to-mrtg.pl 831 2008-09-07 13:45:27Z remko $
  4. #
  5. # (c) 2005 Remko Lodder <remko@elvandar.org>
  6. # (c) 2008 Remko Lodder <remko@FreeBSD.org>
  7. # Based upon ipf.pl by Ronald Florence <ron@18james.com>
  8. # last modified remko@elvandar.org, 05 Sept 2009
  9. # Made the script working again.
  10.  
  11. # Example output from pfctl -si
  12. #Interface Stats for fxp0              IPv4             IPv6
  13. #  Bytes In                          156041                0
  14. #  Bytes Out                        1895602                0
  15. #  Packets In
  16. #    Passed                            1504                0
  17. #    Blocked                            256                0
  18. #  Packets Out
  19. #    Passed                            1756                0
  20. #    Blocked                              0                0
  21. #
  22. #State Table                          Total             Rate
  23. #  current entries                       33               
  24. #  searches                            8865           10.7/s
  25. #  inserts                              204            0.2/s
  26. #  removals                             171            0.2/s
  27. #Counters
  28. #  match                                460            0.6/s
  29. #  bad-offset                             0            0.0/s
  30. #  fragment                               0            0.0/s
  31. #  short                                  0            0.0/s
  32. #  normalize                              0            0.0/s
  33. #  memory                                 0            0.0/s
  34.  
  35. use strict;
  36. use Getopt::Std;
  37.  
  38. # prototype variables.
  39. my($inp,$outp) = 0;
  40.  
  41. my ($out,$in,$uptime,$firewall);
  42. my(@pfctl);
  43. my(%option);
  44.  
  45. # define some variables upfront
  46. my $scriptname = __FILE__;
  47. my $version = "2.0";
  48.  
  49. # Index our options
  50. getopts("bBfimMnpsS", \%option);
  51.  
  52. my $pass_flag   = 1 if $option{p};
  53. my $block_flag  = 1 if $option{b};
  54. my $bytes_flag  = 1 if $option{B};
  55. my $state_flag  = 1 if $option{s};
  56. my $search_flag = 1 if $option{S};
  57. my $inres_flag  = 1 if $option{i};
  58. my $match_flag  = 1 if $option{m};
  59. my $frag_flag   = 1 if $option{f};
  60. my $short_flag  = 1 if $option{n};
  61. my $memory_flag = 1 if $option{M};
  62.  
  63. @pfctl=`/sbin/pfctl -si`;
  64.  
  65. foreach my $packetfilter (@pfctl) {
  66.         if ($pass_flag || $block_flag) {
  67.                 if ($packetfilter =~ /Packets In/) { $in = 1; $out = 0; }
  68.                 if ($packetfilter =~ /Packets Out/) { $in = 0; $out = 1; }
  69.                 if ($pass_flag) {
  70.                         if ($packetfilter =~ /Passed\s+(\d+)/) { if ($in) { $inp += $1; } }
  71.                         if ($packetfilter =~ /Passed\s+(\d+)/) { if ($out) { $outp += $1; } }
  72.                 }
  73.                 if ($block_flag) {
  74.                         if ($packetfilter =~ /Blocked\s+(\d+)/) { if ($in) { $inp += $1; } }
  75.                         if ($packetfilter =~ /Blocked\s+(\d+)/) { if ($out) { $outp += $1; } }
  76.                 }
  77.         }
  78.  
  79.         elsif ($bytes_flag) {
  80.                 if ($packetfilter =~ /Bytes\sIn\s+(\d+)/)  { $inp += $1; }
  81.                 if ($packetfilter =~ /Bytes\sOut\s+(\d+)/) { $outp += $1; }
  82.         }
  83.         elsif ($state_flag) {
  84.                 if ($packetfilter =~ /current entries\s+(\d+)/) { $inp += $1 }
  85.                 $outp = 0;
  86.         }
  87.         elsif ($search_flag) {
  88.                 if ($packetfilter =~ /searches\s+(\d+)/) { $inp += $1 }
  89.                 if ($packetfilter =~ /searches\s+\d+\s+(\d+)/) { $outp += $1 }
  90.         }
  91.         elsif ($inres_flag) {
  92.                 if ($packetfilter =~ /inserts\s+(\d+)/) { $inp += $1 }
  93.                 if ($packetfilter =~ /removals\s+(\d+)/) { $outp += $1 }
  94.         }
  95.         elsif ($match_flag) {
  96.                 if ($packetfilter =~ /match\s+(\d+)/) { $inp += $1 }
  97.                 if ($packetfilter =~ /match\s+\d+\s+(\d+)/) { $outp += $1 }
  98.         }
  99.         elsif ($frag_flag) {
  100.                 if ($packetfilter =~ /bad-offset\s+(\d+)/) { $inp += $1 }
  101.                 if ($packetfilter =~ /fragment\s+(\d+)/) { $outp += $1 }
  102.         }
  103.         elsif ($short_flag) {
  104.                 if ($packetfilter =~ /short\s+(\d+)/) { $inp += $1 }
  105.                 if ($packetfilter =~ /normalize\s+(\d+)/) { $outp += $1 }
  106.         }
  107.         elsif ($memory_flag) {
  108.                 if ($packetfilter =~ /memory\s+(\d+)/) { $inp += $1 }
  109.                 if ($packetfilter =~ /memory\s+\d+\s+(\d+)/) { $outp += $1 }
  110.         }
  111.         else {
  112.                 print("Usage:\t$scriptname [ -b ] [ -B ] [ -f ] [ -i ] [ -m ] [ -M ] [ -n ] [ -p ] [ -s ] [ -S ]
  113. \t-b\tIndex blocked packets incoming and outgoing.
  114. \t-B\tIndex bytes incoming and outgoing
  115. \t-f\tIndex bad-offsets and fragments
  116. \t-i\tIndex inserts and removals
  117. \t-m\tIndex matched packets current values and usage rate
  118. \t-M\tIndex memory usage current values and usage rate
  119. \t-n\tIndex short packets and normalized packets
  120. \t-p\tIndex passed packets incoming and outgoing.
  121. \t-s\tIndex states other value will be zero (0)
  122. \t-S\tIndex searches current searches and search rate
  123. Version: $version
  124. Originally written by Remko Lodder <remko\@FreeBSD.org>.\n");
  125.                 exit(1);
  126.         }
  127. }
  128.  
  129. print "$inp\n",
  130.       "$outp\n";
  131.  
  132. $_ = `/usr/bin/uptime`;
  133. ($uptime) = /up\s+(.*),\s+.+user/;
  134. $uptime =~ s/(^1\s+day)\s/1/;
  135.  
  136. chop($firewall = `uname -nm`);
  137. print "$uptime\n",
  138.  
  139. __END__
  140.  
  141. =head1 NAME
  142.  
  143.   pf-to-mrtg.pl -  generates statistics for use with MRTG
  144.  
  145. =head1 SYNOPSIS
  146.  
  147.   Two example configuration options for MRTG:
  148.  
  149.   Target[connections]: `/path/to/pf-to-mrtg.pl -p`
  150.   Options[connections]: growright, perhour
  151.   MaxBytes[connections]: 50000
  152.   Title[connections]: Firewall Connections
  153.   PageTop[connections]: <h3>Firewall Connections</h3>
  154.   YLegend[connections]: packets/hr
  155.   ShortLegend[connections]: pkts/h
  156.   Legend1[connections]: Incoming Connections
  157.   Legend2[connections]: Outgoing Connections
  158.  
  159.   Target[state]: `/path/to/pf-to-mrtg.pl -s`
  160.   Options[state]: growright, gauge, integer
  161.   MaxBytes[state]: 2048
  162.   Title[state]: State Table
  163.   PageTop[state]: <h3>NAT &amp; IP state tables</h3>
  164.   YLegend[state]: states
  165.   ShortLegend[state]: states
  166.   Legend1[state]: NAT states
  167.   Legend2[state]: IP states
  168.   LegendI[state]: nat:
  169.   LegendO[state]: ip:
  170.  
  171.   Other available targets are `pf-to-mrtg.pl -b`
  172.                               `pf-to-mrtg.pl -B`
  173.                               `pf-to-mrtg.pl -f`
  174.                               `pf-to-mrtg.pl -i`
  175.                               `pf-to-mrtg.pl -m`
  176.                               `pf-to-mrtg.pl -M`
  177.                               `pf-to-mrtg.pl -n`
  178.                               `pf-to-mrtg.pl -p`
  179.                               `pf-to-mrtg.pl -s`
  180.                               `pf-to-mrtg.pl -S`
  181.  
  182.   See the instructions in the help to see what they represent.
  183.  
  184. =head1 DESCRIPTION
  185.  
  186.     The purpose of this script is to be able to create statistics
  187.     from various PF counters.  By using this script you will be
  188.     able to see what your firewall does, how it behaves, and see
  189.     trends.  Note: Due to MRTG's nature you will get spikes after
  190.     rebooting the machine.
  191. =head1 LICENSE
  192.     This module is licensed under the BSD license.
  193. =head1 AUTHOR
  194.     Remko Lodder <remko@FreeBSD.org> with additional help from
  195.     Mattieu Arnold <mat@FreeBSD.org> and Pasi Hirvonen.
  196.     Originally based on work from Ron James (before this was entirely rewritten).
  197. =cut

 
Page 1 of 3123
© 2003-2010 Evilcoder.org
Bear