Community discussions

MikroTik App
 
timjee
just joined
Topic Author
Posts: 14
Joined: Fri Sep 19, 2014 9:23 pm

Script to limit according to number of packets

Fri Sep 19, 2014 9:44 pm

Hi,

I have tried to compile a script that would monitor the total number of packets according to individual IP's and block those IP's in the firewall.
I still have to add a line to reset the queue counters after the script has run, however the beginnings of the script is below, I have tried to run this script and it doesn't work.
This is my first script, so please feel free to tell me what I am doing wrong.

:global interval;
:global threshold;
:set interval 10;
:set threshold 2000;

:local recipients {"user@example.com"}

:local subject "Subject of Message"

:for i from=1 to=254 do={
:if ([/queue simple find target-addresses=("192.168.1." . $i)] != "") do={
:set pack [get [find target-addresses=("192.168.1." . $i)] packets]
:if ($pack / $interval > $threshold) do={
/ip firewall filter add action=reject chain=forward src-address=("192.168.1." . $i) disabled=yes
:foreach r in=[:toarray $recipients] do={
:put ("Sending email to " . [:tostr $r])
/tool e-mail send from="mikrotik@scottnet.co.za" server="196.41.123.125" to=[:tostr $r] subject=[:tostr $subject] body="Body of Message"
}
}
}
}
 
User avatar
skot
Long time Member
Long time Member
Posts: 584
Joined: Wed Nov 30, 2011 3:05 am

Re: Script to limit according to number of packets

Fri Sep 26, 2014 2:16 am

To troubleshoot a script, I start by enclosing the whole script in brackets and pasting into the terminal (right-click, paste). This allows you to use local variables and also see errors in the script. These brackets can be removed when script is ready for production:
{
script...
....
}
I re-worked the script a bit. Instead of looping through all 254 IP addresses, it finds all simple queues that contain 192.168.1 and then checks packet totals.

One note on target-addresses: Because there can be multiple ones, the addresses are returned as an array. The script assumes that there is only one target-address per queue, and it is converted to a string. If queues have multiple addresses, the script will need to be changed.
:local interval 10;
:local threshold 2000;

:local recipients {"user@example.com"}

/queue simple
# find simple queues that contain base IP
:foreach i in=[find target-addresses~"192.168.1"] do={
# convert target-addresses array to a string
  :local ip [:tostr [get $i target-addresses]]
  :local packets [get $i total-packets]
  :if ($packets / $interval > $threshold) do={
   /ip firewall filter add action=reject chain=forward src-address=$ip disabled=no
   :foreach j in=$recipients do={
      :put ("Sending email to " . $j)
      /tool e-mail send ...
    }
  }
}
HTH
 
psamsig
Member Candidate
Member Candidate
Posts: 161
Joined: Sun Dec 06, 2009 1:36 pm
Location: Denmark

Re: Script to limit according to number of packets

Fri Sep 26, 2014 8:56 am

~ is regex, so escape accordingly:
[find target-addresses~"^192\\.168\\.1\\."]
Also be aware that syntax has changed for RouterOS 6 (at least in 6.19):
[find target~"^192\\.168\\.1\\."]
 
timjee
just joined
Topic Author
Posts: 14
Joined: Fri Sep 19, 2014 9:23 pm

Re: Script to limit according to number of packets

Fri Sep 26, 2014 8:06 pm

Thanks for the help skot, I will use your way of testing scripts in future, will certainly be better.
Thanks for the advice on target-addresses as well.
I like the way the re-worked script is, however there are certain queues that I don't want to be part of this. Is there a way to exclude some queues in the re-worked script, or would it be better to try another way of achieving the same goal?
I was going to use :for from= to= to achieve this as the queues I want to skip are 192.168.1.1 and 192.168.1.200-254
 
psamsig
Member Candidate
Member Candidate
Posts: 161
Joined: Sun Dec 06, 2009 1:36 pm
Location: Denmark

Re: Script to limit according to number of packets

Fri Sep 26, 2014 8:52 pm

Use comments and filter with that:
[find comment="ThisOne"]
or combine:
[find target-addresses~"^192\\.168\\.1\\." comment="ThisOne"]
of course you can use name as well:
[find name~"contain this text"]
 
timjee
just joined
Topic Author
Posts: 14
Joined: Fri Sep 19, 2014 9:23 pm

Re: Script to limit according to number of packets

Sat Sep 27, 2014 8:36 am

Thanks psamsig, I will give that a try and see which works better.
 
User avatar
skot
Long time Member
Long time Member
Posts: 584
Joined: Wed Nov 30, 2011 3:05 am

Re: Script to limit according to number of packets

Tue Sep 30, 2014 9:54 pm

Thanks for the help skot, I will use your way of testing scripts in future, will certainly be better.
Thanks for the advice on target-addresses as well.
I like the way the re-worked script is, however there are certain queues that I don't want to be part of this. Is there a way to exclude some queues in the re-worked script, or would it be better to try another way of achieving the same goal?
I was going to use :for from= to= to achieve this as the queues I want to skip are 192.168.1.1 and 192.168.1.200-254
Ah, ok... in that case your original plan was probably better! :)

Something like this would loop through by numbers and do the same checking:
:local interval 10;
:local threshold 2000;

:local recipients {"user@example.com"}

/queue simple
:for i from=2 to=199 do={
  :local search [find target-addresses=("192.168.1." . $i . "/32")]
  :if ($search != "") do={
    :local id $search
    :local ip [:tostr [get $id target-addresses]]
    :local packets [get $id total-packets]
    :if ($packets / $interval > $threshold) do={
      /ip firewall filter add action=reject chain=forward src-address=$ip disabled=no
      :foreach j in=$recipients do={
        :put ("Sending email to " . $j)
        /tool e-mail send ...
      }
    }
  }
}
HTH
 
timjee
just joined
Topic Author
Posts: 14
Joined: Fri Sep 19, 2014 9:23 pm

Re: Script to limit according to number of packets

Tue Oct 14, 2014 1:37 pm

Hi skot,

Just to say thanks, I have tested the script, and got it to work.
I did have to make one change though, target-addresses needed to be target.
:local search [find target-addresses=("192.168.1." . $i . "/32")]
  :if ($search != "") do={
    :local id $search
    :local ip [:tostr [get $id target-addresses]]
Thanks for the help from both you and psamsig.