system,error,critical MikroTik: login failure for user per from 192.168.88.10 via winbox
# Created Jotne 2019 v1.0
#
# Add user who tries wrong user or password to address-list
# Find all "login failure" error last 5 min
:local loglist [:toarray [/log find time>([/system clock get time] - 5m) message~"login failure"]]
5
# for all error do
:foreach i in=$loglist do={
# find message
:local logMessage [/log get $i message]
# find ip
:local ip [:pick $logMessage ([:find $logMessage "from"]+5) [:find $logMessage " via"]]
# Add ip to accesslist
/ip firewall address-list add address=$ip list=Wrong_User timeout=24h
}
Any update ?This should do:
Schedule it to run every 5 min.
It will then add the IP for the user with wrong username or password to address list Wrong_User for 24 hour.
Code: Select all# Created Jotne 2019 v1.0 # # Add user who tries wrong user or password to address-list # Find all "login failure" error last 5 min :local loglist [:toarray [/log find time>([/system clock get time] - 5m) message~"login failure"]] 5 # for all error do :foreach i in=$loglist do={ # find message :local logMessage [/log get $i message] # find ip :local ip [:pick $logMessage ([:find $logMessage "from"]+5) [:find $logMessage " via"]] # Add ip to accesslist /ip firewall address-list add address=$ip list=Wrong_User timeout=24h }
# Created Jotne 2019 v1.0
#
# Add user who tries wrong user or password to address-list
# Find all "login failure" error last 5 min
:local loglist [:toarray [/log find time>([/system clock get time] - 5m) message~"login failure"]]
# for all error do
:foreach i in=$loglist do={
# find message
:local logMessage [/log get $i message]
# find ip
:local ip [:pick $logMessage ([:find $logMessage "from"]+5) [:find $logMessage " via"]]
# Add ip to accesslist
/ip firewall address-list add address=$ip list=Wrong_User timeout=24h
}
What if I don't care about wrong passwords? Only wrong usernames?
# Add user who tries wrong user or password to address-list
They are not logged differently. That would make this too easy..I am not sure if the message that are logged are different if its wrong user or wrong password.
Login failure for user x from a.b.c.d via service"
Well but I am asking for the opposite: when a user name is entered that is NOT one of the locally known usernames, do NOT log it.When going through bad login, its possible to compare the username against all local stored user name and if not found, then do log a message.
I'd rather blacklist/drop on the first attempt of using a wrong username, but that is the idea..I prefer a script that will put in a blacklist all the usernames login attempts (more than 3 attempts) that are not users of the system.
That is a pretty small use-case...Why? Because Wor6Eqs2FWqA then probably is the PASSWORD for a user known in the system. And because log information could become available to others more easily than you would desire (e.g. when an external log server is used, or when critical messages are picked up by a monitoring system and sent as alerts).
[/system clock get time] - 5m
/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"
}
}
}
/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.I have already maded one similar script, I just need to modify it to do what required from OP:
viewtopic.php?p=917307#p917428
: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"
/ip firewall address-list
add list=$listfail address=$ipinside comment="$rmess"
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list add list=$listfail address=$ipinside comment="$rmess"
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 winboxOn 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, thanksI 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"
}
}
:if ([:len [/user find where name=$userinside]] = 0) do={
/ip firewall address-list add list=$listfail address=$ipinside comment="$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" } }
: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"
how to configure the number of attempts before they goes in blacklist?I have already maded one similar script, I just need to modify it to do what required from OP:
/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.Same warnings:
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.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?
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.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.
Read this: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.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.
Do not remove... DISABLE...When a remove a blacklist entry, at the next script run it will put again the blacklist entry. How to avoid this?
Is there any way to increase the efficiency of this script?I have already maded one similar script, I just need to modify it to do what required from OP:
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.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...
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...
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={
Interesting.. Put it in the startup scheduler and then have the script call itself at the end..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...
'system script run 'script1'
:execute "/system script run script1"
:do {
<ORIGINAL SCRIPT>
:delay 1s ; # safety measure against loops
} while=(true)
Go for it, I don't care, they are not getting in.Leaving open SSH you say to the world "Hey, I have SSH open, try to guess username and password, is free!!!"...
PasswordAuthentication No
Nice. Thank you.Remember asyncronous ":execute"...
Is it possible to delete/remove a message from the log? - I removed the ! because I want the script to 'act' when finding a SSH log entry to delete the message, otherwise still using from above, it just gets really, really slow when there are a lot of log entries with IP addresses in them, at least I believe it is log entries with IP addresses slowing it down.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:Code: Select allfrom: :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={
/system logging
set 0 topics=info,!dhcp
Thanks for your script. Is it possible to modify it so the IP enters the Wrong_User list only after, for example, 3 or 5 attempts?This should do:
Schedule it to run every 5 min.
It will then add the IP for the user with wrong username or password to address list Wrong_User for 24 hour.
Thanks. I'm new to MikroTik, and this is the only script that works for me in v7.12.1. I like that it will only add the IP after three failed attempts.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:Code: Select all/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" } } } }
So this, kind of, replicates an enterprise firewall where everything is blocked unless explicitly unblocked?Hi!
An alternative version of the script that searches the device log for not only the wrong username, but many other phrases and can use a firewall:
https://forummikrotik.ru/viewtopic.php?p=91464#p91464
https://github.com/drpioneer/MikrotikBl ... danger.rsc
When the 'firewallUsage' variable is set to 'true', the script will try to configure the Firewall according to the principle: "everything that is not allowed is prohibited."So this, kind of, replicates an enterprise firewall where everything is blocked unless explicitly unblocked?