├── README.md └── danger.rsc /README.md: -------------------------------------------------------------------------------- 1 | # Cкрипт блокировки опасных IPv4 адресов, с которых пытались произвести подключение к роутеру. 2 | 3 | Скрипт автоматически блокирует IPv4 адреса злоумышленников, прощупывающих маршрутизаторы Mikrotik из внешних сетей. Скрипт не имеет зависимостей от сторонних функций и скриптов. Настройка подразумевает правку значений локальных переменных в начале тела скрипта, краткое описание которых присутствует в комментариях. Тело скрипта необходимо закинуть в 'System/Scripts', запустить вручную из окна терминала командой '/system script run <имя скрипта>', ознакомиться с представленной информацией и при необходимости подправить рабочие настройки. Далее производится настройка запуска по расписанию из 'System/Scheduler' с необходимым периодом времени (типовое значение составляет единицы минут). 4 | 5 | Работа скрипта сводится к формированию чёрного списка IPv4 адресов для их блокировки. 6 | Формирование чёрного списка происходит двумя разными независимыми способами: 7 | 1. на основе анализа записей журнала устройства 8 | 2. при помощи преднастроенных правил Firewall 9 | 10 | 1й способ срабатывает каждый раз при запуске скрипта. При первом запуске проверяется весь журнал устройства, а при последующих запусках проверяется только непроверенная часть журнала. Так сделано для увеличения скорости последующих проверок журнала. 11 | 12 | 2й способ изначально отключен, это сделано из соображения, что Firewall может быть уже настроен и вмешательство в его работу не желательно. 13 | Активация 2го способа производится вручную, путём присвоения переменной 'fwUsag' значения 'true'. 14 | После активации 2го способа скрипт настраивает Firewall по принципу: "запрещено всё, что не разрешено" и с этого момента, даже если скрипт не запущен, все попытки из вне прощупать роутер будут считаться несанкционированными. 15 | Попутно, при задействовании 2го способа, при каждом запуске скрипт проверяет наличие преднастроенных правил Firewall и в случае их отсутствия производит установку недостающих. Поиск недостающих правил Firewall скрипт производит по комментариям в списках: 'Firewall/Filter Rules', 'Firewall/Raw', 'Firewall/Layer7 Protocols'. После установки правил Firewall пользователю необходимо расположить их вручную согласно своим предпочтениям. Для исключения неожиданной блокировки при установке новых правил, правила блокировки устанавливаются ОТКЛЮЧЕННЫМИ (!!!). Перемещение и активацию правил блокировки пользователь делает самостоятельно, вручную. Настройка правил FIREWALL производится в активном режиме 'Safe Mode' на случай неожиданной потери связи с роутером и для автоматического отката настроек в исходное состояние. По окончании настроек режим 'Safe Mode' необходимо деактивировать. Если правила блокировки оставить отключенными - скрипт будет об этом оповещать. 16 | 17 | В итоге, все обращения к роутеру, не прошедшие проверку Firewall или отображённые в журнале устройства, как попытки несанкционированного доступа, попадают в черный список и блокируются на время, заданное в переменной 'timeout'. Типовое количество записей в чёрном списке при блокировке на 8 часов может составлять от нескольких сотен до нескольких тысяч (!!!) записей, и напрямую зависит от активности злоумышленников. 18 | 19 | Обкатка скрипта проводилась на актуальных версиях RouterOS 6.49.++ и 7.16.++ . 20 | 21 | Известные проблемы: 22 | * работа скрипта может завершаться ошибкой, при включенном контроле правил Firewall и наличии в списке одинаковых правил с отличающимися комментариями. 23 | * для предотвращения блокировки скриптом адресов, влияющих на работоспособность сетевого оборудования (DNS провайдера, адрес вышестоящего узла и т.п.), имеет смысл заранее внести их в белый список. 24 | 25 | Ветка форума с обсуждением скрипта: https://forummikrotik.ru/viewtopic.php?t=11586 26 | 27 | Используете скрипт - отметьте это звездочкой, Вам не сложно, а мне приятно! 28 | -------------------------------------------------------------------------------- /danger.rsc: -------------------------------------------------------------------------------- 1 | # Script for searching and blocking dangerous IPv4 addresses 2 | # Script uses ideas by podarok66 evgeniy.demin Virtue tgrba denismikh MMAXSIM andrey-d GregoryGost Chupakabra303 Jotne rextended drPioneer 3 | # https://github.com/drpioneer/MikrotikBlockDangerAddresses/blob/master/danger.rsc 4 | # https://forummikrotik.ru/viewtopic.php?p=70410#p70410 5 | # tested on ROS 6.49.17 & 7.17 6 | # updated 2025/02/11 7 | 8 | :global scriptBlckr; # flag of the running script (false=>in progress / true=>idle) 9 | :global timeBlckr; # time of the last log check (in unix time) 10 | :do { 11 | :local timeout "8h"; # timeout of blacklist ("1w" "2d" "3h" "4m" "5s" "0w0d8h0m0s" etc...) 12 | :local wanLst ""; # name of external interface list ("internet" "WAN" or others=>manual input value; ""=>automatic value selection) 13 | :local fwUsag false; # checking & installing firewall rules (false or true) 14 | :local xtreme false; # setting log scan level (false=>usual option or true=>extremal option) 15 | :local logEnt false; # maintaining log entries (false or true) 16 | :local stcAdr false; # converting blacklist from dynamic to static (false or true) 17 | :local nameBL "BlockDangerAddress"; # name of blacklist 18 | :local nameWL "WhiteList"; # name of whitelist 19 | :local cmntBL "dropping dangerous addresses"; # comment for blacklist rule 20 | :local cmntWL "white list of IP-addresses"; # comment for whitelist rule 21 | :local debug false; # debug mode (true=>is active or false=>is inactive) 22 | 23 | # time translation function to UNIX time # https://forum.mikrotik.com/viewtopic.php?t=75555#p994849 24 | :global T2UDNG do={ # $1-date/time in any format: "hh:mm:ss","mmm/dd hh:mm:ss","mmm/dd/yyyy hh:mm:ss","yyyy-mm-dd hh:mm:ss","mm-dd hh:mm:ss" 25 | :local dTime [:tostr $1]; :local yesterDay false; /system clock 26 | :local cYear [get date]; :if ($cYear~"....-..-..") do={:set cYear [:pick $cYear 0 4]} else={:set cYear [:pick $cYear 7 11]} 27 | :if ([:len $dTime]=10 or [:len $dTime]=11) do={:set dTime "$dTime 00:00:00"} 28 | :if ([:len $dTime]=15) do={:set dTime "$[:pick $dTime 0 6]/$cYear $[:pick $dTime 7 15]"} 29 | :if ([:len $dTime]=14) do={:set dTime "$cYear-$[:pick $dTime 0 5] $[:pick $dTime 6 14]"} 30 | :if ([:len $dTime]=8) do={:if ([:totime $1]>[get time]) do={:set yesterDay true}; :set dTime "$[get date] $dTime"} 31 | :if ([:tostr $1]="") do={:set dTime ("$[get date] $[get time]")} 32 | :local vDate [:pick $dTime 0 [:find $dTime " " -1]]; :local vTime [:pick $dTime ([:find $dTime " " -1]+1) [:len $dTime]] 33 | :local vGmt [get gmt-offset]; :if ($vGmt>0x7FFFFFFF) do={:set vGmt ($vGmt-0x100000000)}; :if ($vGmt<0) do={:set vGmt ($vGmt*-1)} 34 | :local arrMn [:toarray "0,0,31,59,90,120,151,181,212,243,273,304,334"]; :local vdOff [:toarray "0,4,5,7,8,10"] 35 | :local month [:tonum [:pick $vDate ($vdOff->2) ($vdOff->3)]] 36 | :if ($vDate~".../../....") do={ 37 | :set vdOff [:toarray "7,11,1,3,4,6"] 38 | :set month ([:find "xxanebarprayunulugepctovecANEBARPRAYUNULUGEPCTOVEC" [:pick $vDate ($vdOff->2) ($vdOff->3)] -1]/2) 39 | :if ($month>12) do={:set month ($month-12)}} 40 | :local year [:pick $vDate ($vdOff->0) ($vdOff->1)] 41 | :if ((($year-1968)%4)=0) do={:set ($arrMn->1) -1; :set ($arrMn->2) 30} 42 | :local toTd ((($year-1970)*365)+(($year-1968)>>2)+($arrMn->$month)+([:pick $vDate ($vdOff->4) ($vdOff->5)]-1)) 43 | :if ($yesterDay) do={:set toTd ($toTd-1)}; # bypassing ROS6.xx time format problem after 00:00:00 44 | :return (((((($toTd*24)+[:pick $vTime 0 2])*60)+[:pick $vTime 3 5])*60)+[:pick $vTime 6 8]-$vGmt)} 45 | 46 | # time conversion function from UNIX time # https://forum.mikrotik.com/viewtopic.php?p=977170#p977170 47 | :global U2TDNG do={ # $1-UnixTime $2-OnlyTime 48 | :local ZeroFill do={:return [:pick (100+$1) 1 3]} 49 | :local prMntDays [:toarray "0,0,31,59,90,120,151,181,212,243,273,304,334"] 50 | :local vGmt [:tonum [/system clock get gmt-offset]] 51 | :if ($vGmt>0x7FFFFFFF) do={:set vGmt ($vGmt-0x100000000)} 52 | :if ($vGmt<0) do={:set vGmt ($vGmt*-1)} 53 | :local tzEpoch ($vGmt+[:tonum $1]) 54 | :if ($tzEpoch<0) do={:set tzEpoch 0}; # unsupported negative unix epoch 55 | :local yearStamp (1970+($tzEpoch/31536000)) 56 | :local tmpLeap (($yearStamp-1968)>>2) 57 | :if ((($yearStamp-1968)%4)=0) do={:set ($prMntDays->1) -1; :set ($prMntDays->2) 30} 58 | :local tmpSec ($tzEpoch%31536000) 59 | :local tmpDays (($tmpSec/86400)-$tmpLeap) 60 | :if ($tmpSec<(86400*$tmpLeap) && (($yearStamp-1968)%4)=0) do={ 61 | :set tmpLeap ($tmpLeap-1); :set ($prMntDays->1) 0; :set ($prMntDays->2) 31; :set tmpDays ($tmpDays+1)} 62 | :if ($tmpSec<(86400*$tmpLeap)) do={:set yearStamp ($yearStamp-1); :set tmpDays ($tmpDays+365)} 63 | :local mnthStamp 12; :while (($prMntDays->$mnthStamp)>$tmpDays) do={:set mnthStamp ($mnthStamp-1)} 64 | :local dayStamp [$ZeroFill (($tmpDays+1)-($prMntDays->$mnthStamp))] 65 | :local timeStamp (00:00:00+[:totime ($tmpSec%86400)]) 66 | :if ([:len $2]=0) do={:return "$yearStamp/$[$ZeroFill $mnthStamp]/$[$ZeroFill $dayStamp] $timeStamp"} else={:return "$timeStamp"}} 67 | 68 | # search of interface-list gateway 69 | :local GwFinder do={ # no input parameters 70 | :local routeISP [/ip route find dst-address=0.0.0.0/0 active=yes]; :if ([:len $routeISP]=0) do={:return ""} 71 | :set routeISP "/ip route get $routeISP"; /interface 72 | :local routeGW {"[$routeISP vrf-interface]";"[$routeISP immediate-gw]";"[$routeISP gateway-status]"} 73 | :foreach ifLstMmb in=[list member find] do={ 74 | :local ifIfac [list member get $ifLstMmb interface]; :local ifList [list member get $ifLstMmb list] 75 | :local brName ""; :do {:set brName [bridge port get [find interface=$ifIfac] bridge]} on-error={} 76 | :foreach answer in=$routeGW do={ 77 | :local gw ""; :do {:set gw [:tostr [[:parse $answer]]]} on-error={} 78 | :if ([:len $gw]>0 && $gw~$ifIfac or [:len $brName]>0 && $gw~$brName) do={:return $ifList}}} 79 | :return ""} 80 | 81 | # checking & installing optional firewall rules 82 | :local ChkFWRul do={ # $1-FWusage $2-wanLst $3-nameBL $4-nameWL $5-cmntRuleBL $6-cmntRuleWL $7-timeout 83 | 84 | # string parsing function 85 | :local StrParser do={ # $1-string $2-desired parameter $3-separator 86 | :if ([:len [:find $1 $2 -1]]=0) do={:return ""} 87 | :local bgn ([:find $1 $2 -1]+[:len $2] +1); :local end [:find $1 "\"" $bgn] 88 | :if ([:len $3]!=0) do={ 89 | :if ([:len [:find $1 $3 $bgn]]=0) do={:set end [:find $1 "\"" $bgn]} else={:set end [:find $1 $3 $bgn]}} 90 | :if ($end<$bgn) do={:set end ($bgn+1)} 91 | :return [:pick $1 $bgn $end]} 92 | 93 | :global T2UDNG; :global U2TDNG 94 | :if ($1) do={ 95 | /; /ip firewall layer7-protocol; find; :local cmnt "" 96 | :local fwL7prt [:toarray { 97 | "name=CVE-2023-28771 comment=\"IPsec payload missing: SA\" regexp=\";bash -c \\\"(curl|wget) (http:\\\\/\\\\/|)[0-9]+\\\\.[0-9]+\\\\.[0-9]+\\\\.[0-9]\""}] 98 | :foreach payLoad in=$fwL7prt do={ 99 | :set cmnt [$StrParser [:tostr $payLoad] "comment="] 100 | :if ([:len [/ip firewall layer7-protocol find comment=$cmnt]]=0) do={ 101 | [:parse "/ip firewall layer7-protocol add $payLoad"] 102 | :put "$[$U2TDNG [$T2UDNG]]\tFirewall layer7 protocol with comment '$cmnt' not found.\r\n$[$U2TDNG [$T2UDNG]]\tAdded a regular expression"}} 103 | /; /ip firewall filter; find 104 | :local fwFltRul [:toarray { 105 | "action=accept chain=input comment=\"defconf: accept established,related,untracked\" connection-state=established,related,untracked"; 106 | "action=drop chain=input comment=\"defconf: drop invalid\" connection-state=invalid"; 107 | "action=accept chain=input comment=\"accept ICMP from external interface\" in-interface-list=$2 limit=50/5s,2:packet protocol=icmp"; 108 | "action=accept chain=input comment=\"defconf: accept ICMP\" disabled=yes protocol=icmp"; 109 | "action=accept chain=input comment=\"defconf: accept to local loopback (for CAPsMAN)\" dst-address=127.0.0.1"; 110 | "action=accept chain=forward comment=\"defconf: accept in ipsec policy\" ipsec-policy=in,ipsec"; 111 | "action=accept chain=forward comment=\"defconf: accept out ipsec policy\" ipsec-policy=out,ipsec"; 112 | "action=fasttrack-connection chain=forward comment=\"defconf: fasttrack\" connection-state=established,related"; 113 | "action=accept chain=forward comment=\"defconf: accept established,related, untracked\" connection-state=established,related,untracked"; 114 | "action=drop chain=forward comment=\"defconf: drop invalid\" connection-state=invalid"; 115 | "action=drop chain=forward comment=\"defconf: drop all from WAN not DSTNATed\" connection-nat-state=!dstnat connection-state=new in-interface-list=$2"; 116 | "action=jump chain=input comment=\"packet analysis for attacks\" in-interface-list=$2 jump-target=TARPIT protocol=tcp src-address-list=$3"; 117 | "action=tarpit chain=TARPIT comment=\"slow down attack to router\" limit=10,10:packet protocol=tcp"; 118 | "action=drop chain=TARPIT comment=\"drop rest of TCP attack\" protocol=tcp"; 119 | "action=drop chain=input comment=\"drop CVE-2023-28771\" connection-state=\"\" dst-port=500 in-interface-list=$2 layer7-protocol=CVE-2023-28771 protocol=udp"; 120 | "action=accept chain=input comment=\"allow DNS request\" in-interface-list=$2 protocol=udp src-port=53"; 121 | "action=accept chain=input comment=\"accept L2TP/IPSec connections\" connection-state=\"\" dst-port=500,1701,4500 in-interface-list=$2 protocol=udp"; 122 | "action=accept chain=input comment=\"accept IPSec-esp connections\" connection-state=\"\" in-interface-list=$2 protocol=ipsec-esp"; 123 | "action=accept chain=input comment=\"accept IPSec-ah connections\" connection-state=\"\" in-interface-list=$2 protocol=ipsec-ah"; 124 | "action=accept chain=input comment=\"accept SSTP connections\" dst-port=443 in-interface-list=$2 protocol=tcp"; 125 | "action=accept chain=input comment=\"accept PPTP TCP connections\" connection-state=\"\" dst-port=1723 in-interface-list=$2 protocol=tcp"; 126 | "action=accept chain=input comment=\"accept PPTP GRE connections\" connection-state=\"\" in-interface-list=$2 protocol=gre"; 127 | "action=accept chain=input comment=\"accept OVPN connections\" connection-state=\"\" disabled=yes dst-port=1194 in-interface-list=$2 protocol=tcp"; 128 | "action=accept chain=forward comment=\"accept SIP UDP packets\" disabled=yes dst-port=5060-5061,5160-5161,10000-20000 in-interface-list=$2 protocol=udp"; 129 | "action=accept chain=forward comment=\"accept SIP TCP packets\" disabled=yes dst-port=5060-5061,5160-5161,10000-20000 in-interface-list=$2 protocol=tcp"; 130 | "action=accept chain=input comment=\"accept to Minecraft server\" disabled=yes dst-port=25565-25566 in-interface-list=$2 protocol=tcp"; 131 | "action=jump chain=input comment=\"brute force protection on specified ports\" connection-state=new dst-port=8291 in-interface-list=$2 jump-target=BruteForce protocol=tcp"; 132 | "action=return chain=BruteForce comment=\"packet analysis for brute force on the specified ports\" dst-limit=4/1m,1,src-address/1m40s"; 133 | "action=add-src-to-address-list chain=BruteForce comment=\"add to BlackList attacker who used specified ports\" address-list=$3 address-list-timeout=$7"; 134 | "action=accept chain=input comment=\"accept WinBox\" dst-port=8291 protocol=tcp in-interface-list=$2"; 135 | "action=add-src-to-address-list chain=input comment=\"add to BlackList attacker who used unopened ports\" address-list=$3 address-list-timeout=$7 dst-address-type=!broadcast in-interface-list=$2"; 136 | "action=drop chain=input comment=\"drop rest of packets\" in-interface-list=$2"}]; 137 | :foreach payLoad in=$fwFltRul do={ 138 | :set cmnt [$StrParser [:tostr $payLoad] "comment="] 139 | :if ([:len [/ip firewall filter find comment=$cmnt]]=0) do={ 140 | [:parse "/ip firewall filter add $payLoad"] 141 | :put "$[$U2TDNG [$T2UDNG]]\tFirewall filter rule with comment '$cmnt' not found, added a rule"}} 142 | /; /ip firewall raw; find 143 | :local fwRawRul [:toarray { 144 | "action=drop chain=prerouting comment=\"drop DNS parasit traffic\" dst-port=53 protocol=udp in-interface-list=$2"}] 145 | :foreach payLoad in=$fwRawRul do={ 146 | :set cmnt [$StrParser [:tostr $payLoad] "comment="] 147 | :if ([:len [/ip firewall raw find comment=$cmnt]]=0) do={ 148 | [:parse "/ip firewall raw add $payLoad"] 149 | :put "$[$U2TDNG [$T2UDNG]]\tFirewall raw rule with comment '$cmnt' not found, added a rule"}}; / 150 | } else={ 151 | :put "$[$U2TDNG [$T2UDNG]]\tATTENTION!!! Firewall rule checking is DISABLED (fwUsag false)" 152 | :put "$[$U2TDNG [$T2UDNG]]\tRecommended to ENABLE (fwUsag true)"} 153 | 154 | # checking & installing mandatory firewall rules 155 | :if ([/ip firewall address-list find list=$4]="") do={/ip firewall address-list add address="input_your_address" list=$4} 156 | /; /ip firewall filter; :local ruleID ""; :local fwFlt [find] 157 | :if ([:len $fwFlt]=0) do={ 158 | add chain=input comment=$6 src-address-list=$4 disabled=no 159 | } else={ 160 | :if ([find src-address-list=$4]="") do={ 161 | :if ([find action~"passthrough" dynamic=yes]="") do={ 162 | add chain=input comment=$6 src-address-list=$4 disabled=no place-before=($fwFlt->0) 163 | } else={ 164 | :set ruleID [$StrParser [:tostr [get [find action~"passthrough" dynamic=yes]]] ".nextid" ";"] 165 | :if ($ruleID!="") do={add chain=input comment=$6 src-address-list=$4 disabled=no place-before=$ruleID}}}} 166 | :if ([find src-address-list=$4 disabled=yes]!="") do={enable [find src-address-list=$4 disabled=yes]} 167 | /; /ip firewall raw; :local fwRaw [find] 168 | :if ([:len $fwRaw]=0) do={ 169 | add action=accept chain=prerouting comment=$6 src-address-list=$4 disabled=no 170 | } else={ 171 | :if ([find src-address-list=$4]="") do={ 172 | :if ([find action~"passthrough" dynamic=yes]="") do={ 173 | add action=accept chain=prerouting comment=$6 src-address-list=$4 disabled=no place-before=($fwRaw->0) 174 | } else={ 175 | :set ruleID [$StrParser [:tostr [get [find action~"passthrough" dynamic=yes]]] ".nextid" ";"] 176 | :if ($ruleID!="") do={add action=accept chain=prerouting comment=$6 src-address-list=$4 disabled=no place-before=$ruleID}}}} 177 | :if ([find src-address-list=$4 disabled=yes]!="") do={enable [find src-address-list=$4 disabled=yes]} 178 | :if ([find src-address-list=$3]="") do={add action=drop chain=prerouting comment=$5 src-address-list=$3 in-interface-list=$2 protocol=!tcp disabled=yes} 179 | :if ([find src-address-list=$3 disabled=yes]!="") do={ 180 | :put "$[$U2TDNG [$T2UDNG]]\tATTENTION!!! RAW-rule for blocking dangerous IPv4 addresses is DISABLED" 181 | :put "$[$U2TDNG [$T2UDNG]]\tCheck rule properties in 'IP-Firewall-Raw'" 182 | /log warning "ATTENTION!!! Rule for blocking dangerous IPv4 addresses is DISABLED" 183 | /log warning "Check rule properties in 'IP-Firewall-Raw'"}; /} 184 | 185 | # device log analysis 186 | :local Analysis do={ # $1-NameBL $2-TimeoutBL $3-LogEntry $4-ExtremeScan $5-Debug 187 | 188 | # dangerous IPv4 addresses finder in log 189 | :local IpFinder do={ # $1-PrevStr $2-CurrStr $3-NextStr $4-BeginPtrn $5-EndPtrn $6-NameAttack $7-NameBL $8-TimeoutBL $9-LogEntry $10-Debug 190 | 191 | # checking correctness IPv4 address & blacklisting it 192 | :local IpCheck do={ # $1-IPaddr $2-NameBL $3-TimeoutBL $4-LogEntry $5-NameAttack $6-Debug 193 | :global T2UDNG; :global U2TDNG; :global numDNG 194 | :if ($1~"((25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)[.]){3}(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)") do={ 195 | :if ($6) do={:put ">IpCheck__ip:$1<"} 196 | :if ([/ip firewall address-list find address=$1 list=$2]="") do={ 197 | :set numDNG ($numDNG+1) 198 | /ip firewall address-list add address=$1 list=$2 timeout=$3 199 | :put "$[$U2TDNG [$T2UDNG]]\tAdded in BlackList IPv4: $1 ($5)" 200 | :if ($4) do={/log warning ">>> Added in BlackList IPv4: $1 ($5)"} 201 | :return true}} 202 | :return false} 203 | 204 | # correcting characters of IPv4 addr 205 | :local CorrectIpV4 do={ 206 | :if ([:typeof $1]!="str" or [:len $1]=0) do={:return ""} 207 | :local sym "0123456789."; :local res "" 208 | :for i from=0 to=([:len $1]-1) do={:local chr [:pick $1 $i]; :if ([:find $sym $chr]>-1) do={:set res ($res.$chr)}} 209 | :return [:toip $res]} 210 | 211 | :if ($10) do={:put ">>>IpFinder1__Prev:$1__Curr:$2__Next:$3__Begin:$4__End:$5<<<"} 212 | :local prevLen [:len $1]; :local currLen [:len $2]; :local nextLen [:len $3]; :local isDng false; # sign of detected danger 213 | :if ($currLen=0 or $prevLen!=0 && $nextLen!=0) do={:return $isDng}; # quick exit with incorrect input parameters 214 | /log; :local arrPrevId ""; :if ($prevLen!=0) do={:set arrPrevId [find message~$1]} 215 | :local arrCurrId ""; :if ($currLen!=0) do={:set arrCurrId [find message~$2]} 216 | :local arrNextId ""; :if ($nextLen!=0) do={:set arrNextId [find message~$3]} 217 | :local lenPrevId [:len $arrPrevId]; :local lenCurrId [:len $arrCurrId]; :local lenNextId [:len $arrNextId] 218 | :if ($lenCurrId=0 or $prevLen!=0 && lenPrevId=0 or $nextLen!=0 && $lenNextId=0) do={:return $isDng}; # quick exit when specified string is not found 219 | :global timeBlckr; :global T2UDNG; :local bgnPtrn [:len $4]; :local endPtrn [:len $5]; :local dngIp ""; :local line 5 220 | :foreach currId in=$arrCurrId do={ # selecting current id string 221 | :local msg [/log get $currId message]; :local strLen [:len $msg]; :local tim [$T2UDNG [/log get $currId time]] 222 | :if ($tim>$timeBlckr && $strLen<200) do={ # filtering out old & very long strings 223 | :local currHexId ("0x".[:pick $currId ([:find $currId "*"] +1) [:len $currId]]); # hex id of current string 224 | :local findPrev false; :local findNext false; 225 | :if ($lenPrevId>0) do={ 226 | :foreach prevId in=$arrPrevId do={ # selecting previous id string 227 | :local prevHexId ("0x".[:pick $prevId ([:find $prevId "*"] +1) [:len $prevId]]); # hex id of previos string 228 | :local diff ($currHexId-$prevHexId); :if ($diff>0 && $diff<$line) do={:set findPrev true}}} 229 | :if ($lenNextId>0) do={ 230 | :foreach nextId in=$arrNextId do={ # selecting next id string 231 | :local nextHexId ("0x".[:pick $nextId ([:find $nextId "*"] +1) [:len $nextId]]); # hex id of next string 232 | :local diff ($nextHexId-$currHexId); :if ($diff>0 && $diff<$line) do={:set findNext true}}} 233 | :if ($prevLen=0 && $lenCurrId!=0 && $nextLen=0 or $prevLen!=0 && $nextLen=0 && $findPrev or $prevLen=0 && $nextLen!=0 && $findNext) do={ 234 | :if ($bgnPtrn!=0) do={:set dngIp [:pick $msg ([:find $msg $4] +$bgnPtrn) $strLen]} else={:set dngIp $msg}; # begin of dangerous IPv4 addr 235 | :if ($endPtrn!=0) do={:set dngIp [:pick $dngIp 0 [:find $dngIp $5]]}; # end of dangerous ipAddr 236 | :set dngIp [$CorrectIpV4 $dngIp]; # removing non-IPv4 characters 237 | :if ($10) do={:put ">>>IpFinder3__dngIp:$dngIp__findPrev:$findPrev__findNext:$findNext<<<"} 238 | :if ([$IpCheck $dngIp $7 $8 $9 $6 $10]) do={:set isDng true}}}}; # sending suspicious address to verification 239 | :return $isDng} 240 | 241 | :if ($5) do={:put ">>>>Analysis__NameOfBL:$1__Timeout:$2__LogEntry:$3__ExtremeScan:$4<<<<<"} 242 | :local isDetected false; :local phraseBase { 243 | {name="login failure";prev="";curr="login failure for user";next="";bgn="from ";end=" via"}; 244 | {name="denied connect";prev="";curr="denied winbox/dude connect from";next="";bgn="from ";end=""}; 245 | {name="L2TP auth failed";prev="";curr="authentication failed";next="";bgn="<";end=">"}; 246 | {name="IPsec wrong passwd";prev="";curr="parsing packet failed, possible cause: wrong password";next="";bgn="";end=" parsing"}; 247 | {name="IPSec failed proposal";prev="";curr="failed to pre-process ph1 packet";next="";bgn="";end=" failed"}; 248 | {name="IPsec ph1 failed due to time up";prev="respond new phase 1 ";curr="phase1 negotiation failed due to time up";next="";bgn="<=>";end="["}; 249 | {name="IKEv2 ident not found";prev="identity not found";curr="killing ike2 SA";next="";bgn="]-";end="["}; 250 | {name="IKEv2 payload missing";prev="";curr="payload missing";next="";bgn="proto UDP, ";end=":"}; 251 | {name="OVPN peer disconn";prev="TCP connection established from";curr="disconnected ";next="";bgn="<";end=">:"}; 252 | {name="OVPN unknown opcode";prev="unknown opcode received";curr="disconnected ";next="";bgn="<";end=">:"}; 253 | {name="OVPN too short MSG";prev="msg too short";curr="TCP connection established from";next="";bgn="from ";end=""}; 254 | {name="OVPN unknown MSG";prev="unknown msg";curr="TCP connection established from";next="";bgn="from ";end=""}; 255 | {name="PPTP auth failed";prev="";curr="TCP connection established from";next="authentication failed";bgn="from ";end=""}; 256 | {name="TCP conn establ";prev="";curr="TCP connection established from";next="";bgn="from ";end="";extr=true}; 257 | {name="IPsec due to time up";prev="";curr="phase1 negotiation failed due to time up";next="";bgn="<=>";end="[";extr=true}} 258 | :foreach dangObj in=$phraseBase do={ 259 | :if ([:len ($dangObj->"extr")]=0 or $4=($dangObj->"extr")) do={ 260 | :if ([$IpFinder ($dangObj->"prev") ($dangObj->"curr") ($dangObj->"next") ($dangObj->"bgn") ($dangObj->"end") ($dangObj->"name") $1 $2 $3 $5]) do={:set isDetected true}}} 261 | :return $isDetected} 262 | 263 | # main body 264 | :global numDNG 0; :local startTime [$T2UDNG]; :local currTime [$U2TDNG $startTime]; 265 | :put "$currTime\tStart of searching dangerous IPv4 addresses on '$[/system identity get name]' router" 266 | :if ([:len $scriptBlckr]=0) do={:set scriptBlckr true} 267 | :if ($scriptBlckr) do={ 268 | :set scriptBlckr false; :set timeout [:totime $timeout] 269 | :if ($debug) do={:put "$[$U2TDNG [$T2UDNG]]\tDebug mode is ENABLED"} 270 | :if ($xtreme) do={:put "$[$U2TDNG [$T2UDNG]]\tBE CAREFUL!!!!!! Extreme scanning mode is ENABLED!"} 271 | :if ($wanLst="") do={:set wanLst [$GwFinder]; :put "$[$U2TDNG [$T2UDNG]]\tVariable 'wanLst' is empty -> so value '$wanLst' is automatically assigned"} 272 | :if ([:len [/interface list find name=$wanLst]]!=0) do={ 273 | [$ChkFWRul $fwUsag $wanLst $nameBL $nameWL $cmntBL $cmntWL $timeout] 274 | } else={:put "$[$U2TDNG [$T2UDNG]]\tATTENTION!!! Not found list external interfaces named '$wanLst'." 275 | :put "$[$U2TDNG [$T2UDNG]]\tCheck it 'Interfaces-Interface List', firewall protection may not work!!!"} 276 | :if ($timeBlckr=0 or [:len $timeBlckr]=0) do={:put "$[$U2TDNG [$T2UDNG]]\tTime of the last log check was not found"; :set timeBlckr 0 277 | } else={:put "$[$U2TDNG [$T2UDNG]]\tTime of the last log check $[$U2TDNG $timeBlckr]"} 278 | :if ([$Analysis $nameBL $timeout $logEnt $xtreme $debug]) do={ 279 | :put "$[$U2TDNG [$T2UDNG]]\t$numDNG new dangerous IPv4 addresses were found" 280 | } else={:put "$[$U2TDNG [$T2UDNG]]\tNo new dangerous IPv4 addresses were found"} 281 | :set timeBlckr $startTime 282 | :if ($stcAdr) do={ 283 | /ip firewall address-list 284 | :foreach idx in=[find dynamic=yes list=$nameBL] do={ 285 | :local ipaddress [get $idx address]; remove $idx; add list=$nameBL address=$ipaddress}} 286 | :set currTime [$U2TDNG [$T2UDNG]] 287 | /system script environment remove [find name~"DNG"] 288 | :set scriptBlckr true 289 | } else={:put "$currTime\tScript already being executed..."} 290 | :put "$currTime\tEnd of searching dangerous IPv4 addresses script" 291 | } on-error={ 292 | :set scriptBlckr true 293 | :put "Script of blocking dangerous IPv4 addresses worked with errors" 294 | /system script environment remove [find name~"DNG"] 295 | /log warning "Script of blocking dangerous IPv4 addresses worked with errors"} 296 | # finita la commedia 297 | --------------------------------------------------------------------------------