comparison maltfilter @ 83:532169789f52 maltfilter-0.19.0

Add automatic temporary suspension of DroneBL submissions if enough HTTP connection or other errors occur (thresholds and suspension time can be set in configuration file.)
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 30 Aug 2009 01:47:40 +0300
parents 4e3f87470426
children 4362bf9e52e4
comparison
equal deleted inserted replaced
82:0c9d8dc3f70c 83:532169789f52
11 use Net::IP; 11 use Net::IP;
12 use Net::DNS; 12 use Net::DNS;
13 use LWP::UserAgent; 13 use LWP::UserAgent;
14 use IO::Seekable; 14 use IO::Seekable;
15 15
16 my $progversion = "0.18.1"; 16 my $progversion = "0.19.0";
17 my $progbanner = 17 my $progbanner =
18 "Malicious Attack Livid Termination Filter daemon (maltfilter) v$progversion\n". 18 "Malicious Attack Livid Termination Filter daemon (maltfilter) v$progversion\n".
19 "Programmed by Matti 'ccr' Hamalainen <ccr\@tnsp.org>\n". 19 "Programmed by Matti 'ccr' Hamalainen <ccr\@tnsp.org>\n".
20 "(C) Copyright 2009 Tecnic Software productions (TNSP)\n"; 20 "(C) Copyright 2009 Tecnic Software productions (TNSP)\n";
21 21
59 "DRONEBL" => 0, 59 "DRONEBL" => 0,
60 "DRONEBL_THRESHOLD" => 5, 60 "DRONEBL_THRESHOLD" => 5,
61 "DRONEBL_MAX_AGE" => 30, # in minutes 61 "DRONEBL_MAX_AGE" => 30, # in minutes
62 "DRONEBL_RPC_URI" => "http://dronebl.org/RPC2", 62 "DRONEBL_RPC_URI" => "http://dronebl.org/RPC2",
63 "DRONEBL_RPC_KEY" => "", 63 "DRONEBL_RPC_KEY" => "",
64 "DRONEBL_MAX_ERRORS" => 5,
65 "DRONEBL_SUSPEND" => 10,
64 ); 66 );
65 67
66 # List loopback and private netblocks by default here 68 # List loopback and private netblocks by default here
67 my @noaction_ips_def = ( 69 my @noaction_ips_def = (
68 "127.0.0.0/8", 70 "127.0.0.0/8",
175 177
176 178
177 ############################################################################# 179 #############################################################################
178 ### Status output functionality 180 ### Status output functionality
179 ############################################################################# 181 #############################################################################
180 sub urlencode($) 182 ## Return string expressing given UNIX timestamp or "?" if not valid
181 {
182 my $value = $_[0];
183 $value =~ s/([^a-zA-Z_0-9 ])/"%" . uc(sprintf "%lx" , unpack("C", $1))/eg;
184 $value =~ tr/ /+/;
185 return $value;
186 }
187
188 my %entities = (
189 "<" => "lt",
190 ">" => "gt",
191 "&" => "amp",
192 );
193
194 sub htmlentities($)
195 {
196 my $value = $_[0];
197 # $value =~ s/([keys %entities])/"&".$entities{$1}.";"/eg;
198 foreach my $val (keys %entities) {
199 $value =~ s/$val/\&$entities{$val}\;/g;
200 }
201 return $value;
202 }
203
204 sub get_time_str($) 183 sub get_time_str($)
205 { 184 {
206 if ($_[0] >= 0) { 185 return ($_[0] >= 0) ? (scalar localtime($_[0])) : "?";
207 return scalar localtime($_[0]); 186 }
208 } else { 187
209 return "?"; 188 ## Return string expressing how long ago given UNIX timestamp is from current time
210 }
211 }
212
213 my @paskat = (30*24*60*60, 7*24*60*60, 24*60*60, 60*60, 60); 189 my @paskat = (30*24*60*60, 7*24*60*60, 24*60*60, 60*60, 60);
214 my @opaskat = ("months", "weeks", "days", "hours", "minutes"); 190 my @opaskat = ("months", "weeks", "days", "hours", "minutes");
215 my @upaskat = ("month", "week", "day", "hour", "minute"); 191 my @upaskat = ("month", "week", "day", "hour", "minute");
216 192
217 sub get_ago_str($) 193 sub get_ago_str($)
236 return $str." ago"; 212 return $str." ago";
237 } else { 213 } else {
238 return "?"; 214 return "?";
239 } 215 }
240 } 216 }
217
218 ## Convert non-alphanumeric characters in strong to hex-coded URI style
219 sub urlencode($)
220 {
221 my $value = $_[0];
222 $value =~ s/([^a-zA-Z_0-9 ])/"%" . uc(sprintf "%lx" , unpack("C", $1))/eg;
223 $value =~ tr/ /+/;
224 return $value;
225 }
226
227 my %entities = (
228 "<" => "lt",
229 ">" => "gt",
230 "&" => "amp",
231 );
232
233 ## Convert special characters to HTML/XML entities
234 sub htmlentities($)
235 {
236 my $value = $_[0];
237 $value =~ s/$_/\&$entities{$_}\;/g foreach (keys %entities);
238 return $value;
239 }
240
241 241
242 sub printH($$$$) 242 sub printH($$$$)
243 { 243 {
244 my $fh = $_[1]; 244 my $fh = $_[1];
245 if ($_[0]) { 245 if ($_[0]) {
523 523
524 524
525 ############################################################################# 525 #############################################################################
526 ### DroneBL submission support 526 ### DroneBL submission support
527 ############################################################################# 527 #############################################################################
528 my $dronebl_errors = 0;
529 my $dronebl_suspend = 0;
530
528 sub dronebl_process 531 sub dronebl_process
529 { 532 {
533 return if ($dronebl_suspend-- > 0);
530 return unless ($settings{"DRONEBL"} > 0); 534 return unless ($settings{"DRONEBL"} > 0);
531 535
532 # Create submission data 536 # Create submission data
533 my $xml = "<?xml version=\"1.0\"?>\n<request key=\"".$settings{"DRONEBL_RPC_KEY"}."\">\n"; 537 my $xml = "<?xml version=\"1.0\"?>\n<request key=\"".$settings{"DRONEBL_RPC_KEY"}."\">\n";
534 my $entries = 0; 538 my $entries = 0;
535 while (my ($ip, $entry) = each(%dronebl)) { 539 while (my ($ip, $entry) = each(%dronebl)) {
536 if ($entry->{"sent"} == 0 && $entry->{"tries"} < 3) { 540 if ($entry->{"sent"} == 0 && $entry->{"tries"} < 3) {
537 # $xml .= "<add ip=\"".$ip."\" type=\"".$entry->{"type"}."\" />\n"; 541 $xml .= "<add ip=\"".$ip."\" type=\"".$entry->{"type"}."\" />\n";
538 $xml .= "<add ip=\"".$ip."\" type=\"1\" />\n"; 542 # $xml .= "<add ip=\"".$ip."\" type=\"1\" />\n";
539 $entries++; 543 $entries++;
540 } 544 }
541 } 545 }
542 $xml .= "</request>\n"; 546 $xml .= "</request>\n";
543 547
572 $type = $1; $msg = ""; 576 $type = $1; $msg = "";
573 } 577 }
574 578
575 if ($type eq "success") { 579 if ($type eq "success") {
576 mlog(1, "[DroneBL] Succesfully submitted $entries entries.\n$msg\n"); 580 mlog(1, "[DroneBL] Succesfully submitted $entries entries.\n$msg\n");
581 $dronebl_errors = 0;
577 while (my ($ip, $entry) = each(%dronebl)) { 582 while (my ($ip, $entry) = each(%dronebl)) {
578 $entry->{"sent"} = 1; 583 $entry->{"sent"} = 1;
579 $statlist{$ip}{"dronebl"} = 2 if defined($statlist{$ip}); 584 $statlist{$ip}{"dronebl"} = 2 if defined($statlist{$ip});
580 } 585 }
581 } elsif ($type eq "error") { 586 } elsif ($type eq "error") {
582 # If we don't have a valid key, disable further submissions. 587 # If we don't have a valid key, disable further submissions.
583 if ($msg =~ /<code>403<\/code>/) { 588 if ($msg =~ /<code>403<\/code>/) {
584 mlog(-1, "Disabling DroneBL submission due to invalid key.\n"); 589 mlog(-1, "Disabling DroneBL submission due to invalid key.\n");
585 $settings{"DRONEBL"} = 0; 590 $settings{"DRONEBL"} = 0;
591 } else {
592 $dronebl_errors++;
586 } 593 }
587 # Log error message mangled 594 # Log error message mangled
588 $msg =~ s{\s*</?[^>]+>}{ }g; 595 $msg =~ s{\s*</?[^>]+>}{ }g;
589 mlog(-1, "[DroneBL] Error in submission: $msg\n"); 596 mlog(-1, "[DroneBL] Error in submission: $msg\n");
590 } else { 597 } else {
591 mlog(-1, "[DroneBL] Unsupported response message ".$str."\n"); 598 mlog(-1, "[DroneBL] Unsupported response message ".$str."\n");
599 $dronebl_errors++;
592 } 600 }
593 } else { 601 } else {
594 mlog(-1, "[DroneBL] HTTP request failed: [".$res->code."] ".$res->message."\n"); 602 mlog(-1, "[DroneBL] HTTP request failed: [".$res->code."] ".$res->message."\n");
603 $dronebl_errors++;
604 }
605
606 if ($dronebl_errors >= $settings{"DRONEBL_MAX_ERRORS"}) {
607 mlog(-1, "Temporarily disabling DroneBL submissions due to too many errors for next ".$settings{"DRONEBL_SUSPEND"}. " rounds.\n");
608 $dronebl_suspend = $settings{"DRONEBL_SUSPEND"};
595 } 609 }
596 610
597 # Clean up expired entries, warn/note about unsubmitted ones. 611 # Clean up expired entries, warn/note about unsubmitted ones.
598 while (my ($ip, $entry) = each(%dronebl)) { 612 while (my ($ip, $entry) = each(%dronebl)) {
599 if (!check_time3($entry->{"date"})) { 613 if (!check_time3($entry->{"date"})) {
1102 } 1116 }
1103 sleep(1); 1117 sleep(1);
1104 foreach my $filename (keys %filehandles) { 1118 foreach my $filename (keys %filehandles) {
1105 seek($filehandles{$filename}, $filepos{$filename}, 0); 1119 seek($filehandles{$filename}, $filepos{$filename}, 0);
1106 } 1120 }
1107 if ($counter < 0 || $counter >= (60*5)) { 1121 if ($counter < 0 || $counter >= 60) {
1108 # Every once in a while, execute maintenance functions 1122 # Every once in a while, execute maintenance functions
1109 $counter = 0; 1123 $counter = 0;
1110 malt_maintenance(); 1124 malt_maintenance();
1111 } 1125 }
1112 $counter++; 1126 $counter++;