#!/usr/bin/perl ########################################################################### # # Program : Log Analyzer for DansGuardian # Author : Jimmy Myrick (jmyrick@tiger1.tiger.org) # Version : .1.1 # Released : July 6, 2002 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # Heck, if you like it though and want to send me something, that's # ok too. # # Change history is available here for now: # http://www.tiger.org/technology/dg # # Change LOG: November 04, 2002 # # Adapted end Tranlated from Netcon Soluções em Informática # Adaptado e Traduzido por Netcom Soluções em Informática # Charles Jonh Camello - charles@netcom.inf.br # # Revision of Tranlation # Revisão de Tradução # Vicente Fontanella - vicente@netcom.inf.br # ########################################################################### ########################################################################### # # Mude para o caminho do diretorio de log do DansGuardian # NOTE: No final é obrigatório ter a / # ########################################################################### $logdir = '/var/log/dansguardian/'; ########################################################################### # # Arquivo de log. Altere isto para o exato prefixo dos seus arquivos de log # Por padrão este arquivo é access.log e não deve ser modificado. # # Qualquer arquivo de log em $logdir com o prefixo $logfile será zipado # com a extenção .gz para futuras consultas. O resultado será impresso na # ordem cronológica reversa dos arquivos. # # Exemplo: # Se você tem os arquivos: acces.log access.log.0.gz access.log.1.gz # então será impresso primeiro o access.log.1.gz depois access.log.0.gz e # por último access.log # # Nenhuma organização é feita pelo programa e os resultados são mostrados # na ordem dos arquivos de log. Se os seus resultados estão fora da sequencia # verifique os nomes dos arquivos e as datas para ter certeza que eles estão # compridos na sequencia correta. Se você usa FreeBSD newsyslog.conf para rodar # os seus logs, então você não terá problemas. # ########################################################################### $logfile = 'access.log'; ########################################################################### # # Se você precisa os modulos do perl abaixo, faça o download para algum # diretório. Então entre no diretório, descompacte o arquivo e execute os # seguintes comandos: # perl Makefile.PL; make; make test; make install # # Se você precisar de mais informações vá para o site: # http://www.cpan.org/modules/INSTALL.html # # Faça o downdoad de: # http://www.cpan.org/authors/id/LDS/CGI.pm-2.81.tar.gz # ########################################################################### use CGI; ########################################################################### # # Isso é nesessário para descompactar os arquivos # # Faça o download em: # http://www.cpan.org/authors/id/PMQS/Compress-Zlib-1.16.tar.gz # ########################################################################### use Compress::Zlib; ########################################################################### # # Isto ira determinar onde o programa será chamado automaticamente. # Se não, descomente a primeira linha, mude para o caminho do seu servidor # nome/caminho e comente a segunda linha. Se desejar pode utilizar as # restrições do Apache para tornar bloquear o ascesso. # ########################################################################### $cgipath = 'http://nome_do_servidor/cgi-bin/dglog.pl'; #cgipath = $ENV{SCRIPT_NAME}; ########################################################################### # # NÃO SE DEVE MODICIFAR QUALQUER COISA ABAIXO DESTA LINHA # ########################################################################### $q = new CGI; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $mon = $mon + 1; # mon starts at 0 $year = $year + 1900; # year needs 1900 added $pagename = 'Analizador de Logs para DansGuardian'; $a = $q->param('a'); if ($a eq 'i') { # Inquiry into logs # These are the values that can be sent by the user through the browser $sIP = "Todos"; # IP address $sUN = "Todos"; # Username $sURL = "Todos"; # URL to show or trace a denied site - this is the URL to trace $sSD = "Todos"; # Complete start date $sSDY = "Todos"; # Start date year $sSDM = "Todos"; # Start date month $sSDD = "Todos"; # Start date day $sED = "Todos"; # Complete end date $sEDY = "Todos"; # End date year $sEDM = "Todas"; # End date month $sEDD = "Todos"; # End date day $sA = "Todos"; # Action $sSumCnt = "20"; # Number of summary sites to show $sSumDen = "off"; # Show denied summary? on/off $sSumAlw = "off"; # Show allowed summary? on/off $sL = "off"; # Turn URL's into links? on/off $sZ = "off"; # Examine gziped files? on/off $sIP = &validateIP($q->param('sIP')) if $q->param('sIP') ne ""; $sUN = $q->param('sUN') if $q->param('sUN') ne ""; $sURL = $q->param('sURL') if $q->param('sURL') ne ""; if ($q->param('sSDY') ne "" && $q->param('sSDM') ne "" && $q->param('sSDD') ne "" && $q->param('sEDY') ne "" && $q->param('sEDM') ne "" && $q->param('sEDD') ne "") { $sSDY = $q->param('sSDY'); $sSDM = $q->param('sSDM'); $sSDD = $q->param('sSDD'); $sEDY = $q->param('sEDY'); $sEDM = $q->param('sEDM'); $sEDD = $q->param('sEDD'); $sSD = $sSDY.'.'.$sSDM.'.'.$sSDD; $sSD = convertDate($sSD); $sED = $sEDY.'.'.$sEDM.'.'.$sEDD; $sED = convertDate($sED); if ($sSD > $sED) { $msg = "Data Final é posterior a data Inicial"; &printMenu; } } $sA = &validateAction($q->param('sA')) if $q->param('sA') ne ""; # Action $sSumCnt = &validateSummary($q->param('sSumCnt')) if $q->param('sSumCnt') ne ""; $sSumDen = $q->param('sSumDen') if $q->param('sSumDen') eq 'on'; $sSumAlw = $q->param('sSumAlw') if $q->param('sSumAlw') eq 'on'; $sL = $q->param('sL') if $q->param('sL') eq 'on'; $sZ = $q->param('sZ') if $q->param('sZ') eq 'on'; # Need a few global variables to keep from passing back and forth a bunch $linesRead, $allowTotal, $blockTotal, $grandTotal = 0; &searchLog; } elsif ($a eq 'h') { &displayHelp; } else { &printMenu; } ############# sub searchLog ############# { my $first = 0; &printHeader; print ""; print "Relatório de Infrmações para:
Data Inicial: $sSDD/$sSDM/$sSDY | Data Final: $sEDD/$sEDM/$sEDY | Nome do Usuário : $sUN | IP: $sIP | Ação: $sA | URL: $sURL
\n"; print ""; opendir(D, $logdir); @files = grep {/^$logfile/} readdir(D); @files = sort {$b cmp $a} @files; closedir(D); foreach $file (@files) { if ($file =~ /\.gz/) { if ($sZ eq 'on') { if ($first == 0) { print "Ignoring gzip logfile(s) in $logdir: "; $first = 1; } print "$file | "; next; } $gz = gzopen($logdir.$file,r); if (!$gz) { $msg = "Impossivel abrir $logdir$file. Verifique as Permissões."; &printMenu; } while ($gz->gzreadline($line)) { &checkLine($line); } $gz->gzclose; } else { print "

"; unless (open(F,$logdir.$file)) { $msg = "Impossivel abrir $logdir$file. Verifique as Permissões."; &printMenu; } while ($line = ) { &checkLine($line); } close(F); } } if ($sSumAlw eq "on" && $allowTotal != 0) { &showSummarySites($allowTotal,'PERMITIDO',$sSumCnt,%topSites); } if ($sSumDen eq "on" && $blockTotal != 0) { &showSummarySites($blockTotal,'NEGADO',$sSumCnt,%blockSites); } print "


Total Encontrados: $grandTotal | Total Requerimentos: $linesRead
"; print "
Retornar ao Menu
"; } ############# sub checkLine ############# { my ($line) = @_; $linesRead++; # Print out a '.' every 1000 log file lines read. Keep browser connect alive if (($linesRead % 1000) == 0) { print " "; } ($date,$time,$user,$ip,$url,$toeol) = split(/ /,$line,6); # Rule out the easy matches first return if ($sIP ne "Todos" && $sIP ne $ip); return if ($sUN ne "Todos" && $sUN ne $user); # Don't do a date comparison unless we are told to if ($sSD ne "Todos" || $sED ne "Todos") { $dgDate = &convertDate($date); return if (!($dgDate ge $sSD && $dgDate le $sED)); } $url =~ /(\w+):\/\/([\w\.-]+)\/?(\S*)/; $protocol = $1; # HTTP, FTP $baseurl = $2; # domain part without http:// or ftp:// return if ($sURL ne "Todos" && $sURL ne $baseurl); $toeol =~ /(\*.+\*)? ?(.+)? (\w+) (\d+)$/; $action = $1; # *DENIED# or *EXCEPTION* etc., if exists $reason = $2; # Reason for #1 if exists $method = $3; # method (GET POST) $size = $4; # size if ($sA ne "ALL") { return if ($sA eq "denAll" && $action ne "*DENIED*"); return if ($sA eq "excAll" && $action ne "*EXCEPTION*"); return if ($sA eq "denSite" && !($reason =~ /^Banned site/)); return if ($sA eq "denRegURL" && !($reason =~ /^Banned Regular Expression URL/)); return if ($sA eq "denPhrase" && !($reason =~ /^Banned Phrase/)); return if ($sA eq "denCombPhrase" && !($reason =~ /^Banned combination phrase/)); return if ($sA eq "denWeightPhrase" && !($reason =~ /^Weighted phrase limit/)); return if ($sA eq "denExt" && !($reason =~ /^Banned extension/)); return if ($sA eq "denMIME" && !($reason =~ /^Banned MIME Type/)); return if ($sA eq "denICRA" && !($reason =~ /^ICRA/)); return if ($sA eq "denBlanketIP" && !($reason =~ /^Blanket IP Block/)); return if ($sA eq "excSite" && !($reason =~ /^Exception site/)); return if ($sA eq "excPhrase" && !($reason =~ /^Exception phrase/)); return if ($sA eq "excCombPhrase" && !($reason =~ /^Combination exception phrase/)); } # Need to do a count for grandTotal if allowed OR denied summary selected if ($sSumAlw eq "on" || $sSumDen eq "on") { if ($action ne '*DENIED*') { $allowTotal++; $grandTotal++; # Don't waste memory if didn't want this, but need to count for grandTotal $topSites{$baseurl}++ if $sSumAlw eq "on"; } else { $blockTotal++; $grandTotal++; # Don't waste memory if didn't want this, but need to count for grandTotal $blockSites{$baseurl}++ if $sSumDen eq "on"; } } else { print "$date   $time   "; print "$ip   $user
"; if ($sL eq 'on') { print "$url $method $size
"; } else { print "$url $method $size
"; } if ($action ne "" && $reason ne "") { print "$action : $reason

"; } else { print "

"; } $grandTotal++; } } #################### sub showSummarySites { #################### my ($subTotal, $whatToShow, $topNum, %sites) = @_; my $count = 1; print "
"; foreach $key (sort {$sites{$b} <=> $sites{$a}} keys %sites) { if ($count <= $topNum) { print ""; print ""; print ""; $count++; } break; } print ""; print "

Os $topNum Sites mais $whatToShow
Colocação URL Contagem \% de
$whatToShow
\% de
Total
Detalhes
$count.  "; if ($sL eq 'on') { print "$key"; } else { print "$key"; } print "$sites{$key}"; printf("   %2.2f  ",($sites{$key}/$subTotal)*100); print ""; printf("   %2.2f",($sites{$key}/$grandTotal)*100); print " Sobre

Total de Sites $whatToShow (os $topNum mais ascessados) : $subTotal


"; } ################### sub validateSummary ################### { my ($count) = @_; if ($count < 0 || $count > 100) { $count = 20; } return($count); } ############## sub validateIP ############## { my ($checkIP) = @_; if ($checkIP eq 'Todos') { return('Todos'); } elsif ($checkIP =~ /^((2([0-4]\d|5[0-5])|1?\d{1,2})(\.|$)){4}/) { return ($checkIP); } else { $msg = "Endereço IP Inválido."; &printMenu; } } ################## sub validateAction { ################## my ($action) = @_; # Need to make the actions a hash and reference them that way # Make it easier to add/modify and can validate that way too # Maybe later. if ($action eq "none") { return ("Todos"); } return ($action); } ############### sub convertDate { ############### my ($workDate) = @_; ($year, $mon, $day) = split(/\./,$workDate); if (length($mon) == 1) { $mon = '0'.$mon; } if (length($day) == 1) { $day = '0'.$day; } if (($mon ge "01" && $mon le "12") && ($day ge "01" && $day le "31") && ($year ge "2000" && $year le "2035")) { $goodDate = $year.$mon.$day; return ($goodDate); } else { $msg = "Detectado Data Inválida"; &printMenu; } } ############### sub buildSelect ############### { my ($start, $end, $type) = @_; my $x = 0; ## print "