#!/usr/bin/perl

###
### This is a httpd abuse monitor for nginx.
###

$| = 1;
$this_filename = "scan_nginx";
$times = `date +%y%m%d-%H%M%S`;
chomp($times);
$myhn = `hostname --fqdn`;
chomp($myhn);
$llip = `echo \$(getent ahostsv4 $myhn) | cut -d: -f2 | awk '{ print $1}'`;
local($myip, $rest) = split(/\s+/,$llip);
print "myip is $myip";
chomp($myip);
if (-e "/root/.hr.monitor.cnf") {
  $default_critnumber = 188;
  $default_lines = 400;
  $default_mode = 1;
}
else {
  $default_critnumber = 222;
  $default_lines = 300;
  $default_mode = 2;
}
&makeactions;
print "CONTROL complete for $myip ($myhn)\n";
exit;

#############################################################################
sub makeactions
{
  if (-e "/var/xdrago/monitor/web.log") {
    $this_path = "/var/xdrago/monitor/web.log";
    open (NOT,"<$this_path");
    @banetable = <NOT>;
    close (NOT);
  }
  local(@MYARR) = `tail --lines=$default_lines /var/log/nginx/access.log 2>&1`;
  local($critnumber) = $default_critnumber;
  local($mininumber) = $critnumber / 2;
  print "\n===[$mininumber] mininumber===\n";
  local($sumar,$li_cnt{$VISITOR},$sumarpx,$px_cnt{$PROXY});
  local($im_sumar,$im_li_cnt{$VISITOR},$im_sumarpx,$im_px_cnt{$PROXY});
  foreach $line (@MYARR) {
    local($VISITOR, $PROXY, $XREAL, $YREAL, $ZREAL, $RESTX) = split(/\s+/,$line);
    $VISITOR =~ s/[^0-9\.]//g;
    if ($VISITOR =~ /^((192.168.)|(172.16.)|(unknown)|(10.)|(127.0.))/)
    {
      $VISITOR = $PROXY;
      $PROXY = $XREAL;
      if ($VISITOR =~ /^((192.168.)|(172.16.)|(unknown)|(10.)|(127.0.))/)
      {
        $VISITOR = $XREAL;
        $PROXY = $YREAL;
        if ($VISITOR =~ /^((192.168.)|(172.16.)|(unknown)|(10.)|(127.0.))/)
        {
          $VISITOR = $YREAL;
          $PROXY = $ZREAL;
          if ($VISITOR =~ /^((192.168.)|(172.16.)|(unknown)|(10.)|(127.0.))/)
          {
            $VISITOR = $ZREAL;
          }
        }
      }
    }
    $VISITOR =~ s/[^0-9\.]//g;
    if ($VISITOR !~ /^((192.168.)|(172.16.)|(10.)|(127.0.))/ && $VISITOR =~ /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/) {
      chomp($line);
      if ($line =~ /(GET|HEAD|POST)/) {
        local($skip_post) = 0;
        if ($line =~ /(GET|POST) \/([a-z]{2}\/)?(batch|advagg|views-bulk-operations|node\/[0-9]{1,}\/edit|media\/browser)|POST \/js\/|(GET|POST) \/([a-z]{2}\/)?(hosting|system|admin|app|ckeditor)\/|\/(ajax|autocomplete|shs)\/|files\/progress|plupload|json|api\/rest|GET \/(filefield_nginx_progress|filefield\/progress)/) {
          ### print "Not Counted Dynamic Request URI: $line\n";
          $skip_post = 1;
        }
        elsif ($line =~ /files\/(imagecache|styles)/) {
          ### print "Monitored Dynamic Request URI: $line\n";
          $im_li_cnt{$VISITOR}++;
          $skip_post = 1;
        }
        elsif ($line =~ /GET \/.*\.(mp4|m4a|flv|avi|mpe?g|mov|wmv|mp3|ogg|ogv|wav|midi|zip|tar|t?gz|rar|dmg|exe|apk|pxl|ipa)\"/) {
          ### print "Not Counted Static Request URI: $line\n";
          $skip_post = 1;
        }
        elsif ($line =~ /GET \/timemachine\/[0-9]{4}\//) {
          ### print "Not Counted Static Request URI: $line\n";
          $skip_post = 1;
        }
        else {
          $li_cnt{$VISITOR}++;
        }
        $li_cnt{$VISITOR} = $li_cnt{$VISITOR} + 1  if ($line =~ /POST/ && $skip_post < 1);
        if ($default_mode eq "1") {
          $li_cnt{$VISITOR} = $li_cnt{$VISITOR} + 10 if ($line =~ /POST/ && $line =~ /(\/user)|(user\/(register|pass|login))|(node\/add)/);
          $li_cnt{$VISITOR} = $li_cnt{$VISITOR} + 3  if ($line =~ /GET/  && $line =~ /node\/add/);
          $li_cnt{$VISITOR} = $li_cnt{$VISITOR} + 5 if ($line =~ /foobar/);
        }
      }
      else {
        if ($line =~ /0.000/) {
          print "Not Counted Not Supported Request Type: $line\n";
        }
        else {
          $li_cnt{$VISITOR}++;
          ### print "Counted Not Supported Request Type: $line\n";
        }
      }
    }
    $PROXY =~ s/[^0-9\.]//g;
    if ($PROXY ne $VISITOR && $PROXY !~ /^((192.168.)|(172.16.)|(10.)|(127.0.))/ && $PROXY =~ /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/) {
      chomp($line);
      if ($line =~ /(GET|HEAD|POST)/) {
        local($skip_post) = 0;
        if ($line =~ /(GET|POST) \/([a-z]{2}\/)?(batch|advagg|views-bulk-operations|node\/[0-9]{1,}\/edit|media\/browser)|POST \/js\/|(GET|POST) \/([a-z]{2}\/)?(hosting|system|admin|app|ckeditor)\/|\/(ajax|autocomplete|shs)\/|files\/progress|plupload|json|api\/rest|GET \/(filefield_nginx_progress|filefield\/progress)/) {
          ### print "Not Counted Dynamic Request URI: $line\n";
          $skip_post = 1;
        }
        elsif ($line =~ /files\/(imagecache|styles)/) {
          ### print "Monitored Dynamic Request URI: $line\n";
          $im_px_cnt{$PROXY}++;
          $skip_post = 1;
        }
        elsif ($line =~ /GET \/.*\.(mp4|m4a|flv|avi|mpe?g|mov|wmv|mp3|ogg|ogv|wav|midi|zip|tar|t?gz|rar|dmg|exe|apk|pxl|ipa)\"/) {
          ### print "Not Counted Static Request URI: $line\n";
          $skip_post = 1;
        }
        elsif ($line =~ /GET \/timemachine\/[0-9]{4}\//) {
          ### print "Not Counted Static Request URI: $line\n";
          $skip_post = 1;
        }
        else {
          $px_cnt{$PROXY}++;
        }
        $px_cnt{$PROXY} = $px_cnt{$PROXY} + 1  if ($line =~ /POST/ && $skip_post < 1);
        if ($default_mode eq "1") {
          $px_cnt{$PROXY} = $px_cnt{$PROXY} + 10 if ($line =~ /POST/ && $line =~ /(\/user)|(user\/(register|pass|login))|(node\/add)/);
          $px_cnt{$PROXY} = $px_cnt{$PROXY} + 3  if ($line =~ /GET/  && $line =~ /node\/add/);
          $px_cnt{$PROXY} = $px_cnt{$PROXY} + 5 if ($line =~ /foobar/);
        }
      }
      else {
        if ($line =~ /0.000/) {
          print "Not Counted Not Supported Request Type: $line\n";
        }
        else {
          $px_cnt{$PROXY}++;
          ### print "Counted Not Supported Request Type: $line\n";
        }
      }
    }
  }
  foreach $VISITOR (sort keys %li_cnt) {
    $sumar = $sumar + $li_cnt{$VISITOR};
    local($thissumar) = $li_cnt{$VISITOR};
    if ($thissumar > $mininumber) {
      local($isloggedin) = 0;
      &check_who($VISITOR);
      $critnumber = $critnumber - 50 if ($critnumber > 250);
      $critnumber = 8888 if ($isloggedin); ### don't block logged in users
      $critnumber = 8888 if ($VISITOR eq $myip); ### don't block own IP
      print "===[$isloggedin] VISITOR li_cnt $VISITOR is logged in===\n" if ($isloggedin);
      print "===[$critnumber] VISITOR li_cnt critnumber for $VISITOR===\n" if ($VISITOR);
      local($blocked) = 0;
      &check_remote_ip($VISITOR);
      local($allowed) = 0;
      &check_own_ip($VISITOR);
      if ($thissumar > $critnumber) {
        if (!$allowed && !$blocked) {
          `echo "$VISITOR # [x$thissumar] $times" >> /var/xdrago/monitor/web.log`;
          `echo "$VISITOR # [x$thissumar] $times" >> /var/xdrago/monitor/$this_filename.archive.log`;
          if (-e "/etc/csf/csf.deny" && -e "/usr/sbin/csf" && !-e "/var/xdrago/guest-fire.sh") {
            `/usr/sbin/csf -td $VISITOR 3600 -p 80`;
          }
        }
      }
    }
  }
  foreach $PROXY (sort keys %px_cnt) {
    $sumarpx = $sumarpx + $px_cnt{$PROXY};
    local($thissumarpx) = $px_cnt{$PROXY};
    if ($thissumarpx > $mininumber) {
      local($isloggedin) = 0;
      &check_who($PROXY);
      $critnumber = $critnumber - 50 if ($critnumber > 250);
      $critnumber = 7777 if ($isloggedin); ### don't block logged in users
      $critnumber = 7777 if ($PROXY eq $myip); ### don't block own IP
      print "===[$isloggedin] PROXY px_cnt $PROXY is logged in===\n" if ($isloggedin);
      print "===[$critnumber] PROXY px_cnt critnumber for $PROXY===\n" if ($PROXY);
      local($blocked) = 0;
      &check_remote_ip($PROXY);
      local($allowed) = 0;
      &check_own_ip($PROXY);
      if ($thissumarpx > $critnumber) {
        if (!$allowed && !$blocked) {
          `echo "$PROXY # [x$thissumarpx] $times" >> /var/xdrago/monitor/web.log`;
          `echo "$PROXY # [x$thissumarpx] $times" >> /var/xdrago/monitor/$this_filename.archive.log`;
          if (-e "/etc/csf/csf.deny" && -e "/usr/sbin/csf" && !-e "/var/xdrago/guest-fire.sh") {
            `/usr/sbin/csf -td $PROXY 3600 -p 80`;
          }
        }
      }
    }
  }
  foreach $VISITOR (sort keys %im_li_cnt) {
    $im_sumar = $im_sumar + $im_li_cnt{$VISITOR};
    local($thisim_sumar) = $im_li_cnt{$VISITOR};
    if ($thisim_sumar > $mininumber) {
      local($isloggedin) = 0;
      &check_who($VISITOR);
      $critnumber = $critnumber - 50 if ($critnumber > 250);
      $critnumber = 999 if ($isloggedin); ### don't block logged in users
      $critnumber = 999 if ($VISITOR eq $myip); ### don't block own IP
      print "===[$isloggedin] VISITOR im_li_cnt $VISITOR is logged in===\n" if ($isloggedin);
      print "===[$critnumber] VISITOR im_li_cnt critnumber for $VISITOR===\n" if ($VISITOR);
      local($blocked) = 0;
      &check_remote_ip($VISITOR);
      local($allowed) = 0;
      &check_own_ip($VISITOR);
      if ($thisim_sumar > $critnumber) {
        if (!$allowed && !$blocked) {
          `echo "$VISITOR # [x$thisim_sumar] $times" >> /var/xdrago/monitor/web.log`;
          `echo "$VISITOR # [x$thisim_sumar] $times" >> /var/xdrago/monitor/$this_filename.archive.log`;
          if (-e "/etc/csf/csf.deny" && -e "/usr/sbin/csf" && !-e "/var/xdrago/guest-fire.sh") {
            `/usr/sbin/csf -td $VISITOR 3600 -p 80`;
          }
        }
      }
    }
  }
  foreach $PROXY (sort keys %im_px_cnt) {
    $im_sumarpx = $im_sumarpx + $im_px_cnt{$PROXY};
    local($thisim_sumarpx) = $im_px_cnt{$PROXY};
    if ($thisim_sumarpx > $mininumber) {
      local($isloggedin) = 0;
      &check_who($PROXY);
      $critnumber = $critnumber - 50 if ($critnumber > 250);
      $critnumber = 999 if ($isloggedin); ### don't block logged in users
      $critnumber = 999 if ($PROXY eq $myip); ### don't block own IP
      print "===[$isloggedin] PROXY im_px_cnt $PROXY is logged in===\n" if ($isloggedin);
      print "===[$critnumber] PROXY im_px_cnt critnumber for $PROXY===\n" if ($PROXY);
      local($blocked) = 0;
      &check_remote_ip($PROXY);
      local($allowed) = 0;
      &check_own_ip($PROXY);
      if ($thisim_sumarpx > $critnumber) {
        if (!$allowed && !$blocked) {
          `echo "$PROXY # [x$thisim_sumarpx] $times" >> /var/xdrago/monitor/web.log`;
          `echo "$PROXY # [x$thisim_sumarpx] $times" >> /var/xdrago/monitor/$this_filename.archive.log`;
          if (-e "/etc/csf/csf.deny" && -e "/usr/sbin/csf" && !-e "/var/xdrago/guest-fire.sh") {
            `/usr/sbin/csf -td $PROXY 3600 -p 80`;
          }
        }
      }
    }
  }
  print "===[$sumar] sumar===\n";
  print "===[$sumarpx] sumarpx===\n";
  print "===[$im_sumar] im_sumar===\n";
  print "===[$im_sumarpx] im_sumarpx===\n";
  undef (%li_cnt);
  undef (%px_cnt);
  undef (%im_li_cnt);
  undef (%im_px_cnt);
}

#############################################################################
sub check_remote_ip
{
  local($IP) = @_;
  if (-e "/var/xdrago/monitor/web.log") {
    foreach $banerecord (@banetable) {
      chomp ($banerecord);
      local($ifbanned, $rest) = split(/\s+/,$banerecord);
      $ifbanned =~ s/[^0-9\.]//g;
      if ($ifbanned eq $IP) {
        $blocked = 1;
        last;
      }
    }
  }
}
#############################################################################
sub check_who
{
  local($IP) = @_;
  @whotable = `who --ips | awk '{print $5}'`;
  foreach $whorecord (@whotable) {
    chomp ($whorecord);
    local($a, $b, $c, $d, $whoip) = split(/\s+/,$whorecord);
    $whoip =~ s/[^0-9\.]//g;
    if ($whoip eq $IP) {
      $isloggedin = 1;
      print "===[$IP] is AUTH OK===\n";
      last;
    }
  }
}
#############################################################################
sub check_own_ip
{
  local($IP) = @_;
  if (-e "/root/.local.IP.list") {
    foreach $record (@table) {
      chomp ($record);
      local($ifallowed, $rest) = split(/\s+/,$record);
      $ifallowed =~ s/[^0-9\.]//g;
      if ($ifallowed eq $IP) {
        $allowed = 1;
        print "===[$IP] is MY OK===\n";
        last;
      }
    }
  }
}
###EOF2014###
