[/system clock get time] - 5m
The omnipresent time error with subtraction, 2022-04-27 00:00:00 - 5 minutes… = 2022-04-27 **-**00:05:00…
[/system clock get time] - 5m
The omnipresent time error with subtraction, 2022-04-27 00:00:00 - 5 minutes… = 2022-04-27 **-**00:05:00…
I have already maded one similar script, I just need to modify it to do what required from OP:
http://forum.mikrotik.com/t/script-to-add-ip-to-list-based-on-log-help-needed/156344/2
REMEMBER TO REMOVE THE \ BEFORE ? IF USED INSIDE A SCRIPT OR SCHEDULER (yes for v6…)
And also I use :global for test rapidly on terminal, but on script can be replaced with :local
First version, add IP of failed logins to blacklist. On the IP addedd to blacklist also add on comment why is added:
/log
:global failmsg "login failure for user "
:global frommsg " from "
:global viamsg " via "
:global listfail "list_failed_attempt"
:foreach rlog in=[find where message~"((25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])\\.){3}(25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])"] do={
:local rmess [get $rlog message]
:if (($rmess~$failmsg) and ($rmess~$frommsg) and ($rmess~$viamsg)) do={
:local userinside [:pick $rmess ([:find $rmess $failmsg -1] + [:len $failmsg]) [:find $rmess $frommsg -1]]
:local ipinside [:pick $rmess ([:find $rmess $frommsg -1] + [:len $frommsg]) [:find $rmess $viamsg -1]]
:local intinside [:pick $rmess ([:find $rmess $viamsg -1] + [:len $viamsg]) [:len $rmess]]
/ip firewall address-list
:if ([:len [find where list=$listfail and address=$ipinside]] = 0) do={
add list=$listfail address=$ipinside comment="$rmess"
}
}
}
This version add to blacklist the IP only if the username do not exist
/log
:global failmsg "login failure for user "
:global frommsg " from "
:global viamsg " via "
:global listfail "list_failed_attempt"
:foreach rlog in=[find where message~"((25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])\\.){3}(25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])"] do={
:local rmess [get $rlog message]
:if (($rmess~$failmsg) and ($rmess~$frommsg) and ($rmess~$viamsg)) do={
:local userinside [:pick $rmess ([:find $rmess $failmsg -1] + [:len $failmsg]) [:find $rmess $frommsg -1]]
:local ipinside [:pick $rmess ([:find $rmess $frommsg -1] + [:len $frommsg]) [:find $rmess $viamsg -1]]
:local intinside [:pick $rmess ([:find $rmess $viamsg -1] + [:len $viamsg]) [:len $rmess]]
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list
:if ([:len [find where list=$listfail and address=$ipinside]] = 0) do={
add list=$listfail address=$ipinside comment="$rmess"
}
}
}
}
I knew I saw it somewhere in the past, couldn’t find it again.
Thank you rextended!! offers digital drink
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list
:if ([:len [find where list=$listfail and address=$ipinside]] = 0) do={
add list=$listfail address=$ipinside comment="$rmess"
Why two ‘do’ actions? - Trying to understand the ‘why’ so I can learn this scripting..
First go to the address-list section..
/ip firewall address-list
Then add the IP to the list..
add list=$listfail address=$ipinside comment="$rmess"
Why not
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list add list=$listfail address=$ipinside comment="$rmess"
do it with one?
Remember that also exist something like that:
login failure for user aveawve from 64:D1:54:FF:44:77 via mac-telnet
login failure for user dminfghj from 08:60:6E:F7:EE:41 via winbox
On that cases, is possible to add MAC address on /firewall raw prerouting drop, but that logs can come only from your LAN (VPN, etc.), not from Internet…
Nice, thanks
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list
:if ([:len [find where list=$listfail and address=$ipinside]] = 0) do={
add list=$listfail address=$ipinside comment="$rmess"
}
}
Why two ‘do’ actions? - Trying to understand the ‘why’ so I can learn this scripting..
Because the first is added later to first script for fastly understand between the two version what I add (simply the ckeck if the user exist)
First go to the address-list section..
Then add the IP to the list..
Why not
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list add list=$listfail address=$ipinside comment="$rmess"
}
do it with one?
you do notice the two operation on address list:
first check if already is present,
second, if not present, add the address inside the list:
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list
:if ([:len [find where list=$listfail and address=$ipinside]] = 0) do={
add list=$listfail address=$ipinside comment=“$rmess”
}
}
:if ([:len [/user find where name=$userinside]] = 0) do={
:if ([:len [/ip firewall address-list find where list=$listfail and address=$ipinside]] = 0) do={
/ip firewall address-list add list=$listfail address=$ipinside comment=“$rmess”
}
}
if you try to add an IP already existant, you got error, and the script stop. and I hate Microsoft concept of “on-error resume next”
I have already maded one similar script, I just need to modify it to do what required from OP:
how to configure the number of attempts before they goes in blacklist?
The script immediately blacklist the IP, as requested by the OP.
But I can modify the script for wait x attempt for that.
Just wait as long as I implement it and try it.
Same warnings:
REMEMBER TO REMOVE THE \ BEFORE ? IF USED INSIDE A SCRIPT OR SCHEDULER (yes for v6…)
And also I use :global for test rapidly on terminal, but on script can be replaced with :local
This add to blacklist after 3 (configurable) failed attempts:
/log
:global maxattampt 3
:global errorArray [:toarray ""]
:global failmsg "login failure for user "
:global frommsg " from "
:global viamsg " via "
:global listfail "list_failed_attempt"
:foreach rlog in=[find where message~"((25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])\\.){3}(25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])"] do={
:local rmess [get $rlog message]
:if (($rmess~$failmsg) and ($rmess~$frommsg) and ($rmess~$viamsg)) do={
:local userinside [:pick $rmess ([:find $rmess $failmsg -1] + [:len $failmsg]) [:find $rmess $frommsg -1]]
:local ipinside [:pick $rmess ([:find $rmess $frommsg -1] + [:len $frommsg]) [:find $rmess $viamsg -1]]
:local intinside [:pick $rmess ([:find $rmess $viamsg -1] + [:len $viamsg]) [:len $rmess]]
:if ([:typeof (($errorArray)->$ipinside)] = "nothing") do={
:set (($errorArray)->$ipinside) 1
} else={
:set (($errorArray)->$ipinside) ((($errorArray)->$ipinside) + 1)
}
:if ((($errorArray)->$ipinside) > ($maxattampt - 1)) do={
/ip firewall address-list
:if ([:len [find where list=$listfail and address=$ipinside]] = 0) do={
add list=$listfail address=$ipinside comment="$rmess"
}
}
}
}
Thank you for the script.
I have tested and works great, but there is a trouble.
When a remove a blacklist entry, at the next script run it will put again the blacklist entry. How to avoid this?
You create a second address list with your address to white-list with a rule that is accepted, before the blacklist rule drops the traffic.
No way to create a script that parses only last entries from the log, without going to parse everytime entire logs? ( think I have seen something like “-5 minutes” or something like this.
Read this:
http://forum.mikrotik.com/t/can-a-script-be-created-if-a-wrong-login-name-is-used/132192/1
When a remove a blacklist entry, at the next script run it will put again the blacklist entry. How to avoid this?
Do not remove… DISABLE…
Or empty the log…
Or use my script here, this use two list, white and black:
http://forum.mikrotik.com/t/script-to-add-ip-to-list-based-on-log-help-needed/156344/2
I have already maded one similar script, I just need to modify it to do what required from OP:
Is there any way to increase the efficiency of this script?
It is taking well over two minutes to execute with just DHCP entries.. I logged a firewall drop rule and it created 30-40 entries and the script started taking 4+ minutes to execute..
I used to have it set to run every 10 seconds or so which worked great for the SSH attempts except last time I logged in there were many instances of the job running, cleared the log and set for 1 minute, came back later a LOT of DHCP entries showed up and there was 35 instances of the job. Performance didn’t affect a CCR but it did on a RB750Gr3, at least it only tied up one core, not all of them.. On a CCR1009, I stopped the scheduler with 42 jobs running, one has been running for an hour now..
Or is it already as optimized as it can be? Better to come up with a different solution?
if /system scripts job ‘script1’ present end? Something along those lines?
What is the best way? I don’t see a way to stop logging failed logins… To stop logging DHCP is easy though..
If SSH is used for RouterBOARD remote management, close SSH and use VPN.
If SSH is used inside the network, drop all SSH traffic on RAW, regardless if someone try to login or not,
and allow only secure source IPs (or again, use VPN) or put that IP on whitelist for x hours after correct port knocking…
Leaving open SSH you say to the world “Hey, I have SSH open, try to guess username and password, is free!!!”…
Yes, if SSH is used for RouterBOARD remote management, close SSH and use VPN.
If SSH is used inside the network, drop all SSH traffic on RAW, regardless if someone try to login or not,
and allow only secure source IPs (or again, use VPN) or put that IP on whitelist for x hours after correct port knocking…
SSH is allowed for remote management.. It is our fail safe because it is simple and safe.. If we can’t connect with the VPN, we can use SSH to get in and fix the VPN.
I don’t care about SSH attempts.. I would be happy to not log them at all.. Unfortunately failed SSH logs don’t use the SSH “topic”.. May be a bug…
About the script, a best practice is to not run another job for same script,
but at least wait the end, or leave the script auto-call himself at the end…
I don’t care about SSH attempts.. I would be happy to not log them at all.. Unfortunately failed SSH logs don’t use the SSH “topic”.. May be a bug…
for ignore completly SSH:
from:
:foreach rlog in=[find where message~"((25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])\\.){3}(25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])"] do={
to:
:foreach rlog in=[find where !(message~" via ssh") and \
message~"((25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])\\.){3}(25[0-5]|(2[0-4]|[01]\?[0-9]\?)[0-9])"] do={
About the script, a best practice is to not run another job for same script,
but at least wait the end, or leave the script auto-call himself at the end…
Interesting.. Put it in the startup scheduler and then have the script call itself at the end..
If I have the last command as
'system script run 'script1'
Will the ‘jobs’ show the first as still running because it hasn’t ended? Resource exhaustion would happen very quickly..
Even putting a second script in the middle to call the first, if it treats it as a sub-routine, I expect the same result..
‘script1’
as above..
/system script run “script2”
‘script2’
/system script run “script1”
Humm…