user admin logged in from 192.168.0.1 via web
# Script to check for specific new logs and send email alerts
# Tested on RouterOS v5.7+
# container to keep track of the last time stamp detected
:global lastTime;
# find log entries where the message contains "logged in" or "login failure"
:local currentBuf [ :toarray [ /log find message~"logged in" || message~"login failure" ] ] ;
# get number of log entries
:local currentLineCount [ :len $currentBuf ] ;
# if any logs were found, proceed
if ($currentLineCount > 0) do={
# based on number of entries, get time of last entry
:local currentTime "$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]";
# check currentTime length, if length is 15, log is from a previous day and begins with month/day
:if ([:len $currentTime] = 15 ) do={
# trim currentTime so we are left only with time xx:xx:xx
:set currentTime [ :pick $currentTime 7 15 ];
}
# the output for the body of the email, includes time stamp and log message
:local output "$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]";
# email function
:local sndEmail [:parse "/tool e-mail send to=email@domain.com subject=\"MikroTik alert $currentTime\" body=\"$output\" tls=yes"];
# beep function
:local doBeep [:parse ":beep;:delay 150ms;:beep;"];
# if the last time stamp has not been set, length will be 0 (after reboot, etc)
:if ([:len $lastTime] < 1 ) do={
# update lastTime to match currentTime
:set lastTime $currentTime ;
# send email and beep
$sndEmail;
$doBeep;
# if lastTime has been set, continue
} else={
# if lastTime does not match time stamp of the latest
:if ( $lastTime != $currentTime ) do={
# update lastTime to match currentTime
:set lastTime $currentTime ;
# send email and beep
$sndEmail;
$doBeep;
}
}
}
:local scheduleName "mySchedule" :local emailAddress "myEmail" :local startBuf [:toarray [/log find message~"logged in" || message~"login failure"]] :local removeThese ("telnet","whatever string you want") :local lastTime [/system scheduler get [find name="$scheduleName"] comment] :local currentBuf ""; :set currentBuf [:toarray $currentBuf] :foreach i in=$startBuf do={ :local toggle 1 :foreach j in=[:toarray $removeThese] do={ :if ([:typeof [:find [/log get $i message] "$j"]] = "num") do={ :set toggle 0 } } :if ($toggle = 1) do={ :set currentBuf ($currentBuf , $i) } } :local currentLineCount [ :len $currentBuf ] if ($currentLineCount > 0) do={ :local currentTime "$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]" :if ([:len $currentTime] = 15 ) do={ :set currentTime [ :pick $currentTime 7 15 ] } :local output "$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]" :if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={ /system scheduler set [find name="$scheduleName"] comment=$currentTime /tool e-mail send to="$emailAddress" subject="MikroTik alert $currentTime" body="$output" } }
:local scheduleName value="mySchedule";
:local emailAddress value="myEmail";
:local startBuf value=[:toarray [/log find where message~"logged in" or message~"login failure"] ];
:local removeThese value=[:toarray ("telnet","whatever string you want")];
:local lastTime value=("".[/system scheduler get [find name=$scheduleName] value-name=comment]);
:local currentBuf value=[:toarray ""];
:foreach i in=$startBuf do={
:foreach j in=$removeThese do={
:if ([/log get $i value-name=message] ~ $j) do={ } else={
:set $currentBuf ($currentBuf,$i);
};
};
};
:local currentLineCount value=[:len $currentBuf];
if ($currentLineCount > 0) do={
:local currentTime value=[/log get [:pick $currentBuf ($currentLineCount - 1)] value-name=time];
:if ([:len $currentTime] = 15) do={
:set $currentTime value=[:pick $currentTime 7 15];
};
:local output value=($currentTime." ".[/log get [:pick $currentBuf ($currentLineCount - 1)] value-name=message]);
:if ( ([:len $lastTime] < 1) or ( ([:len $lastTime] > 0) and ($lastTime != $currentTime) ) ) do={
/system scheduler set [find where name=$scheduleName] comment=$currentTime;
/tool e-mail send to=$emailAddress subject=("MikroTik alert ".$currentTime) body=$output;
}
}
:local toggle 1 :foreach j in=[:toarray $removeThese] do={ :if ([:typeof [:find [/log get $i message] "$j"]] = "num") do={ :set toggle 0 } } :if ($toggle = 1) do={ :set currentBuf ($currentBuf , $i) }To
:foreach j in=$removeThese do={
:if ([/log get $i value-name=message] ~ $j) do={ } else={
:set $currentBuf ($currentBuf,$i);
};
};
I count on it )Thanks Rex!
I changed up your suggestions from earlier and have the script functioning as I need considering the time is irrelevant to me.
I'll definitely take a look at your link though.
I owe you a drink next time I'm in Italy!
I don't know why it didn't work on 6.13. Just now ran it on 6.20 without any problems. Glad rextended's edit got it working for you.Quick question. Script runs flawlessly on 6.2 as you stated. Any way if you have a free moment you could take a look see and try on 6.13. I can't get the script to complete outside of 6.2.
This code causes problems when there are multiple removeThese array items. For example, say there are 5 array items, and 1 of them is a match. This code does not add the matching one. But for all of the other ones, it adds this same log entry to the currentBuf array 4 times. My original code prevents this by looping through all items, and if a match is found once, the log entry is ignored. If no matching entries are found, only then is the log entry added.Code: Select all:foreach j in=$removeThese do={ :if ([/log get $i value-name=message] ~ $j) do={ } else={ :set $currentBuf ($currentBuf,$i); }; };
I was aware of the time format having 2 different formats (00:00:00 and jul/11 00:00:00), and the v3 script checks for these. But I did not know about the other one. I wonder what that's about? I will update the script to check for this./log> pri detail
time=jan/01/2002 02:00:09 topics=system,info message="router rebooted"
time=jan/01/2002 02:00:20 topics=interface,info message="ether1 link up (speed 100M, full duplex)"
time=jan/01/2002 02:00:24 topics=dhcp,info message="dhcp-client on ether1 got IP address 192.168.1.101"
time=jul/11 19:11:42 topics=system,info,account message="user admin logged in from 192.168.0.102 via winbox"
time=jul/11 19:12:34 topics=system,info,account message="user admin logged in from 192.168.0.102 via telnet"
time=19:16:05 topics=system,info message="system time zone settings changed by admin"
This is a good idea. Aside from the benefit of not missing any "inbetween" logs, it also provides more flexibility. If you only want the script to check for new logins, say every 5 minutes, this would return them all.Great script! But why only the last log message is send by e-mail? How to set that script to send all monitored messages from last change?
Are You planning to public taht new script at this topic/forum? It would be great:)I will work on a new version to incorporate this.
# BEGIN SETUP
:local scheduleName "mySchedule"
:local emailAddress "user@email.com"
:local startBuf [:toarray [/log find message~"logged in" || message~"login failure"]]
:local removeThese {"telnet";"whatever string you want"}
# END SETUP
# warn if schedule does not exist
:if ([:len [/system scheduler find name="$scheduleName"]] = 0) do={
/log warning "[LOGMON] ERROR: Schedule does not exist. Create schedule and edit script to match name"
}
# get last time
:local lastTime [/system scheduler get [find name="$scheduleName"] comment]
# for checking time of each log entry
:local currentTime
# log message
:local message
# final output
:local output
:local keepOutput false
# if lastTime is empty, set keepOutput to true
:if ([:len $lastTime] = 0) do={
:set keepOutput true
}
:local counter 0
# loop through all log entries that have been found
:foreach i in=$startBuf do={
# loop through all removeThese array items
:local keepLog true
:foreach j in=$removeThese do={
# if this log entry contains any of them, it will be ignored
:if ([/log get $i message] ~ "$j") do={
:set keepLog false
}
}
:if ($keepLog = true) do={
:set message [/log get $i message]
# LOG DATE
# depending on log date/time, the format may be different. 3 known formats
# format of jan/01/2002 00:00:00 which shows up at unknown date/time. Using as default
:set currentTime [ /log get $i time ]
# format of 00:00:00 which shows up on current day's logs
:if ([:len $currentTime] = 8 ) do={
:set currentTime ([:pick [/system clock get date] 0 11]." ".$currentTime)
} else={
# format of jan/01 00:00:00 which shows up on previous day's logs
:if ([:len $currentTime] = 15 ) do={
:set currentTime ([:pick $currentTime 0 6]."/".[:pick [/system clock get date] 7 11]." ".[:pick $currentTime 7 15])
}
}
# if keepOutput is true, add this log entry to output
:if ($keepOutput = true) do={
:set output ($output.$currentTime." ".$message."\r\n")
}
# if currentTime = lastTime, set keepOutput so any further logs found will be added to output
# reset output in the case we have multiple identical date/time entries in a row as the last matching logs
# otherwise, it would stop at the first found matching log, thus all following logs would be output
:if ($currentTime = $lastTime) do={
:set keepOutput true
:set output ""
}
}
# if this is last log entry
:if ($counter = ([:len $startBuf]-1)) do={
# If keepOutput is still false after loop, this means lastTime has a value, but a matching currentTime was never found.
# This can happen if 1) The router was rebooted and matching logs stored in memory were wiped, or 2) An item is added
# to the removeThese array that then ignores the last log that determined the lastTime variable.
# This resets the comment to nothing. The next run will be like the first time, and you will get all matching logs
:if ($keepOutput = false) do={
# if previous log was found, this will be our new lastTime entry
:if ([:len $message] > 0) do={
:set output ($output.$currentTime." ".$message."\r\n")
}
}
}
:set counter ($counter + 1)
}
# If we have output, save new date/time, and send email
if ([:len $output] > 0) do={
/system scheduler set [find name="$scheduleName"] comment=$currentTime
/tool e-mail send to="$emailAddress" subject="MikroTik alert $currentTime" body="$output"
/log info "[LOGMON] New logs found, send email"
}
[spippan@RB2011_sp-private] /user> print
Flags: X - disabled
# NAME GROUP ADDRESS LAST-LOGG
0 X ;;; system default user
admin_old full nov/26/20
1 spippan full mar/11/20
2 spippan_ssh full mar/11/20
[spippan@RB2011_sp-private] /user>
So, you are using the hotspot, but you don't want any hotspot logins found by the script, only logins directly to the router, right? Generally you would compare the normal login logs with the hotspot login logs to determine what string you can put into the removeThese array to filter out the hotspot logs, but in this case it would be better to filter by the topic rather than the log... but this is not built into the script. It could be easily incorporated, something like this:1 check ("realize") when a user logs on to the ROUTER (not hotspot! no hotspot use is intended at all)
:local removeTopic {"hotspot"}
:foreach j in=$removeTopic do={
# if this log topic is in the removeTopic array, it will be ignored
:if ([/log get $i topic] ~ "$j") do={
:set keepLog false
}
}
hi and thanks for the reply!So, you are using the hotspot, but you don't want any hotspot logins found by the script, only logins directly to the router, right? Generally you would compare the normal login logs with the hotspot login logs to determine what string you can put into the removeThese array to filter out the hotspot logs, but in this case it would be better to filter by the topic rather than the log... but this is not built into the script. It could be easily incorporated, something like this:1 check ("realize") when a user logs on to the ROUTER (not hotspot! no hotspot use is intended at all)
HTH
/user print
The script was designed to do #1, and since you're not using the hotspot, that won't matter. If you know how to do 2 and 3, then they would need to be adapted into the script.so my question is:
can i/we use this script (or edit it) to do following steps:
1 check ("realize") when a user logs on to the ROUTER (not hotspot! no hotspot use is intended at all)
2 on succesful login get the IP and name of the active user (as in "/user active get 0 address")
3 add its IP address to the whitelist for a timeout of, let's say 2h (or whatever disired)
i know how to achieve 2 and 3 but i'm completely stuck on point 1
The script was designed to do #1, and since you're not using the hotspot, that won't matter. If you know how to do 2 and 3, then they would need to be adapted into the script.so my question is:
can i/we use this script (or edit it) to do following steps:
1 check ("realize") when a user logs on to the ROUTER (not hotspot! no hotspot use is intended at all)
2 on succesful login get the IP and name of the active user (as in "/user active get 0 address")
3 add its IP address to the whitelist for a timeout of, let's say 2h (or whatever disired)
i know how to achieve 2 and 3 but i'm completely stuck on point 1
# BEGIN SETUP
:local scheduleName "Send Login alert"
:local emailAddress1 "<redacted>.com"
:local emailAddress2 "<redacted>.org"
:local startBuf [:toarray [/log find message~"logged in" || message~"login failure" || message~"logged out" || message~"Long Port Knock step x"]]
:local removeThese {"zippo";"whatever string you want"}
# END SETUP
# warn if schedule does not exist
:if ([:len [/system scheduler find name="$scheduleName"]] = 0) do={
/log warning "[LOGMON] ERROR: Schedule does not exist. Create schedule and edit script to match name"
}
# get last time
:local lastTime [/system scheduler get [find name="$scheduleName"] comment]
# for checking time of each log entry
:local currentTime
# log message
:local message
# final output
:local output
:local keepOutput false
# if lastTime is empty, set keepOutput to true
:if ([:len $lastTime] = 0) do={
:set keepOutput true
}
:local counter 0
# loop through all log entries that have been found
:foreach i in=$startBuf do={
# loop through all removeThese array items
:local keepLog true
:foreach j in=$removeThese do={
# if this log entry contains any of them, it will be ignored
:if ([/log get $i message] ~ "$j") do={
:set keepLog false
}
}
:if ($keepLog = true) do={
:set message [/log get $i message]
# LOG DATE
# depending on log date/time, the format may be different. 3 known formats
# format of jan/01/2002 00:00:00 which shows up at unknown date/time. Using as default
:set currentTime [ /log get $i time ]
# format of 00:00:00 which shows up on current day's logs
:if ([:len $currentTime] = 8 ) do={
:set currentTime ([:pick [/system clock get date] 0 11]." ".$currentTime)
} else={
# format of jan/01 00:00:00 which shows up on previous day's logs
:if ([:len $currentTime] = 15 ) do={
:set currentTime ([:pick $currentTime 0 6]."/".[:pick [/system clock get date] 7 11]." ".[:pick $currentTime 7 15])
}
}
# if keepOutput is true, add this log entry to output
:if ($keepOutput = true) do={
:set output ($output.$currentTime." ".$message."\r\n")
}
# if currentTime = lastTime, set keepOutput so any further logs found will be added to output
# reset output in the case we have multiple identical date/time entries in a row as the last matching logs
# otherwise, it would stop at the first found matching log, thus all following logs would be output
:if ($currentTime = $lastTime) do={
:set keepOutput true
:set output ""
}
}
# if this is last log entry
:if ($counter = ([:len $startBuf]-1)) do={
# If keepOutput is still false after loop, this means lastTime has a value, but a matching currentTime was never found.
# This can happen if 1) The router was rebooted and matching logs stored in memory were wiped, or 2) An item is added
# to the removeThese array that then ignores the last log that determined the lastTime variable.
# This resets the comment to nothing. The next run will be like the first time, and you will get all matching logs
:if ($keepOutput = false) do={
# if previous log was found, this will be our new lastTime entry
:if ([:len $message] > 0) do={
:set output ($output.$currentTime." ".$message."\r\n")
}
}
}
:set counter ($counter + 1)
}
# If we have output, save new date/time, and send email
if ([:len $output] > 0) do={
/log info "[LOGMON] New login or logout logs found, sending E-Mail."
/system scheduler set [find name="$scheduleName"] comment=$currentTime
/tool e-mail send to="$emailAddress1" subject="MikroTik RB750Gr3 #2 Log in or out alert $currentTime" body="Sent from Microtik RB750Gr3 #2 \n \n $output"
/tool e-mail send to="$emailAddress2" subject="MikroTik RB750Gr3 #2 Log in or out alert $currentTime" body="Sent from Microtik RB750Gr3 #2 \n \n $output"
/log info "Login / Logout update E-Mail sent."
}
yes, you can add (or replace e-mail) notification to telegram. i use it with my RBsusing this script with telegram ?
I don't do it in Mangle rules. I do it in firewall rules. For each step, there are two rules. The second one sets the source address to the address list Long Knock-x (where x is the step number). Except for the first step, the source address must be in the previous steps source list. Successfully meeting the criteria for each step results in a leg entry. Since the source computer does not get a response, it will continue to send packets which would keep creating log entries. To prevent that, the first rule looks for packets that meet the port knock step one and if the address is in the address list, is simply drops the packet. Obviously the IPs and ports shown are not the actual numbers...I've chosen to use this script to give me an alert when someone does a port-knock to request access to the network. We have RB750Gr3 on site at customer locations -- we do the port knock and want to see the customer an email with the log so they know when we accessed their network.
I've created a Mangle rule on Prerouting chain to add SRC to address list on port knock -- this is working fine.
I've set the Mangle rule to log with a prefix of "knock" -- again, working fine.
However, when we do the port knock we see 4-5 lines of log each time we knock. Also, sometimes there are logs for "knock" even when we didn't do the knock. Is there any way to reduce the number of lines for this? I think it's from TCP ACKs or something possibly.
add action=drop chain=input comment="Long Port Knock step 1 log blocker" \
dst-address=8.7.4.3 dst-port=54321 in-interface=VLAN_200 \
protocol=tcp src-address-list="Long Knock-1"
add action=add-src-to-address-list address-list="Long Knock-1" \
address-list-timeout=15s chain=input comment=\
"Long Port Knock setup step 1" dst-address=8.7.4.3 dst-port=54321 \
in-interface=VLAN_200 log=yes log-prefix="Long Port Knock step 1" \
protocol=tcp
add action=drop chain=input comment="Long Port Knock step 2 log blocker" \
dst-address=8.7.4.2 dst-port=45123 in-interface=VLAN_200 protocol=\
tcp src-address-list="Long Knock-2"
add action=add-src-to-address-list address-list="Long Knock-2" \
address-list-timeout=15s chain=input comment=\
"Long Port Knock setup step 2" dst-address=8.7.4.2 dst-port=45123 \
in-interface=VLAN_200 log=yes log-prefix="Long Port Knock step 2" \
protocol=tcp src-address-list="Long Knock-1"
add action=drop chain=input comment="Long Port Knock step 3 log blocker" \
dst-address=8.7.4.1 dst-port=32145 in-interface=VLAN_200 \
protocol=tcp src-address-list="Long Knock-3"
add action=add-src-to-address-list address-list="Long Knock-3" \
address-list-timeout=15s chain=input comment=\
"Long Port Knock setup step 3" dst-address=8.7.4.1 dst-port=32145 \
in-interface=VLAN_200 log=yes log-prefix="Long Port Knock step 3" \
protocol=tcp src-address-list="Long Knock-2"
add action=drop chain=input comment="Long Port Knock step 4 log blocker" \
dst-address=8.7.4.5 dst-port=14725 in-interface=VLAN_200 protocol=\
tcp src-address-list=Safe
add action=add-src-to-address-list address-list=Safe address-list-timeout=1m \
chain=input comment="Long Port Knock setup step 4" dst-address=\
8.7.4.5 dst-port=14725 in-interface=VLAN_200 log=yes log-prefix=\
"Long Port Knock step 4" protocol=tcp src-address-list="Long Knock-3"
Makes total sence, thanks!I don't do it in Mangle rules. I do it in firewall rules. For each step, there are two rules. The second one sets the source address to the address list Long Knock-x (where x is the step number). Except for the first step, the source address must be in the previous steps source list. Successfully meeting the criteria for each step results in a leg entry. Since the source computer does not get a response, it will continue to send packets which would keep creating log entries. To prevent that, the first rule looks for packets that meet the port knock step one and if the address is in the address list, is simply drops the packet. Obviously the IPs and ports shown are not the actual numbers...I've chosen to use this script to give me an alert when someone does a port-knock to request access to the network. We have RB750Gr3 on site at customer locations -- we do the port knock and want to see the customer an email with the log so they know when we accessed their network.
I've created a Mangle rule on Prerouting chain to add SRC to address list on port knock -- this is working fine.
I've set the Mangle rule to log with a prefix of "knock" -- again, working fine.
However, when we do the port knock we see 4-5 lines of log each time we knock. Also, sometimes there are logs for "knock" even when we didn't do the knock. Is there any way to reduce the number of lines for this? I think it's from TCP ACKs or something possibly.
The script that I posted on June 21st looks for both the log on and off messages in the log, but also the "Long Port Knock step 4" message.Code: Select alladd action=drop chain=input comment="Long Port Knock step 1 log blocker" \ dst-address=8.7.4.3 dst-port=54321 in-interface=VLAN_200 \ protocol=tcp src-address-list="Long Knock-1" add action=add-src-to-address-list address-list="Long Knock-1" \ address-list-timeout=15s chain=input comment=\ "Long Port Knock setup step 1" dst-address=8.7.4.3 dst-port=54321 \ in-interface=VLAN_200 log=yes log-prefix="Long Port Knock step 1" \ protocol=tcp add action=drop chain=input comment="Long Port Knock step 2 log blocker" \ dst-address=8.7.4.2 dst-port=45123 in-interface=VLAN_200 protocol=\ tcp src-address-list="Long Knock-2" add action=add-src-to-address-list address-list="Long Knock-2" \ address-list-timeout=15s chain=input comment=\ "Long Port Knock setup step 2" dst-address=8.7.4.2 dst-port=45123 \ in-interface=VLAN_200 log=yes log-prefix="Long Port Knock step 2" \ protocol=tcp src-address-list="Long Knock-1" add action=drop chain=input comment="Long Port Knock step 3 log blocker" \ dst-address=8.7.4.1 dst-port=32145 in-interface=VLAN_200 \ protocol=tcp src-address-list="Long Knock-3" add action=add-src-to-address-list address-list="Long Knock-3" \ address-list-timeout=15s chain=input comment=\ "Long Port Knock setup step 3" dst-address=8.7.4.1 dst-port=32145 \ in-interface=VLAN_200 log=yes log-prefix="Long Port Knock step 3" \ protocol=tcp src-address-list="Long Knock-2" add action=drop chain=input comment="Long Port Knock step 4 log blocker" \ dst-address=8.7.4.5 dst-port=14725 in-interface=VLAN_200 protocol=\ tcp src-address-list=Safe add action=add-src-to-address-list address-list=Safe address-list-timeout=1m \ chain=input comment="Long Port Knock setup step 4" dst-address=\ 8.7.4.5 dst-port=14725 in-interface=VLAN_200 log=yes log-prefix=\ "Long Port Knock step 4" protocol=tcp src-address-list="Long Knock-3"
If we have output, save new date/time, and send email
if ([:len $output] > 0) do={
/file print file=accesslog
/file set [find name="accesslog"] contents="$output"
/system scheduler set [find name="$scheduleName"] comment=$currentTime
/tool e-mail send to="$emailAddress" subject="$output"" file="accesslog";
/log info "[LOGMON] New logs found, send email";
/file remove accesslog.txt;
}
# jul/16/2017 20:23:32 by RouterOS 6.39.2
# software id = 9Z71-UNW2
#
# NAME TYPE SIZE CREATION-TIME
0 flash disk dec/31/1969 20:00:01
1 disk1 disk dec/31/1969 20:00:02
2 flash/skins directory dec/31/1969 20:00:02
/file set [find name="accesslog"] contents="test123"
:local currentBuf [ :toarray [ /log find message~"logged in from" || message~"login failure" ] ] ;
And when you connect to the router, says:user logged in, <ipaddress>
user XXXX logged in from <ipaddress> via winbox or whatever.
MMM MMM KKK TTTTTTTTTTT KKK
MMMM MMMM KKK TTTTTTTTTTT KKK
MMM MMMM MMM III KKK KKK RRRRRR OOOOOO TTT III KKK KKK
MMM MM MMM III KKKKK RRR RRR OOO OOO TTT III KKKKK
MMM MMM III KKK KKK RRRRRR OOO OOO TTT III KKK KKK
MMM MMM III KKK KKK RRR RRR OOOOOO TTT III KKK KKK
MikroTik RouterOS 6.43.2 (c) 1999-2018 http://www.mikrotik.com/
[?] Gives the list of available commands
command [?] Gives help on the command and list of arguments
[Tab] Completes the command/word. If the input is ambiguous,
a second [Tab] gives possible options
/ Move up to base level
.. Move up one level
/command Use command at the base level
# BEGIN SETUP
:local TelegramBotToken "110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw"
:local TelegramChatId "-1501445581143"
:local RemoveThese {"telnet";"whatever string you want"}
# END SETUP
# final output
:local output
:local EventMessage
:local EventTime
:local KeepOutput false
:local KeepInLog true
#Get id of all log entry
:local StartBuf [:toarray [/log find]]
:global LastId
if ([:len $LastId] < 1) do={
:set output ("Last log id not found. Maybe Router was rebooted%0A")
if ([:len $StartBuf] > 0) do={:set LastId [:pick $StartBuf ([:len $StartBuf]-1)]}
}
:foreach i in=$StartBuf do={
if ($KeepOutput = true) do={
:set EventMessage [/log get $i message]
:set EventTime [/log get $i time]
# loop through all RemoveThese array items. if this log entry contains any of them, it will be ignored
:set KeepInLog true
:foreach j in=$RemoveThese do={:if ($EventMessage ~ "$j") do={:set KeepInLog false}}
if ($KeepInLog = true) do={:set output ($output.$EventTime." ".$EventMessage."%0A")}
} else={
if ($i = $LastId) do={:set KeepOutput true}
}
}
:set LastId [:pick $StartBuf ([:len $StartBuf]-1)]
# If we have output send message
if ([:len $output] > 0) do={
:set output ([/system clock get date]." log from ".[/system identity get name]."%0A".$output)
/tool fetch url="https://api.telegram.org/bot$TelegramBotToken/sendmessage\?chat_id=$TelegramChatId&text=$output" keep-result=no
}
Hi, first thanks for script im new and i learn with it, but i have a problem. I have RouterOS 6.45.7 and i only change this line:Thia is mine. This is a variation of the code posted on 17 December 2014 by skotI copied this from my RB750Gr3 running 6.39.1Code: Select all# BEGIN SETUP :local scheduleName "Send Login alert" :local emailAddress1 "<redacted>.com" :local emailAddress2 "<redacted>.org" :local startBuf [:toarray [/log find message~"logged in" || message~"login failure" || message~"logged out" || message~"Long Port Knock step x"]] :local removeThese {"zippo";"whatever string you want"} # END SETUP # warn if schedule does not exist :if ([:len [/system scheduler find name="$scheduleName"]] = 0) do={ /log warning "[LOGMON] ERROR: Schedule does not exist. Create schedule and edit script to match name" } # get last time :local lastTime [/system scheduler get [find name="$scheduleName"] comment] # for checking time of each log entry :local currentTime # log message :local message # final output :local output :local keepOutput false # if lastTime is empty, set keepOutput to true :if ([:len $lastTime] = 0) do={ :set keepOutput true } :local counter 0 # loop through all log entries that have been found :foreach i in=$startBuf do={ # loop through all removeThese array items :local keepLog true :foreach j in=$removeThese do={ # if this log entry contains any of them, it will be ignored :if ([/log get $i message] ~ "$j") do={ :set keepLog false } } :if ($keepLog = true) do={ :set message [/log get $i message] # LOG DATE # depending on log date/time, the format may be different. 3 known formats # format of jan/01/2002 00:00:00 which shows up at unknown date/time. Using as default :set currentTime [ /log get $i time ] # format of 00:00:00 which shows up on current day's logs :if ([:len $currentTime] = 8 ) do={ :set currentTime ([:pick [/system clock get date] 0 11]." ".$currentTime) } else={ # format of jan/01 00:00:00 which shows up on previous day's logs :if ([:len $currentTime] = 15 ) do={ :set currentTime ([:pick $currentTime 0 6]."/".[:pick [/system clock get date] 7 11]." ".[:pick $currentTime 7 15]) } } # if keepOutput is true, add this log entry to output :if ($keepOutput = true) do={ :set output ($output.$currentTime." ".$message."\r\n") } # if currentTime = lastTime, set keepOutput so any further logs found will be added to output # reset output in the case we have multiple identical date/time entries in a row as the last matching logs # otherwise, it would stop at the first found matching log, thus all following logs would be output :if ($currentTime = $lastTime) do={ :set keepOutput true :set output "" } } # if this is last log entry :if ($counter = ([:len $startBuf]-1)) do={ # If keepOutput is still false after loop, this means lastTime has a value, but a matching currentTime was never found. # This can happen if 1) The router was rebooted and matching logs stored in memory were wiped, or 2) An item is added # to the removeThese array that then ignores the last log that determined the lastTime variable. # This resets the comment to nothing. The next run will be like the first time, and you will get all matching logs :if ($keepOutput = false) do={ # if previous log was found, this will be our new lastTime entry :if ([:len $message] > 0) do={ :set output ($output.$currentTime." ".$message."\r\n") } } } :set counter ($counter + 1) } # If we have output, save new date/time, and send email if ([:len $output] > 0) do={ /log info "[LOGMON] New login or logout logs found, sending E-Mail." /system scheduler set [find name="$scheduleName"] comment=$currentTime /tool e-mail send to="$emailAddress1" subject="MikroTik RB750Gr3 #2 Log in or out alert $currentTime" body="Sent from Microtik RB750Gr3 #2 \n \n $output" /tool e-mail send to="$emailAddress2" subject="MikroTik RB750Gr3 #2 Log in or out alert $currentTime" body="Sent from Microtik RB750Gr3 #2 \n \n $output" /log info "Login / Logout update E-Mail sent." }
I have the exact same script on my RB750r2 running 6.38.5
This script runs every one minute. This will send me an E-Mail message when someone logs into the router, logs out, or completes my Port Knock security access.
When I logged into the Gr3 to copy this code, I shortly thereafter received an E-Mail with a subject of:
MikroTik RB750Gr3 #2 Log in or out alert jun/21/2017 19:56:05
And the following text:
Sent from Microtik RB750Gr3 #2
jun/21/2017 19:56:05 user <redacted here> logged in from 192.168.101.42 via winbox
script error: no such item (4)
:local date ([:pick [/system clock get date] 7 11] ."-". [:pick [/system clock get date] 0 3]);
/log print append follow-only file="MicroSD/export-security-log-$date" where topics~"firewall" message ~"export: security"