-1

I am trying to list a number of offending IP's with a one line command, and am not sure how to do the last little bit, maybe someone can point me in the right direction.

cat /var/log/syslog* | grep "SRC=" | cut -d " " -f 14 | sort | uniq -c | sort -n -r

In English...this should print all syslog files (also those rotated), search for entries of the Firewall and grab the SRC value (IP), count them and list them from highest to lowest. All I want now is to limit it to the top 5... Anybody know a command that can do that ?

Example entry in syslog:

Jan 11 12:01:52 xxxx kernel: [47261.722647] INPUT packet died: IN=eth0 OUT= MAC=44:8a:5b:a0:24:eb:00:31:46:0d:21:e8:08:00 SRC=xx.xx.xx.xx DST=xx.xx.xx.xx LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=33840 PROTO=TCP SPT=1024 DPT=22151 WINDOW=1024 RES=0x00 SYN URGP=0

The entries are made by my custom Firewall, not part of this Question

Example output of the command:

 47 SRC=13.82.59.79
  2 SRC=77.72.82.145
  2 SRC=213.157.51.11
  2 SRC=159.203.72.216
  1 SRC=77.72.85.15
  1 SRC=77.72.85.10
  1 SRC=77.72.83.238
  1 SRC=77.221.1.237
  1 SRC=222.186.172.43
  1 SRC=216.170.126.109
  1 SRC=191.101.167.253
  1 SRC=190.198.183.234
  1 SRC=173.254.247.206
  1 SRC=164.52.13.58
  1 SRC=141.212.122.145
  1 SRC=125.78.165.42
  1 SRC=118.139.177.119
  1 SRC=111.75.222.141
  1 SRC=103.30.40.9
  • 2
    Is it a head -n 5 you need as an extra step at the end of the pipeline, or did I misunderstand what you meant by "the top five"? – Kusalananda Jan 11 '18 at 11:33
  • in your "example entry" the crucial item SRC=xx.xx.xx.xx is the 13th field, while you are cutting it as 14th field cut -d " " -f 14 , why? – RomanPerekhrest Jan 11 '18 at 11:40
  • 1
    also, cat | grep | cut when just awk will do?? Try, e.g awk '/SRC=/ {print $13}' /var/log/syslog | sort | uniq -c | sort -nr | head -n 5 – cas Jan 11 '18 at 11:40
  • @RomanPerekhrest because cut isn't smart about whitespace. -d ' ' means exactly one space character, not one-or-more. It's one of the reasons i prefer to use awk rather than cut. – cas Jan 11 '18 at 11:41
  • 1
    some would say that's a useful skill in any language. – cas Jan 11 '18 at 11:43
1
awk '/SRC=/ { print $13 }' /var/log/syslog* | sort | uniq -c | sort -n -r | head -n 5

This does away with the catting, grepping and cutting from the original pipeline and replaces them with awk. The head -n 5 at the end will give you the top five results.

0

With single GNU awk "magic":

awk 'BEGIN{ 
         PROCINFO["sorted_in"]="@val_num_desc" 
     }
     /SRC=/{ src[$13]++ }
     END{ 
         for (k in src) { 
             print src[k], k; 
             if (++c > 4) break 
         } 
     }' /var/log/syslog*
0

Using only perl (no need for grep, cut, sort, or uniq):

perl -lane '
  $IPs{$F[12]}++ if (m/SRC=/);  # perl arrays start from zero, not 1.

  END {
    foreach $ip (sort { $IPs{$b} <=> $IPs{$a} } keys %IPs) { 
      last if ($count++ > 4);

      $seen=$IPs{$ip};   # $seen is only really needed in case you uncomment 
                         # the next line, to use the key before we change it.

      #$ip =~ s/^SRC=//; # uncomment if you want IPs without the SRC=

      printf "%s\t%s\n", $seen, $ip;
    };
  }' < <(zcat /var/log/syslog*)

It builds a hash array (%IPs) counting each time it sees a particular IP address. After it's read all the input, it sorts the hash by the count, and prints the top 5.

BTW, this uses zcat rather than just /var/log/syslog* because it's common for syslog and other log files to be rotated and compressed regularly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.