Home  About Us   All Products  News Article  How to Order  Contact  
CATEGORIES

Welcome to spectrumindo.com

 
  PRODUCT
TRAINING
TOP PRODUCT
SUPPORT





Analyze LOG with Scripting in MikroTik

 At the MUM workshop about scripting, one question challenges me about how to find host that unsuccessful attempt to connect our Router and use random username/password. It is showed at the Log as “system, error,critical” topics, but the question is how can we find that IPs and then put it in our blacklist ips so next time those IPs try to connect, we can blocked them.

OK, the first thing appear in my mind is we can use a syslog to do that. The   idea is redirect all the “system,error,critical” topics of the log   into our syslog (or different syslog as the other topics). Then we can create   a script (usually I use the PERL script) to analyze the log if there are some   thread to access our Router. Well, however the next question is “can it   be done at the Router itself?”. Hmmm…. Interesting quest. Although   I think that a Router should be a Router (don’t bother a Router to do   a non-Router thing), but getting it done using MikroTik Scripting is very challenging.   Is it possible?

Basically, we can do almost everything in scripting (I mean it). Well, let’s   see how we can make it happened. Before continuing, I suggest that you learn   the basic scripting (you can access the workshop ppt here)

First of all, we need to get the log in-order to proceed the checking. The   log, of course, can be accessed using “/log print”   command. But wait a minute, can you imagine how many log will be at the the   process if you just using “/log print”?
 
 
 
  However, there are several parameters that we can use to simplify the log. In   this case, we will use the “where” parameters.   The differences between the line contains a unsuccessful login attempt is the   topics is “system,info,critical”. Besides this information, the   topics also include the information of improperly shutdown of the system. We   will make this as the filter. Now the parameter will show this information
 
 
 
  Now to analyze the log, we need to put the log into a variable in a script.   There are parameters at “print” action to return   the value and put it in a variable. This parameter is named “as-value”.   Now we are creating a variable to store the result of filtered-log.
 
 

Now we have the variable log as the list that we want to proceed.   But hold-a-second, what is the data-type of the variable? It will be easy for   us if only the log variable type is array because we can access   each of the items and using “foreach” command.   Now let’s check the data-type and change it to array if it’s not   so.
 
 

Since it is already array (be careful for some MikroTik version will result   a string type, use a “typeof” command to make sure),   now we can access the items by creating a loop. Use command “foreach”.

:foreach line in $log do={
  # Here where we will analyze each variable line
 
}

We will then check line-by-line. For easy way, let’s pick one items of   the list to get the IP address that attempt to connect using wrong username/password.   But before we go any further, we need to validate the line first. Since we need   the IP address, we will ignore this kind of line :
  • unsuccesfull attempts from mac-winbox or mac-telnet
  • topics “system,error,critical” what caused by improper shutdown
  It means we will checked whether it has a word “from”   since it will followed by an IP address. We use command “find”   to do this. Then the loop will be like this

:foreach line in $log do={
:set line [:tostr $line] => to make sure it is       str
      :if ([:find $line "from"] >0) do={
     
      # Here is the valid line to proceed
    }
  }

Now the interesting part is to get the IP address from the line itself. To   do that, let’s get an item from the list as if we are in one of the loop   we made before. I will extract one line using command “pick”.   I take the 2nd items of the list (array no. 1). Since the data type is still   array, then we have to change it to string.
 
 
 
  From the line, we can see that the IP is located just after word “from”.   The idea is to find the space after “from” and then get the word   next after that until the next space. Unfortunately the “from” word   is not located at the same position since the “username” can be   different. To get it dynamically, we can use a command “find”.
 
 

The start position (variable startpos) for the IP is the fromposition   + 5 (the length of word “from “) and the end position (variable   endpos) is the next space (the space right after startpos+1).   After getting the start position and end position, all we have to do is just   get the IP by using pick command.

OK… now we get the IP ?. But it’s not over yet. To enable further   access, we need to put the IP we found in the loop into an array variable. But   the problem is it can be duplicate IP in the log. We only need unique IP to   put in the blacklist.

To make sure the IP is uniquely assign at the array, we must checked if the   IP has already in the array or not. To do this, we only need a command “find”   but this time, we implement it in an array (not in a string). Variable iplist   is a defined variable before.

:if ( [:tostr [:find $iplist $ip]] = "")   do={
:set iplist ($iplist + $ip)
  }

After this process, we have a list with all the IP that attempts to connect   but failed to login. In the script, I simply put the IP in the Log so you can   see the IP is found. You can put it in a blacklist, you can make a script that   emailed those IPs, or you can just simply queue the IP with 1bps bandwidth.   This script is made only to find those IP. What you want to do with the IP,   is totally depends on you.
 
  Here is the complete script

:global log
  :global iplist ""
  :set log [/log print as-value where topics="system,error,critical"]
  :set log [:toarray $log]
  :foreach line in $log do={ 
  :set line [:tostr $line]
  :if ([:find $line "from"] >0) do={
  :local fromposition [:find $line "from"]
  :local startpos ($fromposition+5)
  :local endpos [:find $line " " ($startpos+1)]
  :local ip [:pick $line $startpos $endpos]
  :set iplist [:toarray $iplist]
  :if ( [:tostr [:find $iplist $ip]] = "") do={
  :set iplist ($iplist + $ip)  
     
  }
   
  }
 
 
  }
  :foreach ips in $iplist do={
  :log info $ips => put your own command here
  }

Is it all? I don’t think so. This script only got the IP. What is happened   when you are typing wrong username/password once? Your IP will be put in the   blacklist and no longer have access to the Router ?. Another weakness is how   do you avoid an IP already checked at the log being checked again?

Next article will discuss how we can count the IPs and make a threshold value,   for example it will be considered a thread if those IP have try to connect for   minimal 5 times. See you at the next article.


<< back
 


Copyright © 2007 spectrumindo.com
PT Dutakom Wibawa Putra