all version have this editor?in that case take CLI script editor (inside RouterOS) and edit script in there. Most of the syntax changes can be caught using that. F5 to refresh highlighting.
in CLI - /system script edit <script-name> source
:foreach i in=[/ip dhcp-server lease find dynamic=yes] do={
:set dynamicMAC [/ip dhcp-server lease get $i mac-address];
:set dynamicHOST [/ip dhcp-server lease get $i host-name];
:set macfound [/ip firewall filter find src-mac-address=$dynamicMAC];
:if ($macfound != "") do={
:log info ($dynamicMAC. " already filtered")
} else= {
/ip firewall filter add chain=forward src-mac-address=$dynamicMAC action=drop comment=($dynamicHOST . " - " . $dynamicMAC . " Unregistered device")
:log info ("Added " . $dynamicMAC. " to firewall filter")
}
}
:foreach i in=[/ip dhcp-server lease find dynamic] do={
:local dynamicMAC [/ip dhcp-server lease get $i mac-address];
:local dynamicHOST [/ip dhcp-server lease get $i host-name];
:local macfound [/ip firewall filter find src-mac-address=$dynamicMAC];
:if ($macfound != "") do={
:log info ($dynamicMAC. " already filtered")
} else= {
/ip firewall filter add chain=forward src-mac-address=$dynamicMAC action=drop comment=($dynamicHOST . " - " . $dynamicMAC . " Unregistered device")
:log info ("Added " . $dynamicMAC. " to firewall filter")
}
}
/system script add name=pushupdate policy=ftp,read,write,policy,test,winbox,password,sniff,sensitive,api source=" :foreach i in=[/ip firewall address-list find list=accesspoints] do={ [/tool fetch address=[/ip firewall address-list get $i address] mode=ftp user=login password=password src-path=updates/wireless-fp-6.13rc7-mipsbe.npk dst-path=wireless-fp-6.13rc7-mipsbe.npk upload=yes]; [/tool fetch address=[/ip firewall address-list get $i address] mode=ftp user=login password=password src-path=updates/routeros-mipsbe-6.13rc7.npk dst-path=routeros-mipsbe-6.13rc7.npk upload=yes]; [/tool fetch address=[/ip firewall address-list get $i address] mode=ftp user=login password=password src-path=updates/reboot.rsc dst-path=reboot.auto.rsc upload=yes]; }I have all the Access Points in the address list "accesspoints".
:file remove reboot.auto.rsc :log warning "Firmware upgrade initiated" :delay 1s :system reboot...(Warnings and errors are logged to disk, everything else to memory only, this is why I issue a warning).
I don't know where to post this but this is by far the best place to post it. Basically what the script does is that it will check for dynamic leases on my dhcp server, take their mac addresses and check it against firewall filter. If it's not there it will add it and drop everything that's coming from those mac addresses. I'm using this to prevent users from using my internet bandwidth without prior permission and they just happen to know my wireless key from a colleague.
The script below is tested to work on 2.9.x:
The code below is tested to work on 5.19:Code: Select all:foreach i in=[/ip dhcp-server lease find dynamic=yes] do={ :set dynamicMAC [/ip dhcp-server lease get $i mac-address]; :set dynamicHOST [/ip dhcp-server lease get $i host-name]; :set macfound [/ip firewall filter find src-mac-address=$dynamicMAC]; :if ($macfound != "") do={ :log info ($dynamicMAC. " already filtered") } else= { /ip firewall filter add chain=forward src-mac-address=$dynamicMAC action=drop comment=($dynamicHOST . " - " . $dynamicMAC . " Unregistered device") :log info ("Added " . $dynamicMAC. " to firewall filter") } }
Good luck!Code: Select all:foreach i in=[/ip dhcp-server lease find dynamic] do={ :local dynamicMAC [/ip dhcp-server lease get $i mac-address]; :local dynamicHOST [/ip dhcp-server lease get $i host-name]; :local macfound [/ip firewall filter find src-mac-address=$dynamicMAC]; :if ($macfound != "") do={ :log info ($dynamicMAC. " already filtered") } else= { /ip firewall filter add chain=forward src-mac-address=$dynamicMAC action=drop comment=($dynamicHOST . " - " . $dynamicMAC . " Unregistered device") :log info ("Added " . $dynamicMAC. " to firewall filter") } }
Beware that this won't work if your script is above 4Kb ! (See this post ).all RouterOS have this.
Code: Select allin CLI - /system script edit <script-name> source
Please help me with this script as i spent a crazy amount of time and it still doesnt completely work.
. I have tried so many ways to make this work, and i can get Netwatch to work beautifully when the first route goes down, but it doesnt work when the route comes back up again. I have borrowed from many different forums, the largest part from Steve Discher..
I have tried to change the distance, enable=true, disable=false, enabled=true, enabled=yes, and everything else i could think of but nothing works to make the primary route, the primary route.
/ip firewall filter
add action=drop chain=output comment=\
"Drop pings to 4.2.2.4 if they go through PROVIDER2" dst-address=4.2.2.4 \
out-interface=ether2-gateway
/ip route
add comment=PROVIDER1 distance=1 gateway=192.168.2.1 scope=11
add comment=PROVIDER2 distance=10 gateway=192.168.3.1
add comment="Force test pings through PROVIDER1" distance=1 dst-address=\
4.2.2.4/32 gateway=192.168.2.1
Here is my first netwatch script, it works great until provider 2 starts working, and the distance remains at 20, so it doesnt work, and no emails get sent.
/tool netwatch
add comment=CheckCon down-script="/ip route set [find comment=\"PROVIDER1\"] d\
istance=20\r\
\n/ip route set [find comment=\"PROVIDER2\"] disabled=no\r\
\n/tool e-mail send to=\"andrew.wells@xx.xxx\" body=\"Connection with\
\_PROVIDER1 Lost, Switched to PROVIDER2\" subject=\"Lost connection with P\
ROVIDER1\"\r\
\n/tool e-mail send to=\"andrewwells@xx.xxx\" body=\"Connection with \
PROVIDER1 Lost, Switched to PROVIDER2\" subject=\"Lost connection with PRO\
VIDER1\"\r\
\n:log error \"Primary internet connection down\"\r\
\n/ ip firewall connection remove [/ip firewall connection find dst-addres\
s~\"xx.xxx.137.117:5060\"]" host=4.2.2.4 interval=5s timeout=2s \
up-script="/ip route set [find comment=\"PROVIDER1\"] distance=1\r\
\n/ip route set [find comment=\"PROVIDER2\"] disabled=no\r\
\n/tool e-mail send to=\"andrew.wells@xx.xxx\"\r\
\nbody=\"Connection with PROVIDER1 Regained, Switched back to PROVIDER1\" \
subject=\"Regained connection with PROVIDER1\"\r\
\n/tool e-mail send to=\"andrewwells@xx.xxx\"\r\
\nbody=\"Connection with PROVIDER1 Regained, Switched back to PROVIDER1\" \
subject=\"Regained connection with PROVIDER1\"\r\
\n/ ip firewall connection remove [/ip firewall connection find dst-addres\
s~\"xx.xxx.137.117:5060\"]"
Here is my 80th attempt, with changes to the up script, and i have tried everything i could find on the forums. Now the route remains disabled, and again, no emails go out.
/tool netwatch
add comment=CheckCon down-script="/ip route set [find comment=\"PROVIDER1\"] d\
isabled=yes\r\
\n/ip route set [find comment=\"PROVIDER2\"] disabled=no\r\
\n/tool e-mail send to=\"andrew.wells@xx.xxx\" body=\"Connection with\
\_PROVIDER1 Lost, Switched to PROVIDER2\" subject=\"Lost connection with P\
ROVIDER1\"\r\
\n/tool e-mail send to=\"andrewwells@xx.xxx\" body=\"Connection with \
PROVIDER1 Lost, Switched to PROVIDER2\" subject=\"Lost connection with PRO\
VIDER1\"\r\
\n:log error \"Primary internet connection down\"\r\
\n/ ip firewall connection remove [/ip firewall connection find dst-addres\
s~\"xx.xxx.137.117:5060\"]\r\
\n/ ip firewall connection remove [/ip firewall connection find dst-addres\
s~\"xx.xxx.137.116:5060\"]" host=4.2.2.4 interval=5s timeout=2s \
up-script="/ip route get [find comment=\"PROVIDER1\"] disabled=true\r\
\n/ip route set [find comment=\"PROVIDER1\"] disabled=no\r\
\n/ip route set [find comment=\"PROVIDER2\"] disabled=no\r\
\n/tool e-mail send to=\"andrew.wells@xx.xxx\"\r\
\nbody=\"Connection with PROVIDER1 Regained, Switched back to PROVIDER1\" \
subject=\"Regained connection with PROVIDER1\"\r\
\n/tool e-mail send to=\"andrewwells@xx.xxx\"\r\
\nbody=\"Connection with PROVIDER1 Regained, Switched back to PROVIDER1\" \
subject=\"Regained connection with PROVIDER1\"\r\
\n/ ip firewall connection remove [/ip firewall connection find dst-addres\
s~\"xx.xxx.137.117:5060\"]\r\
\n/ ip firewall connection remove [/ip firewall connection find dst-addres\
s~\"xx.xxx.137.116:5060\"]"
/ip firewall filter
rem [find]
/ip firewall filter
rem [find where !dynamic]
:log warning ("DNS script begin")
############## Script FreeDNS.afraid.org ##################
############## CREATED LESHIY_ODESSA ##################
############## Improved by SEAN SCARFO ##################
# Specify your domain or subdomain.
:global "dns-domain" "whatever.woot.me"
# Define IP checker website variable. Any website that returns only the ip address in text format. examples listed
#https://www.trackip.net/ip/
#http://wgetip.com/
#https://api.ipify.org/
#If not pointing to a specific file, must end in a /
# Case sensitive.
:global "wanChecker" "http://wgetip.com/"
#specify your internet interface. naming does not have to be exact as long as it has "ether" in the name
:global "wanInterface" "ether1"
# Specify the "Direct URL", which is https://freedns.afraid.org/dynamic/
# In front of the sign "?" put a backslash "\".
:global "direct-url" "https://freedns.afraid.org/dynamic/update.php\?98675985876548765486547654jhdf"
# Specify the URL API "ASCII"
# Log in under your account and open the page https://freedns.afraid.org/api/
# Then copy the URL of your site - Available API Interfaces : ASCII (!!! NOT XML !!!)
# ATTENTION!!!! Before the question mark, put a backslash "\".
:global "api-url" "https://freedns.afraid.org/api/\?action=getdyndns&v=2&sha=87587657865hjgfhgfjhgf"
# !!!!!!!!!!!!!!!!! Nothing more do not need to edit!!!!!!!!!!!!!!!!!
:global "current-ip"
:global "dns-domain-ip"
:if ([:len $"current-ip"] <7) do={
:log error ("current-ip variable has no value, setting it to 1.1.1.1");
:global "current-ip" 1.1.1.1;
} else={
:log warning ("current IP variable exists and has a value")
#pause for 1 seconds
:delay 1
#Fetch Current IP from ether1
:global "current-ip" [/ip address get value-name=address [find interface~$"wanInterface"]]
:global "current-ip-endloc" ([:len $"current-ip"] -3)
:global "current-ip" [:pick $"current-ip" 0 $"current-ip-endloc"]
# Compare global IP variables
# Compare the external IP with the IP address of the DNS domain.
:if ($"current-ip" = $"dns-domain-ip") do={
:log warning ("current-ip matches dns-domain-ip, script is done!")
} else={
#pause for 1 seconds
:delay 1
:log error ("$"current-ip" does not match $"dns-domain-ip", updating IP FreeDNS")
#pause for 1 seconds
:delay 1
#Fetch Last Known IP info from WanChecker
/tool fetch url="$wanChecker" dst-path="/wanCheckerfile.txt"
#pause for 1 seconds
:delay 1
# Find the current IP address on the external interface
:global "current-ip" [/file get wanCheckerfile.txt contents]
#pause for 1 seconds
:delay 1
#Fetch Last Known IP info from FreeDNS
/tool fetch url=$"api-url" dst-path="/freedns.txt"
#pause for 1 seconds
:delay 1
# Find out the IP address of the domain using the API and parsing.
# Split the file
:local "result" [/file get freedns.txt contents]
:local "startloc" ([:find $result $"dns-domain"] + [:len $"dns-domain"] + 1)
:local "endloc" ([:find $"result" "https" [:find $result $"dns-domain"]] -1)
:global "dns-domain-ip" [:pick $"result" $"startloc" $"endloc"]
#pause for 1 seconds
:delay 1
# Compare global IP variables
# Compare the external IP with the IP address of the DNS domain.
:if ($"current-ip" = $"dns-domain-ip") do={
:log warning ("current-ip matches dns-domain-ip, script is done!")
} else={
#pause for 1 seconds
:delay 1
# Send new IP to freedns.afraid.org our external IP by using Direct URL
:log error ("Service Dynamic DNS: old IP address $"dns-domain-ip" for $"dns-domain" CHANGED to -> $"current-ip"")
/tool fetch mode=https url=$"direct-url" keep-result=no
}
}
}
:log warning ("DNS script end")
:local replace [:parse [:system script get replace-upper-lower source]]
:set $var [$replace "convert me to upper" ]
OR
:set $var [$replace "CONVERT ME TO LOWER" 1 ]
:local lower [:toarray "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"]
:local upper [:toarray "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z"]
# Pass as param 2 to toggle conversion
:local mode false
:local result
:if (($2 = "") || ($2 = nil)) do={:set $mode true}
:for idx from=0 to=([:len $1] - 1) do={
:local char [:pick $1 $idx]
:local match
:if ($mode) do={
:for i from=0 to=[:len $lower] do={
:set $match ($lower->$i)
:if ($char = $match) do={:set $char ($upper->$i)}
}
} else={
:for i from=0 to=[:len $upper] do={
:set $match ($upper->$i)
:if ($char = $match) do={:set $char ($lower->$i)}
}
}
:set $result ($result.$char)
}
:return $result
:local keyfile [:parse [:system script get read-keyfile source]]
:local config [$keyfile "monitor-api" ":"]
:local user [:pick ($config->0) 1]
:local password [:pick ($config->1) 1]
..... More logic here.....
:local filename $1
:local delimiter $2
:local result {nil}
:local aidx 0
:local eof -1
:local eol 0
:local idx 0
:local line
:local cfgfile
:do {
:if (($delimiter = "") || ($delimiter = nil)) do={:set $delimiter ":"}
:if ([:file find name=$filename] != "") do={
:set $cfgfile [:file get [:file find name=$filename] contents]
}
:if ([:len $cfgfile] < 1) do={
:set $cfgfile [:file get [:file find name=($filename.".txt")] contents]
}
:if ([:len $cfgfile] < 1) do={:return {1,1}}
:set $eof [:len $cfgfile]
:do {
:set $eol ([:find $cfgfile "\r"]);
:if ( ($eol=0)||($eol=nil) ) do={:set $eol ([:find $cfgfile "\n"])}
:if ( ($eol=0)||($eol=nil) ) do={:set $eol $eof}
:set $line [:pick $cfgfile 0 $eol]
:if ([:len $line] > 1) do={
:set $idx [:find $line $delimiter]
:set ($result->$aidx) {[:pick $line 0 ($idx)];[:pick $line ($idx+1) $eol]}
:set $aidx ($aidx + 1);
}
:set $cfgfile [:pick $cfgfile ($eol +2) $eof]
:set $eof ($eof - $eol);
} while=($eol > 0)
} on-error={:log error "Could not read configuration file $filename"}
:return $result
:local replace [:parse [:system script get replace-char source]]
:local hostname [$replace ([:system identity get name]) " " "-"]
:local match $2
:local replace $3
:local result
:for i from=0 to=([:len $1] - 1) do={
:local char [:pick $1 $i]
:if ($char = $match) do={:set $char $replace}
:set $result ($result.$char)
}
:return $result
/ip dhcp-server
add authoritative=yes disabled=no interface=ether1 address-pool=pool1 lease-time=7d name=equipment-dhcp use-radius=no \
lease-script="...[DHCP LEASE SCRIPT]......."
:local replace [:parse [:system script get replace-char source]]
:local addmonitor [:parse [:system script get add-monitor-device source]]
:local domainname "equipment.domain.local"
/ip dhcp-server lease
:if ($leaseBound = 1) do={
:local hostname [ get [find where active-address=$leaseActIP] host-name]
:set $hostname [$replace $hostname "." "-"]
:if ([:len $hostname] <= 1) do={:set $hostname [$replace $leaseActMAC ":" ""]}
:do {
[$addmonitor $hostname $domainname]
} on-error={:log error "Error updating API for DHCP client"}
}
:if (!($hostname ~"COMPARE TO ME")) do={:return -1}
:global configfolder
:local keyfile [:parse [:system script get read-keyfile source]]
:local replace [:parse [:system script get replace-char source]]
:local convert [:parse [:system script get replace-lowup source]]
:local domainname "router.domain.local"
:local community "public"
:local hostname [$replace ([:system identity get name]) " " "-"]
:local keep true
:local apikey ($configfolder."monitor-api")
:local results ($configfolder."monitor-results.txt")
:local api
:local user
:local pass
:local url
:if (($1 != "") && ($1 != nil)) do={:set $hostname [$replace $1 " " "-"]}
:if (($2 != "") && ($2 != nil)) do={:set $domainname $2}
:do {
:if (!($hostname ~"XXX-")) do={:return -1}
:set $hostname [$convert $hostname 1]
}
:do {:set $api [$keyfile $apikey ":"]} on-error={:log error "Could not load API information from file $apikey"}
:do {
:set $user [:pick ($api->0) 1]
:set $pass [:pick ($api->1) 1]
:set $url ([:pick ($api->2) 1].[:pick ($api->3) 1].[:pick ($api->4) 1])
} on-error={:log error "Could not parse API array"; return 0}
:do {[:file remove [:file find name=$results]]} on-error={}
:log info "Start add device $hostname.$domainname to monitor server via API [$url]"
:do {
:local content "hostname=$hostname.$domainname&snmp_community=$community"
#:log info $content
[:tool fetch user=$user password=$pass url=$url keep-result=$keep http-method=post http-data=$content check-certificate=no dst-path=$results]
:log info "Added device to monitoring server completed"
} on-error={:log warn "Warning calling monitor API to add device $hostname"; return 0}
:if ($keep) do={
:delay 1s
:set $results [:file get [:file find name=$results] contents]
}
:return $results
:local ipcalc [:parse [:system script get ip-calc source]]; :put [$ipcalc 192.168.10.0/24 1]
:local ipcalc [:parse [:system script get ip-calc source]];
:local subnet [$ipcalc 192.168.10.0/24]
:log info ("Broadcast address is ".($subnet->3))
:local ipnetwork [:toip ([:pick $1 0 [:find $1 "/"]])]
:local cidrsubnet [:pick $1 ([:find $1 "/"] + 1) [:len $1]]
:local subnetmask (0.0.0.0 | (255.255.255.255 << (32-$cidrsubnet)))
:local ipbroadcast ($ipnetwork | ~(255.255.255.255 << (32-$cidrsubnet)))
:local ipstart
:local ipend
:local ipusable
:set ipstart ($ipnetwork + 1)
:set ipend (($ipnetwork | $ipbroadcast) - 1)
:local usable (~$subnetmask)
:local y 0
:local char
:local result
:while ($y < ([:len $usable] + 1)) do={
:set char [:pick $usable $y ($y + 1)]
:if ($char != ".") do={
:set $result ($result.$char)
} else={
:set $result ($result.",")
}
:set $y ($y + 1)
}
:set $result [:toarray $result]
:for i from=0 to=2 do={
:set ipusable ($ipusable + ([:pick $result $i] * (256 << (8 * (2 - $i)))))
}
:set ipusable (($ipusable + [:pick $result 3]) - 1)
:if ([:len $2] != 0) do={
:return "Start: $ipstart End: $ipend Network: $ipnetwork Broadcast: $ipbroadcast Subnetmask: $subnetmask Usable: $ipusable"
} else={
:return [:toarray ($ipstart,$ipend,$ipnetwork,$ipbroadcast,$subnetmask,$ipusable)]
}
I've updated my script as it turns out the hap AC2 does not have a beeper; this new script, in addition to triggering the beeper (no harm done if your RB doesn't have one), also turns on the user-led when the guest wifi is on and turns the led off when the guest wifi is off.Here's a script I recently created for enabling/disabling my guest wifi. I plan to attach this script to the external mode button of a hap AC2. Please note, in the context of the script, "Guest" is the name of the wireless interface. This script checks to see if the guest wifi is disabled. If it is, it enables it and then plays two lower tones and then a high tone over the beeper. If it isn't disabled, it disables it and then plays two high tones and a low tone. This script works on my RB951G version 6.40.7. I don't know yet if it will need to be modifed for the hap AC2 as that will be my first dual-band routerboard.
{
:if ([/interface wireless get Guest disabled]=true) \
do={[/interface wireless enable Guest; /beep frequency=380 length=300ms;
:delay 300ms;
:beep frequency=380 length=300ms;
:delay 300ms;
:beep frequency=770 length=600ms;]} \
else={[/interface wireless disable Guest; beep frequency=770 length=300ms;
:delay 300ms;
:beep frequency=770 length=300ms;
:delay 300ms;
:beep frequency=380 length=600ms;]}
}
{
:if ([/interface wireless get Guest disabled]=true) \
do={[/interface wireless enable Guest;
/beep frequency=380 length=300ms;
:delay 300ms;
:beep frequency=380 length=300ms;
:delay 300ms;
:beep frequency=770 length=600ms;
/system leds set [find where leds=user-led] type=on;]} \
else={[/interface wireless disable Guest;
/beep frequency=770 length=300ms;
:delay 300ms;
:beep frequency=770 length=300ms;
:delay 300ms;
:beep frequency=380 length=600ms;
/system leds set [find where leds=user-led] type=off;]}
}
Hello, thanks for sharing your scriptI've updated my script as it turns out the hap AC2 does not have a beeper; this new script, in addition to triggering the beeper (no harm done if your RB doesn't have one), also turns on the user-led when the guest wifi is on and turns the led off when the guest wifi is off.Here's a script I recently created for enabling/disabling my guest wifi. I plan to attach this script to the external mode button of a hap AC2. Please note, in the context of the script, "Guest" is the name of the wireless interface. This script checks to see if the guest wifi is disabled. If it is, it enables it and then plays two lower tones and then a high tone over the beeper. If it isn't disabled, it disables it and then plays two high tones and a low tone. This script works on my RB951G version 6.40.7. I don't know yet if it will need to be modifed for the hap AC2 as that will be my first dual-band routerboard.
{
:if ([/interface wireless get Guest disabled]=true) \
do={[/interface wireless enable Guest; /beep frequency=380 length=300ms;
:delay 300ms;
:beep frequency=380 length=300ms;
:delay 300ms;
:beep frequency=770 length=600ms;]} \
else={[/interface wireless disable Guest; beep frequency=770 length=300ms;
:delay 300ms;
:beep frequency=770 length=300ms;
:delay 300ms;
:beep frequency=380 length=600ms;]}
}
Please note that for this to work, you would first need to run the command:Code: Select all{ :if ([/interface wireless get Guest disabled]=true) \ do={[/interface wireless enable Guest; /beep frequency=380 length=300ms; :delay 300ms; :beep frequency=380 length=300ms; :delay 300ms; :beep frequency=770 length=600ms; /system leds set [find where leds=user-led] type=on;]} \ else={[/interface wireless disable Guest; /beep frequency=770 length=300ms; :delay 300ms; :beep frequency=770 length=300ms; :delay 300ms; :beep frequency=380 length=600ms; /system leds set [find where leds=user-led] type=off;]} }
/system leds add leds=user-led type=off
This creates the LED setting for the command in the script to manipulate.
:global oldbgpstate
:if (:len $oldbgpstate = 0 ) do={ :set $oldbgpstate {"_dummy"=33} }
:local bgpstates ({disabled=0},{idle=1},{connect=2},{active=3},{opensent=4},{openconfirm=5},{established=6})
/routing bgp peer
:local peerstate
:foreach peer in=[/routing bgp peer find ] do={
:local pstate [get $peer state]
:if ( [get $peer disabled] ) do={ :set $pstate value="disabled" }
:local peername [get $peer name]
:local severity "info"
:if ( ($bgpstates->($oldbgpstate->$peername)) > ($bgpstates->$pstate) ) do={
#raise error if state is decreasing
:set $severity "error"
}
:if ($oldbgpstate->$peername != $pstate) do={
#peer state changed
:local peerip [get $peer "remote-address"]
:local message "bgp,$severity peer $peerip ($peername) changed state to $pstate"
:if ($severity = "error") do={
:log error message=$message
} else={
:log info message=$message
}
}
:set ($oldbgpstate->$peername) value="$pstate"
}
#Imposta ID della VPN (ID - 1)
:global VPNID 1
# Imposta DDNS_Sorgente attualmente legato al DDNS
:global DDNSSorgente [:resolve xxxxxxxxxxx.sn.mynetname.net]
# Imposta DDNS_Destinazione attualmente legato al DDNS
:global DDNSDestinazione [:resolve yyyyyyyyyyyyyy.sn.mynetname.net]
# Imposta VPN_Sorgente
:global VPNSorgente [/ip ipsec policy get $VPNID sa-src-address]
#Imposta VPN_Destinazione
:global VPNDestinazione [/ip ipsec policy get $VPNID sa-dst-address]
#Verifica se cambiato IP Sorgente, nel caso lo modifica nella VPN
:if ($DDNSSorgente !=$VPNSorgente) do={
:log info "IP sorgente $VPNSorgente cambiato in $DDNSSorgente"
/ip ipsec policy set $VPNID sa-src-address=$DDNSSorgente} else= {:log info "Nessun cambiamento IP sorgente"}
:log info "Verifica IP Sorgente $DDNSSorgente con successo"
#Verifica se cambiato IP Destinazione, nel caso lo modifica nella VPN
:if ($DDNSDestinazione!=$VPNDestinazione) do={
:log info "IP destinazione $VPNDestinazione cambiato in $DDNSDestinazione"
/ip ipsec policy set $VPNID sa-dst-address=$DDNSDestinazione} else= {:log info "Nessun cambiamento IP Destinazione"}
:log info "Verifica IP Destinazione $DDNSDestinazione eseguita con successo"
## -----
## timestamp - a few utility functions for handling date + time timestamps as Unix-style
## integer timestamps (seconds since the midnight Jan. 1, 1970 GMT epoch)
##
## Version 1.1
##
## Written by Aaron D. Gifford
## https://www.aarongifford.com/
##
## The above author, and original copyright owner, InfoWest, Inc. hereby place this code in the
## PUBLIC DOMAIN. You may use this code in any way. You may alter it. Redistribute it or any
## derivitave with NO requirements whatsoever. You may remove this notice or remove the
## author's name. You could even claim you wrote it (though that's not very cool). Attribution
## or acknowledgement is appreciated, but not required. Have fun! (NO WARRANTIES, etc.)
## -----
## FUNCTION:
## getUnixTimestamp date="jan/01/1970" time="00:00:00" [offset=0]
## * date is a string in the form "mon/DD/YYYY"
## * time is a string in the form "HH:MM:SS" (24-hour clock)
## * offset is an OPTIONAL signed integer number of seconds east of GMT
## such that a positive offset is for zones east of GMT and a negative
## offset is for zones west of GMT. IF NOT included, the script will
## retrieve the currently ative device offset using:
## /system clock get gmt-offset
##
## Example use:
## {
## :local timestamp [$getUnixTimestamp time=[/system clock get date] date=[/system clock get time]]
## ...
##
## RETURNS a Unix-style timestamp, an integer number of seconds elapsed since the Unix epoch
## (01 JAN 1970 GMT). Hopefully MikroTik will soon add a system funtion to return a timestamp
## directly, making this obsolete.
##
## FUNCTION:
## getNow
##
## RETURNS the same thing as doing:
## $getUnixTimestamp time=[/system clock get date] date=[/system clock get time]
##
## FUNCTION:
## getFileTimestamp fname="filename.txt"
## * fname - the name/path of the file for which a creation timestamp will be retrieved
##
## RETURNS:
## Unix-style timestamp of creation date/time for file OR returns false if file was not found
##
:global getUnixTimestamp do={
:local timestr [:tostr $time]
:local datestr [:tostr $date]
:local timestamp ([:tonum [:pick $timestr 0 2]]*3600 + [:tonum [:pick $timestr 3 5]]*60 + [:tonum [:pick $timestr 6 8]])
## Month number, zero-based (0=January)
:local mon ([:find "janfebmaraprmayjunjulaugsepoctnovdec" [:pick $datestr 0 3]]/3)
## For each month already passed, account for the days passed (ignoring Feb. 29th for now):
:local i 0
:while ($i < $mon) do={
:set timestamp ([:pick {31;28;31;30;31;30;31;31;30;31;30;31} $i] * 86400 + $timestamp)
:set i ($i+1)
}
## Account for the number of days already passed for the current month:
:set timestamp (86400*([:tonum [:pick $datestr 4 6]]-1)+$timestamp)
:local year [:tonum [:pick $datestr 7 11]]
## For each year completed since the epoch, include 365 days worth of seconds (again ignoring leap years):
:set timestamp (($year-1970)*31536000+$timestamp)
## Account for Feb. 29 additionl days in leap years already completed:
:set i 1970
:while ($i<$year) do={
:if (($i+3)/4 = $i/4 && (($i+99)/100 != $i/100 || ($i+399)/400 = $i/400)) do={
## REMEMBER: Leap years occur on years evenly divisible by 4 EXCEPT for those
## that are ALSO evenly divisible by 100 UNLESS the century year is ALSO
## divisible by 400 (in which case it IS a leap year after all):
:set timestamp (86400+$timestamp)
}
:set i ($i+1)
}
## IF the date in question is already past February, account for a leap day IF this year is
## a leap year too:
:if ($mon > 1 && ($year+3)/4 = $year/4 && (($year+99)/100 != $year/100 || ($year+399)/400 = $year/400)) do={
:set timestamp (86400+$timestamp)
}
## Account for time zone offset:
:local tzoffset $offset
:if ([:typeof $tzoffset] = "nothing") do={
:set tzoffset [/system clock get gmt-offset]
}
:if ($tzoffset > 2147483648) do={
## A VERY LARGE integer indicates that the offset is negative (west). Convert
## the offset and subtract the resulting negative integer from the timestamp
## (i.e. add the positive absolute value to the timestamp):
:set timestamp (4294967296-$tzoffset+$timestamp)
} else={
## A small integer indicates the offset is positive (east). Simply subtract
## it from the timestamp:
:set timestamp ($timestamp-$tzoffset)
}
:return $timestamp
}
:global getNow do={
:global getUnixTimestamp
:return [$getUnixTimestamp date=[/system clock get date] time=[/system clock get time]]
}
:global getFileTimestamp do={
:global getUnixTimestamp
:local fts [/file find where name="$fname"]
:if ([:len $fts]=0) do={
## No file found!
:return false
}
:set fts [:tostr [/file get value-name=creation-time $fts]]
:return [$getUnixTimestamp date=[:pick $fts 0 11] time=[:pick $fts 12 20]]
}
## The End
/ppp secret export file=secrets
Bump!HI! I am looking for a way to get the router to act when a certain LAN client (ip address) sends a packet to a certain WAN address. The action would be a webhook. What would be the most effective way to setup something like this? Can anyone point me to the right direction, please?
Would I have to use packet sniffer and fetch?
Thank you!
I don't think so. There are a few places where scripts can be triggered in response to events:
However, the script would have to run every 10 seconds... Is there another way to have the firewall rule trigger a script?
Did you ever get anywhere with this? I'm trying to figure out the same thing. When my video doorbell is pressed it sends an alert via a "cloud" service. I'm trying to trigger something local too and this would be ideal.Bump!HI! I am looking for a way to get the router to act when a certain LAN client (ip address) sends a packet to a certain WAN address. The action would be a webhook. What would be the most effective way to setup something like this? Can anyone point me to the right direction, please?
Would I have to use packet sniffer and fetch?
Thank you!
I guess, one way to do this is to setup a firewall rule, which would then trigger a script similar to this https://wiki.mikrotik.com/wiki/Wake_on_ ... te_Desktop
However, the script would have to run every 10 seconds... Is there another way to have the firewall rule trigger a script?
When you send message to the log system, I do like better that it are in a machine readable format. Since I work allot with Splunk, it reads message with out any modification if you do change from::if ($osVerNewNum > $osVerCurrentNum) do={
:set isUpdateAvailable true;
:log info ("New firmware version found: $osVerNew");
} else={
:log info ("New firmware version not found.")
}
"Upgrading firmware on router $[/system identity get name], board name: $[/system resource get board-name],
"script=firmware_upgrade router=$[/system identity get name] board_name=\"$[/system resource get board-name]\" ........
in that case take CLI script editor (inside RouterOS) and edit script in there. Most of the syntax changes can be caught using that. F5 to refresh highlighting.Same Problem here, can't get the same script working on 6.30.4
Anyone?
i have problem about my script...
-first of all i am changing mikrotik user name and password and delete standard username
user add name=******* password=******* group=full
user remove admin
/system scheduler add name="30 gunde reboot" start-date="jul/12/1970" start-time="04:00:00" interval="1d 00:00:00" policy="read,write" on-event=":if ([/system resource get uptime] > 30d00h00m00s) do={:if ([/system clock get time] < 06:30:00) do={:if ([/system clock get time] > 04:30:00) do={/system reboot}}}"
at the last ..i am adding scheduler, but when i am checking this scheduler, I saw owner admin. that why scheduler isn't working
so how can fix this situation ???
i have text file for my this user and system sittings.I'm copying script and open new terminal for past it there.
/ip firewall filter add action=jump chain=forward comment="Check intruders in \"Dynamic_blacklist\" chain (SSH)" dst-port=22 in-interface-list=WAN jump-target=dynamic_blacklist protocol=tcp
/ip firewall filter add action=add-src-to-address-list address-list=DNSBL_unchecked address-list-timeout=30m chain=dynamic_blacklist comment="DNS Blacklist add ip to list to check." connection-state=!established,related in-interface-list=WAN src-address-list=!DNSBL_unchecked
/ip firewall filter add action=return chain=dynamic_blacklist comment="Return to the chain that jumped into dynamic_blacklist chain"
/ip firewall raw add action=drop chain=prerouting comment="Drop blacklist" in-interface-list=WAN log-prefix="DYNAMIC BLACKLIST IP (Raw)" src-address-list=bl_blacklist
# DNS Blacklist service call
:local blserver "bl.blocklist.de"
:local ToListIPList [:toarray ""]
:local octets
:local revip
:local bllookup
:local blresult
:local i
:global returnOctet;
# for each IP in the unchecked list load it into an array
:set i (0);
:foreach fwlist in=[/ip firewall address-list find where list=DNSBL_unchecked] do={
:foreach ip in=[/ip firewall address-list get $fwlist value-name=address] do={
:set ($ToListIPList->"$i") $ip;
:put "$ip is loaded into array at index $i"
#remove ip from address list to check ether way
/ip firewall address-list { remove [find address=$ip list=DNSBL_unchecked]};
:set i ($i + 1);
};
};
#delete entire list=DNSBL_unchecked
#/ip firewall address-list remove [/ip firewall address-list find list="DNSBL_unchecked"];
#take the IPs and Progress;
:foreach ip in=$ToListIPList do={
:put $ip;
# seperate IP into $octets array;
:set octets [$returnOctet $ip 5];
# Reverse the IP address for reverse DNS lookup;
:set revip ([:tostr [:pick $octets 3]] . "." . [:tostr [:pick $octets 2]] . "." . [:tostr [:pick $octets 1]] . "." . [:tostr [:pick $octets 0]]);
# construct the blacklist lookup
:set bllookup ($revip . "." . $blserver);
:put $bllookup;
# perform the lookup and correct an empty response;
:do {
:set blresult [:resolve $bllookup];
} on-error={
#"No blacklist record found, correct the error";
:set $blresult "fail";
}
# check the result
:if ( $blresult != "fail" ) do={
# if the address is listed add it to the blacklist
:put "listing ip";
/ip firewall address-list add address=$ip list=DNSBL_listed timeout=168h;
};
};
:global returnOctet do={
:if ([:typeof [:toip $1]] != "ip") do={ :error message="You did not specify any VALID IP Address."; };
:if ( (($2 + 0) < 1) || (($2 + 0) > 5) ) do={ :error message="You did not specify any VALID argument to return."; };
:local workString value=[:tostr [:toip $1]];
:local endString value="";
:local thisChar value="";
:for i from=0 to=[:len $workString] step=1 do={
:set $thisChar value=[:pick $workString $i ($i+1)];
:if ($thisChar = ".") do={ :set $thisChar value=",";};
:set $endString value=($endString.$thisChar);
};
:local resultArray value=[:toarray $endString];
:if (($2 + 0) = 5) do={ :return value=$resultArray; } else={ :return value=($resultArray->($2 - 1)); };
}
:local currentIP
:local newIP
:local ddnshost "<Dynamic Domain>"
:local key "<Domain Key>"
:local updatehost "dyn.dns.he.net"
:local lookupserver "ns1.he.net"
:local WANinterface "<WAN Interface>"
:local outputfile ("HE_DDNS" . ".txt")
:set newIP [/ip address get [/ip address find interface=$WANinterface] address]
:set newIP [:pick [:tostr $newIP] 0 [:find [:tostr $newIP] "/"]]
:set currentIP [:resolve $ddnshost server=$lookupserver]
#check error
:if ([:len $newIP] = 0) do={
:log error ("Could not get IP for interface " . $WANinterface)
:error ("Could not get IP for interface " . $WANinterface)
} else={
:if ($newIP != $currentIP) do={
:log info ("WAN IPv4 address $currentIP changed to $newIP")
:log info ("Updating DDNS IPv4 address" . " Client IPv4 address to new IP " . $newIP . "...")
/tool fetch mode=http url="http://$ddnshost:$key@$updatehost/nic/update?hostname=$ddnshost&myip=$ipv4addr" \
dst-path=$outputfile
:set currentIP $newIP
:log info ([/file get ($outputfile) contents])
/file remove ($outputfile)
} else={
# :log info ("WAN IPv4 address has not changed")
}
}
foreach i in={ "NL"; "CN"; "RU"; "DE"; "UA"; "IN"; "IT"; "ID"; "TH"; "BR"; "IR"; "VN"; "PK"} do={
/tool fetch url="http://www.iwik.org/ipcountry/mikrotik/$i" dst-path=/SDHX/downloads/$i;
/import file-name=/SDHX/downloads/$i;
/file remove /SDHX/downloads/$i;
}
add chain=forward action=jump jump-target=dynamic_blacklist protocol=tcp dst-port=22 log=no log-prefix="" comment="Check intruders in "Dynamic_blacklist" chain"
add chain=dynamic_blacklist action=drop src-address-list=bl_blacklist log=no log-prefix="DYNAMIC BLACKLIST IP" comment="drop brute forcers" disabled=no
add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new src-address-list=bl_stage3 address-list=bl_blacklist address-list-timeout=5d log=no log-prefix=""
add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new src-address-list=bl_stage2 address-list=bl_stage3 address-list-timeout=5m log=no log-prefix=""
add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new src-address-list=bl_stage1 address-list=bl_stage2 address-list-timeout=7m log=no log-prefix=""
add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new address-list=bl_stage1 in-interface-list=WAN address-list-timeout=10m log=no log-prefix=""
add chain=dynamic_blacklist action=return log=no log-prefix="" comment="Return to the chain that jumped into dynamic_blacklist chain" disabled=no
just need to fix first forward chain \"dynamic_blacklist\" instead of "dynamic_blacklist"Hi All,
OK not really a script, but I thought it may be in the same flavour. I created this Dynamic Blacklist firewall rule set that counts excessive connection attempts from the same IP within a given time frame and eventually blocks them for X number of days. I was initially going to put in a geo-fence for service brute forcers but i found this to be quite effective instead and not limited geographic attackers. Basically it will start counting any IP you send it via the port/protocol parameters in the first jump rule. You can have more than one jump feeding into the list from different chains.
This example is setup to guard SSH for multiple connection attempts. The time outs can be changed to suit your needs but this will block any IP that averages 3 connection attempts within 5 mins.
Code: Select alladd chain=forward action=jump jump-target=dynamic_blacklist protocol=tcp dst-port=22 log=no log-prefix="" comment="Check intruders in "Dynamic_blacklist" chain" add chain=dynamic_blacklist action=drop src-address-list=bl_blacklist log=no log-prefix="DYNAMIC BLACKLIST IP" comment="drop brute forcers" disabled=no add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new src-address-list=bl_stage3 address-list=bl_blacklist address-list-timeout=5d log=no log-prefix="" add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new src-address-list=bl_stage2 address-list=bl_stage3 address-list-timeout=5m log=no log-prefix="" add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new src-address-list=bl_stage1 address-list=bl_stage2 address-list-timeout=7m log=no log-prefix="" add chain=dynamic_blacklist action=add-src-to-address-list connection-state=new address-list=bl_stage1 in-interface-list=WAN address-list-timeout=10m log=no log-prefix="" add chain=dynamic_blacklist action=return log=no log-prefix="" comment="Return to the chain that jumped into dynamic_blacklist chain" disabled=no
add chain=forward action=jump jump-target=dynamic_blacklist protocol=tcp dst-port=22 log=no log-prefix="" comment="check intruders in \"dynamic_blacklist\" chain"
Easier append array: viewtopic.php?p=819886#p728850Hi all,
Let me also share my scripts collection with you - maybe you will find few of them helpful or useful as they are to me;)
https://github.com/gbudny93/RouterOS_Useful_Scripts
Greg
In this case I'll use a smaller ip list: https://lists.blocklist.de/lists/ftp.txtIf it is bigger than 63KB then that is not possible in RouterOS.
# Written by Shumkov
# Adapted by blacklister
# 20201025
{
/ip firewall address-list
:local update do={
:do {
:local result [/tool fetch url=$url as-value output=user]; :if ($result->"downloaded" != "63") do={ :local data ($result->"data")
:do { remove [find list=$blacklist] } on-error={}
:while ([:len $data]!=0) do={
:if ([:pick $data 0 [:find $data "\n"]]~"^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}") do={
:do {add list=$blacklist address=([:pick $data 0 [:find $data $delimiter]].$cidr) timeout=7d} on-error={}
}
:set data [:pick $data ([:find $data "\n"]+1) [:len $data]]
} ; :log warning "Imported address list < $blacklist> from file: $url"
} else={:log warning "Address list: <$blacklist>, downloaded file to big: $url" }
} on-error={:log warning "Address list <$blacklist> update failed"}
}
$update url=https://lists.blocklist.de/lists/ftp.txt blacklist="blackAddressList" delimiter=("\n")
}
In this case I'll use a smaller ip list: https://lists.blocklist.de/lists/ftp.txt
{
:local timestampLabel "$[/system clock get date] $[/system clock get time]"
:local routeID [/ip route find dst-address=0.0.0.0/0]
# BTest Server Settings
:local btestServer { username="btest" ; password="Ek4@C;f%(-(P3+~5" ; hostname=[/ip route get $routeID value-name=gateway] }
# TCP Test Settings
:local tcpOptions { duration="5s" ; "updateInterval"="1s" }
# UDP Test Settings
:local udpOptions { duration="5s" ; "updateInterval"="1s" ; "rxSize"=1000 ; "txSize"=1000 }
# Test Results
:local tcpRxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 ; "lostPackets"=0 ; size=0 }
:local tcpTxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 ; "lostPackets"=0 ; size=0 }
:local udpRxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 ; "lostPackets"=0 ; size=0 }
:local udpTxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 ; "lostPackets"=0 ; size=0 }
# TCP Downstream Test
:set ($tcpRxTest->"start") "$[/system clock get date] $[/system clock get time]"
/tool bandwidth-test ($btestServer->"hostname") protocol=tcp random-data=no direction=receive duration=($tcpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") do={
:set ($tcpRxTest->"updated") "$[/system clock get date] $[/system clock get time]"
:set ($tcpRxTest->"current") ($"rx-current" / 1000000)
:set ($tcpRxTest->"average") ($"rx-total-average" / 1000000)
:set ($tcpRxTest->"lostPackets") ($"lost-packets" / 1)
:set ($tcpRxTest->"size") ($"rx-size" / 1)
:if ( ($tcpRxTest->"peak") < ($tcpRxTest->"current") ) do={
:set ($tcpRxTest->"peak") ($tcpRxTest->"current")
}
}
:set ($tcpRxTest->"end") "$[/system clock get date] $[/system clock get time]"
# TCP Upstream Test
:set ($tcpTxTest->"start") "$[/system clock get date] $[/system clock get time]"
/tool bandwidth-test ($btestServer->"hostname") protocol=tcp random-data=no direction=transmit duration=($tcpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") do={
:set ($tcpTxTest->"updated") "$[/system clock get date] $[/system clock get time]"
:set ($tcpTxTest->"current") ($"tx-current" / 1000000)
:set ($tcpTxTest->"average") ($"tx-total-average" / 1000000)
:set ($tcpTxTest->"lostPackets") ($"lost-packets" / 1)
:set ($tcpTxTest->"size") ($"tx-size" / 1)
:if ( ($tcpTxTest->"peak") < ($tcpTxTest->"current") ) do={
:set ($tcpTxTest->"peak") ($tcpTxTest->"current")
}
}
:set ($tcpTxTest->"end") "$[/system clock get date] $[/system clock get time]"
# UDP Downstream Test
:set ($udpRxTest->"start") "$[/system clock get date] $[/system clock get time]"
/tool bandwidth-test ($btestServer->"hostname") protocol=udp random-data=no direction=receive duration=($udpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") remote-udp-tx-size=($udpOptions->"rxSize") do={
:set ($udpRxTest->"updated") "$[/system clock get date] $[/system clock get time]"
:set ($udpRxTest->"current") ($"rx-current" / 1000000)
:set ($udpRxTest->"average") ($"rx-total-average" / 1000000)
:set ($udpRxTest->"lostPackets") ($"lost-packets" / 1)
:set ($udpRxTest->"size") ($"rx-size" / 1)
:if ( ($udpRxTest->"peak") < ($udpRxTest->"current") ) do={
:set ($udpRxTest->"peak") ($udpRxTest->"current")
}
}
:set ($udpRxTest->"end") "$[/system clock get date] $[/system clock get time]"
# UDP Upstream Test
:set ($udpTxTest->"start") "$[/system clock get date] $[/system clock get time]"
/tool bandwidth-test ($btestServer->"hostname") protocol=udp random-data=no direction=transmit duration=($udpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") local-udp-tx-size=($udpOptions->"txSize") do={
:set ($udpTxTest->"updated") "$[/system clock get date] $[/system clock get time]"
:set ($udpTxTest->"current") ($"tx-current" / 1000000)
:set ($udpTxTest->"average") ($"tx-total-average" / 1000000)
:set ($udpTxTest->"lostPackets") ($"lost-packets" / 1)
:set ($udpTxTest->"size") ($"tx-size" / 1)
:if ( ($udpTxTest->"peak") < ($udpTxTest->"current") ) do={
:set ($udpTxTest->"peak") ($udpTxTest->"current")
}
}
:set ($udpTxTest->"end") "$[/system clock get date] $[/system clock get time]"
# Report results via system log facility, syslog aggregation will handle the rest
# Log TCP Test Results
:log info ("Bandwidth test of TCP Downstream; Started: " . ($tcpRxTest->"start") . "; Completed: " . ($tcpRxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($tcpRxTest->"peak") . " Mbps; Average: " . ($tcpRxTest->"average") . " Mbps; Duration: " . ($tcpOptions->"duration") . ";")
:log info ("Bandwidth test of TCP Upstream; Started: " . ($tcpTxTest->"start") . "; Completed: " . ($tcpTxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($tcpTxTest->"peak") . " Mbps; Average: " . ($tcpTxTest->"average") . " Mbps; Duration: " . ($tcpOptions->"duration") . ";")
# Log UDP Test Results
:log info ("Bandwidth test of UDP Downstream; Started: " . ($udpRxTest->"start") . "; Completed: " . ($udpRxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($udpRxTest->"peak") . " Mbps; Average: " . ($udpRxTest->"average") . " Mbps; Packet Size: " . ($udpRxTest->"size") . "; Duration: " . ($udpOptions->"duration") . "; Lost Packets: " . ($udpRxTest->"lostPackets") . ";")
:log info ("Bandwidth test of UDP Upstream; Started: " . ($udpTxTest->"start") . "; Completed: " . ($udpTxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($udpTxTest->"peak") . " Mbps; Average: " . ($udpTxTest->"average") . " Mbps; Packet Size: " . ($udpTxTest->"size") . "; Duration: " . ($udpOptions->"duration") . ";")
}
:local version { full="$1"; major=0; minor=0; patch=0 }
:local segment 1
:local match "$1"
:local length [:len $match]
:while ($segment < 4) do={
:local part ""
:local result [:find $match "."]
:if ([:typeof $result] = "num") do={
:set part [:pick $match 0 $result]
} else={
:set part [:pick $match 0 $length]
}
:if ($segment=1) do={
:set ($version->"major") [:tonum $part]
}
:if ($segment=2) do={
:set ($version->"minor") [:tonum $part]
}
:if ($segment=3) do={
:set ($version->"patch") [:tonum $part]
}
:if ([:typeof $result] = "num") do={
:set segment ($segment + 1)
:set match [:pick $match ($result + 1) $length]
:set length [:len $match]
} else={
:set segment 4
}
}
:return $version
:local config { "targetVersion"="6.47.4"; architecture=[/system resource get architecture-name]; "packageURL"="" }
:local parseVersionString [:parse [/system script get func_parseVersionString source]]
:local packageVersion "$[/system package get system version]"
:local routerBoardVersion "$[/system routerboard get current-firmware]"
:local packageMeta [$parseVersionString $packageVersion]
:local routerBoardMeta [$parseVersionString $routerBoardVersion]
:local targetMeta [$parseVersionString ($config->"targetVersion")]
:set ($config->"packageURL") ("https://download.mikrotik.com/routeros/" . ($config->"targetVersion") . "/routeros-" . ($config->"architecture") . "-" . ($config->"targetVersion") . ".npk")
if (($packageMeta->"full") != ($targetMeta->"full")) do={
:log info ("Package version (" . ($packageMeta->"full") . ") does not match target version (" . ($targetMeta->"full") . "). Downloading package file from " . ($config->"packageURL") .".")
/tool fetch url=($config->"packageURL");
if (($packageMeta->"major") > ($targetMeta->"major") || ($packageMeta->"minor") > ($targetMeta->"minor") || ($packageMeta->"patch") > ($targetMeta->"patch")) do={
:log info ("Target package version (" . ($targetMeta->"full") . ") is older than current package version (" . ($packageMeta->"full") . "). Executing downgrade...");
/system package downgrade;
} else={
:log info ("Target package version (" . ($targetMeta->"full") . ") is newer than current package version (" . ($packageMeta->"full") . "). Executing upgrade...");
/system reboot;
}
} else={
if (($routerBoardMeta->"full") != ($packageMeta->"full")) do={
:log info ("RouterBoard firmware (" . ($routerBoardMeta->"full") . ") does not match target version (" . ($targetMeta->"full") . "). Executing update...");
/system routerboard upgrade;
/system reboot;
} else={
:log info ("Software and firmware currently match target version (" . ($targetMeta->"full") . "). No changes necessary.");
}
}
:local months {"jan"="01";"feb"="02";"mar"="03";"apr"="04";"may"="05";"jun"="06";"jul"="07";"aug"="08";"sep"="09";"oct"=10;"nov"=11;"dec"=12}
:local fullDate [/system clock get date]
:local fullTime [/system clock get time]
:local dateTime { "fullDate"=$fullDate ; "fullTime"=$fullTime ; month=[ :pick $fullDate 0 3 ] ; mm=0 ; day=[ :pick $fullDate 4 6 ] ; year=[ :pick $fullDate 7 11 ] ; hour=[ :pick $fullTime 0 2 ] ; hh=[ :pick $fullTime 0 2 ] ; minute=[ :pick $fullTime 3 5 ] ; second=[ :pick $fullTime 6 8 ] ; meridiem="AM" }
:local month ($dateTime->"month")
:set ($dateTime->"mm") ($months->$month)
:if ($dateTime->"hour" > 12) do={
:set ($dateTime->"meridiem") "PM"
:set ($dateTime->"hh") (($dateTime->"hour") - 12)
}
:return ($dateTime)
:local getCurrentDateTime [:parse [/system script get func_getCurrentDateTime source]]
:local dateTime [$getCurrentDateTime]
:return (($dateTime->"year") . "-" . ($dateTime->"mm") . "-" . ($dateTime->"day") . " @ " . ($dateTime->"hh") . ":" . ($dateTime->"minute") . " " . ($dateTime->"meridiem"))
{
:local formatDateTime [:parse [/system script get func_formatDateTime source]]
:local routeID [/ip route find dst-address=0.0.0.0/0]
# BTest Server Settings
:local btestServer { username="btest" ; password="Ek4@C;f%(-(P3+~5" ; hostname=[/ip route get $routeID value-name=gateway] }
# TCP Test Settings
:local tcpOptions { duration="2s" ; "updateInterval"="1s" }
# UDP Test Settings
:local udpOptions { duration="2s" ; "updateInterval"="1s" ; "rxSize"=1000 ; "txSize"=1000 }
# Test Results
:local tcpRxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 }
:local tcpTxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 }
:local udpRxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 ; size=0 ; "lostPackets"=0 }
:local udpTxTest { start="" ; updated="" ; end="" ; peak=0 ; current=0 ; average=0 ; size=0 }
# TCP Downstream Test
:set ($tcpRxTest->"start") [$formatDateTime]
/tool bandwidth-test ($btestServer->"hostname") protocol=tcp random-data=no direction=receive duration=($tcpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") do={
:set ($tcpRxTest->"updated") [$formatDateTime]
:set ($tcpRxTest->"current") ($"rx-current" / 1000000)
:set ($tcpRxTest->"average") ($"rx-total-average" / 1000000)
:if ( ($tcpRxTest->"peak") < ($tcpRxTest->"current") ) do={
:set ($tcpRxTest->"peak") ($tcpRxTest->"current")
}
}
:set ($tcpRxTest->"end") [$formatDateTime]
# Log Test Results
:log info ("Bandwidth test of TCP Downstream; Started: " . ($tcpRxTest->"start") . "; Completed: " . ($tcpRxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($tcpRxTest->"peak") . " Mbps; Average: " . ($tcpRxTest->"average") . " Mbps; Duration: " . ($tcpOptions->"duration") . ";")
# TCP Upstream Test
:set ($tcpTxTest->"start") [$formatDateTime]
/tool bandwidth-test ($btestServer->"hostname") protocol=tcp random-data=no direction=transmit duration=($tcpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") do={
:set ($tcpTxTest->"updated") [$formatDateTime]
:set ($tcpTxTest->"current") ($"tx-current" / 1000000)
:set ($tcpTxTest->"average") ($"tx-total-average" / 1000000)
:if ( ($tcpTxTest->"peak") < ($tcpTxTest->"current") ) do={
:set ($tcpTxTest->"peak") ($tcpTxTest->"current")
}
}
:set ($tcpTxTest->"end") [$formatDateTime]
# Log Test Results
:log info ("Bandwidth test of TCP Upstream; Started: " . ($tcpTxTest->"start") . "; Completed: " . ($tcpTxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($tcpTxTest->"peak") . " Mbps; Average: " . ($tcpTxTest->"average") . " Mbps; Duration: " . ($tcpOptions->"duration") . ";")
# UDP Downstream Test
:set ($udpRxTest->"start") [$formatDateTime]
/tool bandwidth-test ($btestServer->"hostname") protocol=udp random-data=no direction=receive duration=($udpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") remote-udp-tx-size=($udpOptions->"rxSize") do={
:set ($udpRxTest->"updated") [$formatDateTime]
:set ($udpRxTest->"current") ($"rx-current" / 1000000)
:set ($udpRxTest->"average") ($"rx-total-average" / 1000000)
:set ($udpRxTest->"lostPackets") ($"lost-packets" / 1)
:set ($udpRxTest->"size") ($"rx-size" / 1)
:if ( ($udpRxTest->"peak") < ($udpRxTest->"current") ) do={
:set ($udpRxTest->"peak") ($udpRxTest->"current")
}
}
:set ($udpRxTest->"end") [$formatDateTime]
# Log Test Results
:log info ("Bandwidth test of UDP Downstream; Started: " . ($udpRxTest->"start") . "; Completed: " . ($udpRxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($udpRxTest->"peak") . " Mbps; Average: " . ($udpRxTest->"average") . " Mbps; Packet Size: " . ($udpRxTest->"size") . "; Duration: " . ($udpOptions->"duration") . "; Lost Packets: " . ($udpRxTest->"lostPackets") . ";")
# UDP Upstream Test
:set ($udpTxTest->"start") [$formatDateTime]
/tool bandwidth-test ($btestServer->"hostname") protocol=udp random-data=no direction=transmit duration=($udpOptions->"duration") user=($btestServer->"username") password=($btestServer->"password") local-udp-tx-size=($udpOptions->"txSize") do={
:set ($udpTxTest->"updated") [$formatDateTime]
:set ($udpTxTest->"current") ($"tx-current" / 1000000)
:set ($udpTxTest->"average") ($"tx-total-average" / 1000000)
:set ($udpTxTest->"size") ($"tx-size" / 1)
:if ( ($udpTxTest->"peak") < ($udpTxTest->"current") ) do={
:set ($udpTxTest->"peak") ($udpTxTest->"current")
}
}
:set ($udpTxTest->"end") [$formatDateTime]
# Log Test Results
:log info ("Bandwidth test of UDP Upstream; Started: " . ($udpTxTest->"start") . "; Completed: " . ($udpTxTest->"end") . "; Server: " . ($btestServer->"hostname") . "; Peak: " . ($udpTxTest->"peak") . " Mbps; Average: " . ($udpTxTest->"average") . " Mbps; Packet Size: " . ($udpTxTest->"size") . "; Duration: " . ($udpOptions->"duration") . ";")
}
:local parseVersionString [:parse [/system script get func_parseVersionString source]]
:local packageMeta [$parseVersionString "6.47.4"]
:put ("Full Version: " . ($packageMeta->"full"))
:put ("Major Version: " . ($packageMeta->"major"))
:put ("Minor Version: " . ($packageMeta->"minor"))
:put ("Patch Version: " . ($packageMeta->"patch"))
:local version { full="$1"; major=0; minor=0; patch=0 }
:local segment 1
:local match "$1"
:local length [:len $match]
:while ($segment < 4) do={
:local part ""
:local result [:find $match "."]
:if ([:typeof $result] = "num") do={
:set part [:pick $match 0 $result]
} else={
:set part [:pick $match 0 $length]
}
:if ($segment=1) do={
:set ($version->"major") [:tonum $part]
}
:if ($segment=2) do={
:set ($version->"minor") [:tonum $part]
}
:if ($segment=3) do={
:set ($version->"patch") [:tonum $part]
}
:if ([:typeof $result] = "num") do={
:set segment ($segment + 1)
:set match [:pick $match ($result + 1) $length]
:set length [:len $match]
} else={
:set segment 4
}
}
:return $version
# ********** \\\\\\\\\\ === On Login === ////////// ********** #
:local loginUser $user;
:local a "20000";
:local b "15000"
:local c "5000"
:local devices [/ip hotspot active print count-only where user="$loginUser"];
:set $a ($a/$devices);
:set $b ($b/$devices);
:set $c ($c/$devices);
/queue simple
add max-limit=($a."k/".$a."k") name=($loginUser." - ".$address) parent="Hotspot Connection" target=$address
add limit-at=64k/64k max-limit=($a."k/".$a."k") name=($loginUser." : ".$address." - speedtest") packet-marks=speedtest-pkt parent=($loginUser." - ".$address) priority=2/2 target=""
add limit-at=64k/64k max-limit=($b."k/".$b."k") name=($loginUser." : ".$address." - stream") packet-marks=streaming-pkt parent=($loginUser." - ".$address) target=""
add limit-at=64k/64k max-limit=($b."k/".$b."k") name=($loginUser." : ".$address." - all traffic") packet-marks=all-traffic parent=($loginUser." - ".$address) priority=3/3 target=""
add limit-at=64k/64k max-limit=($c."k/".$c."k") name=($loginUser." : ".$address." - mbl gaming") packet-marks=mobile-gaming-pkt parent=($loginUser." - ".$address) priority=1/1 target=""
add limit-at=64k/64k max-limit=($b."k/".$b."k") name=($loginUser." : ".$address." - pc gaming") packet-marks=pc-gaming-pkt parent=($loginUser." - ".$address) priority=1/2 target=""
:foreach QReset in=[/queue simple find active=$loginUser] do={
/queue simple
set $QReset max-limit=($a."k/".$a."k")
}
# ********** \\\\\\\\\\ === On Logout === ////////// ********** #
:local loginUser $user;
/queue simple
remove [find name=($loginUser." - ".$address)]
remove [find name=($loginUser." : ".$address." - speedtest")]
remove [find name=($loginUser." : ".$address." - stream")]
remove [find name=($loginUser." : ".$address." - all traffic")]
remove [find name=($loginUser." : ".$address." - mbl gaming")]
remove [find name=($loginUser." : ".$address." - pc gaming")]
#Function to parse SNMP-get on mikrotik routers
#PARAMS
#ip - the IP to poll
#community - the SNMP community for the device
#oid - the OID to retrieve from the device
#ver- the SNMP version to use
#call the function by using
#:global ip "x.x.x.x"; - set the IP variable
#:global community "public"; - set the community variable
#:global oid "x.x.x.x.x.x.x.x.x.x.x.x.x"; - set the OID variable
#global version "x"; - Choices are as follows: 1, 2c, 3
#:global result [$snmpGet ip=$ip community=$community oid=$oid version=$version]; retrieve and parse the result
:global snmpGet do={
:global address $ip;
:global comm $community;
:global id $oid;
:global ver $version;
:execute script={
/tool snmp-get address=$address community=$comm version=$ver oid=$id} file=temp.txt;
:while ([:len [/file find where name="temp.txt"]] = 0) do={
:delay 1s;
}
:while ([/file get temp.txt contents] = "") do={
:delay 1s;
}
:local res [:pick [/file get temp.txt contents] 81 [:len [/file get temp.txt contents]]];
if ([:pick $res [find "VALUE"]] > 0) do={
:local prev "";
:local str "";
:local count 0;
:local arr "";
:for i from=0 to=([:len $res] - 1) do={
:local char [:pick $res $i]
:if ($char = " ") do={
:if ($prev != " " && $prev != ";" && $prev != "") do={
:set $char ";";
:set $count ($count + 1);
} else={
:set $char "";
}
}
:if ($count <= 3) do={
:set $str ($str . $char);
}
:if ($char = ";") do={
:if ($arr = "") do={
:set $arr [:pick $str 0 ([:len $str]-1)];
} else={
:set $arr ($arr, [:pick $str 0 ([:len $str]-1)]);
}
:set $str "";
}
:set $prev $char;
}
:if ([:len [/file find where name="temp.txt"]] > 0) do={
/file remove [find where name="temp.txt"];
}
:if ([:len [/system script environment find where name="address"]] > 0) do={
/system script environment remove [find where name="address"];
}
:if ([:len [/system script environment find where name="comm"]] > 0) do={
/system script environment remove [find where name="comm"];
}
:if ([:len [/system script environment find where name="id"]] > 0) do={
/system script environment remove [find where name="id"];
}
:if ([:len [/system script environment find where name="ver"]] > 0) do={
/system script environment remove [find where name="ver"];
}
:if ([:len $arr] != 3) do={
:return "Invalid OID, community, IP, or version.";
} else={
:return $arr;
}
} else={
:return "Error retrieving SNMP value.";
}
}
#Function to parse SNMP-get on mikrotik routers
#PARAMS
#ip - the IP to poll
#community - the SNMP community for the device
#oid - the OID to retrieve from the device
#ver- the SNMP version to use
#call the function by using
#:global ip "x.x.x.x" - set the IP variable
#:global community "public" - set the community variable
#:global oid "x.x.x.x.x.x.x.x.x.x.x.x.x" - set the OID variable
#global version "x"; - Choices are as follows: 1, 2c, 3
#:global result [$snmpGet ip=$ip community=$community oid=$oid version=$version]; retrieve and parse the result
:global snmpGet do={
:global address $ip
:global comm $community
:global id $oid
:global ver $version
:execute script={
/tool snmp-get address=$address community=$comm version=$ver oid=$id
} file=temp.txt
:while ([:len [/file find where name="temp.txt"]] = 0) do={
:delay 1s
}
:while ([/file get temp.txt contents] = "") do={
:delay 1s
}
:local res [:pick [/file get temp.txt contents] 81 [:len [/file get temp.txt contents]]]
if ([:pick $res [find "VALUE"]] > 0) do={
:local prev ""
:local str ""
:local count 0
:local arr ""
:for i from=0 to=([:len $res] - 1) do={
:local char [:pick $res $i]
:if ($char = " ") do={
:if ($prev != " " && $prev != ";" && $prev != "") do={
:set $char ";"
:set $count ($count + 1)
} else={
:set $char ""
}
}
:if ($count <= 3) do={
:set $str ($str . $char)
}
:if ($char = ";") do={
:if ($arr = "") do={
:set $arr [:pick $str 0 ([:len $str]-1)]
} else={
:set $arr ($arr, [:pick $str 0 ([:len $str]-1)])
}
:set $str ""
}
:set $prev $char
}
:if ([:len [/file find where name="temp.txt"]] > 0) do={
/file remove [find where name="temp.txt"]
}
:if ([:len [/system script environment find where name="address"]] > 0) do={
/system script environment remove [find where name="address"]
}
:if ([:len [/system script environment find where name="comm"]] > 0) do={
/system script environment remove [find where name="comm"]
}
:if ([:len [/system script environment find where name="id"]] > 0) do={
/system script environment remove [find where name="id"]
}
:if ([:len [/system script environment find where name="ver"]] > 0) do={
/system script environment remove [find where name="ver"]
}
:if ([:len $arr] != 3) do={
:return "Invalid OID, community, IP, or version."
} else={
:return $arr
}
} else={
:return "Error retrieving SNMP value."
}
}
#Function to parse SNMP-get on mikrotik routers
#PARAMS
#ip - the IP to poll
#community - the SNMP community for the device
#oid - the OID to retrieve from the device
#ver- the SNMP version to use
#call the function by using
#:global ip "x.x.x.x" - set the IP variable
#:global community "public" - set the community variable
#:global oid "x.x.x.x.x.x.x.x.x.x.x.x.x" - set the OID variable
#global version "x"; - Choices are as follows: 1, 2c, 3
#:global result [$snmpGet ip=$ip community=$community oid=$oid version=$version]; retrieve and parse the result
:global snmpGet do={
:global address $ip
:global comm $community
:global id $oid
:global ver $version
:execute script={
/tool snmp-get address=$address community=$comm version=$ver oid=$id
} file=temp.txt
:while ([:len [/file find where name="temp.txt"]] = 0) do={
:delay 1s
}
:while ([/file get temp.txt contents] = "") do={
:delay 1s
}
:local res [:pick [/file get temp.txt contents] 81 [:len [/file get temp.txt contents]]]
if ([:pick $res [find "VALUE"]] > 0) do={
:local prev ""
:local str ""
:local count 0
:local arr ""
:for i from=0 to=([:len $res] - 1) do={
:local char [:pick $res $i]
:if ($char = " ") do={
:if ($prev != " " && $prev != ";" && $prev != "") do={
:set $char ";"
:set $count ($count + 1)
} else={
:set $char ""
}
}
:if ($count <= 3) do={
:set $str ($str . $char)
}
:if ($char = ";") do={
:if ($arr = "") do={
:set $arr [:pick $str 0 ([:len $str]-1)]
} else={
:set $arr ($arr, [:pick $str 0 ([:len $str]-1)])
}
:set $str ""
}
:set $prev $char
}
:if ([:len [/file find where name="temp.txt"]] > 0) do={
/file remove [find where name="temp.txt"]
}
:foreach test in={"address";"comm";"id";"ver"} do={
:if ([:len [/system script environment find where name=$test]] > 0) do={
/system script environment remove [find where name=$test]
}
}
:if ([:len $arr] != 3) do={
:return "Invalid OID, community, IP, or version."
} else={
:return $arr
}
} else={
:return "Error retrieving SNMP value."
}
}
:if ([:len [/file find where name="temp.txt"]] > 0) do={
/file remove [find where name="temp.txt"]
}
:foreach test in={"address";"comm";"id";"ver"} do={
:if ([:len [/system script environment find where name=$test]] > 0) do={
/system script environment remove [find where name=$test]
}
}
/file remove [find where name="temp.txt"]
/system script environment remove [find where name~"^(address|comm|id|ver)$"]
/tool snmp-get address=192.168.1.60 community=public version=2c oid="1.3.6.1.4.1.14988.1.1.3.8.0"
##Init:
/import flash/MTM/Facts.rsc;
:global MtmFacts;
##Examples:
##Epoch formatted time:
:local epoch [($MtmFacts->"execute") nsStr="getTools()->getTime()->getEpoch()->getCurrent()"];
:put ($epoch ); #1633096186
##Strings functions:
:local strTool [($MtmFacts->"execute") nsStr="getTools()->getStrings()"];
#trim
:local myStr " My string with leading and traling spaces and line breaks and chr returns \n\r";
:local result [($strTool->"trim") str=$myStr];
:put ($result); # "My string with leading and traling spaces and line breaks and chr returns";
#replace
:local myStr "Hello World";
:local find "Hell";
:local replace "gkTks";
:local result [($strTool->"replace") str=$myStr find=$find replace=$replace];
:put ($result); #"gkTkso World";
##IP
:local ipv4Tool [($MtmFacts->"execute") nsStr="getTools()->getParsing()->getIPv4()"];
:local addr "10.0.0.1";
:local result [($ipv4Tool >"isRFC1918") $addr];
:put ($result); #true
## literally 100s more. Also tons of model "objects", with methods for manipulating interfaces, dhcp servers, ips etc.
It would seem to me that snippets strewn throughout your code means you are refactoring everything when MT makes a change.Another one reinvented the wheel...
Is better what I do on my Snippets: one simply clear action without interdipendency than can broke someting (or all) if something is changed on "shared" functions...
# from
:local classId "tool-directories";
:global MtmFacts;
:if ($MtmFacts = nil) do={
:error ($classId.": MTM Factories not loaded");
}
# to
:local classId "tool-directories"
:global MtmFacts
:if ($MtmFacts = nil) do={ :error "$classId: MTM Factories not loaded" }
:if ([/system package get [find name=wireless] disabled] = false) do= {
# >is false<
} else={
# >is true<
}
# that I would have written instead
/system package
:if ([get [find where name=wireless] disabled]) do={
# >is true<
} else={
# >is false<
}
/interface
:if ([:len [find where type=wlan]] > 0) do={
# at least one wireless interface is present on board
} else={
# no wireless interfaces present on board
}
/ip firewall mangle
add action=mark-connection chain=input in-interface="MyVPN" new-connection-mark=VPNConnection passthrough=yes
add action=mark-routing chain=output connection-mark=VPNConnection new-routing-mark=VPNRoute passthrough=no
/ip route
add distance=1 gateway="MyVPN" routing-mark=VPNRoute
/ip firewall mangle
add action=add-dst-to-address-list address-list=POE address-list-timeout=none-static chain=prerouting comment="PoE Add IP to Address List" dst-port=6112 protocol=tcp
/system script
add dont-require-permissions=no name="Dynamic Routes from address-list" owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":foreach i in=[/ip firewall address-list\
\_find disabled=no] do={\r\
\n :local poeIP [/ip firewall address-list get \$i address];\r\
\n :local poeROUTE [/ip route rule find comment=\$poeIP];\r\
\n\r\
\n :if (\$poeROUTE != \"\") do={\r\
\n :log info message=\"\$poeIP already routed\"\r\
\n} else= {\r\
\n /ip route rule add dst-address=\$poeIP src-address=\"10.0.32.0/24\" table=VPNRoute comment=\"\$poeIP\"\r\
\n :log info message=\"address \$poeIP route added\"\r\
\n }\r\
\n}"
{
:global prevstatus;
:global status [:ip route get value-name=active [:ip route find comment="3. Recursive lookup for Virgin connection (Via WAN routing table)"]]
:if ( "$status" != "$prevstatus" ) do={
:log warn "Virgin gateway changed status from \"$prevstatus\" -> \"$status\" (true=up, false=down, nothing=unintialized)";
:tool e-mail send to=user1@jdomain1.com subject="Virgin WAN gateway changed status" body=( [ :system clock get date ] . " " . [ :system clock get time ] . " gateway changed status from \"$prevstatus\" -> \"$status\" (true=up, false=down, nothing=unintialized)" )
:tool e-mail send to=user2@domain2.com subject="Virgin WAN gateway changed status" body=( [ :system clock get date ] . " " . [ :system clock get time ] . " gateway changed status from \"$prevstatus\" -> \"$status\" (true=up, false=down, nothing=unintialized)" )
}
:global prevstatus $status
}
New script for RouterOS v7, pleaseI will try to get all the useful links to threads to look at when some script is needed, that is not yet in wiki or is in wiki, just to get them not buried under loads other posts.
Check time of the post, to make some link to RouterOS version these where created for.
:put "Hello Word"
:put "Hello Excel"
:put "Hello Access"
#########################################################################
#A single script to manage Netwatch
#########################################################################
/tool netwatch
:local myHost $host
:local myStatus [ get [find where host=$myHost ] status ]
:local myComment [ get [find where host=$myHost ] comment ]
# Notify ################################################################
:log error "Connection $myStatus to $host:$myComment at $[/system clock get time]"
/tool e-mail send to="mail@here" subject="$myComment: $myStatus to $host from $[/system identity get name] at $[/system clock get time]" body="Netwatch"
#######################################################################
# Fetch and Run a remote script and stop duplicated runs
#######################################################################
:global piUsername
:global piPassword
:local scriptFile "IPDB2.rsc"
:local sourceFolder "files"
:local destFolder "scripts"
:local piIPaddr "192.x.x.x"
:local fetchFileFirst true
:global IPDBscriptNotRunning
:local DisableFetchLogging true
#######################################################################
# Only run if another version is not running
#######################################################################
:if ( $IPDBscriptNotRunning ) do={
/log info "Going to run $sourceFolder/$scriptFile - Will be be fetched first? $fetchFileFirst "
:if ( $fetchFileFirst ) do={
:do {
:if ( $DisableFetchLogging ) do={ [ /system logging set [find where topics~"info" and disabled=no] disabled=yes] }
/tool fetch address=$piIPaddr src-path="$sourceFolder/$scriptFile" user="$piUsername" mode=ftp password="$piPassword" dst-path="$destFolder/$scriptFile"
:if ( $DisableFetchLogging ) do={ [ /system logging set [find where topics~"info" and disabled=yes] disabled=no] }
} on-error={
:if ( $DisableFetchLogging ) do={ [ /system logging set [find where topics~"info" and disabled=yes] disabled=no] }
}
} else={
/log info "Using saved version of $sourceFolder/$scriptFile"
}
# Set flag to stop this script duplicating
:set IPDBscriptNotRunning false
/import "$destFolder/$scriptFile"
# Unset flag once script has run
:set IPDBscriptNotRunning true
} else={
/log info "[IPDB] another currently running. Not starting"
}
It works incorrectly, if there is any disabled log entry, for example for debugging, it is unnecessarily enabled.[*]It has a switch to disable "info" logging - fetch puts in a log entry every time that clogs up the Log File
Don't ask the water to stop wetting.you might suggest how to selectively disable/enable log rules
rather than leaving a slightly passive-aggresive comment.
{
:local logIDs [/system logging find where topics~"info" and disabled=no]
/system logging set $logIDs disabled=yes
# /tool fetch
/system logging set $logIDs disabled=no
}
That's easy. Just freeze it and it's not wet anymore -> problem solved.Don't ask the water to stop wetting.
:local wifiItem;
:local wifiItemMac;
:local dhcpItem;
:local dhcpIPaddr;
:local dhcpServer;
:local dhcpName;
:local dhcpStatus;
:local dhcpLastSeen;
:local newComment;
:local currentComment;
:foreach wifiItem in=[/caps-man registration-table find] do={
:set wifiItemMac [/caps-man registration-table get $wifiItem value-name=mac-address];
:set dhcpItem [/ip dhcp-server lease find where mac-address=$wifiItemMac];
:if ($dhcpItem != "") do={
:set dhcpIPaddr [/ip dhcp-server lease get $dhcpItem value-name=active-address];
:set dhcpName [/ip dhcp-server lease get $dhcpItem value-name=host-name];
:set dhcpServer [/ip dhcp-server lease get $dhcpItem value-name=server];
:set dhcpStatus [/ip dhcp-server lease get $dhcpItem value-name=status];
#:set dhcpLastSeen [/ip dhcp-server lease get $dhcpItem value-name=last-seen];
:set newComment ($dhcpIPaddr . "::" . $dhcpName . "::" . \
$dhcpServer. "::" . $dhcpStatus . "::" . \
$dhcpLastSeen);
#:put ($newComment . " for " . $wifiItemMac);
if ([/caps-man access-list find where mac-address=$wifiItemMac] = "") do={
#didnt find a comment, add new
:put ("Add access-list " . $newComment . " for " . $wifiItemMac);
[/caps-man access-list add mac-address=$wifiItemMac action=accept comment=$newComment];
} else={
#found a comment, check comment content
:set currentComment [/caps-man access-list get [/caps-man access-list find where mac-address=$wifiItemMac] value-name=comment];
if ($currentComment != $newComment) do={
[/caps-man access-list set [/caps-man access-list find where mac-address=$wifiItemMac] comment=$newComment];
} else={
:put ("Comment that didnt change " . $currentComment);
}
}
} else={
:put ("No dhcp item for " . $wifiItemMac);
};
};
Someone?can someone update this script?
(i want to send Firewall Filter info on mail)
https://wiki.mikrotik.com/wiki/Firewall_Usage
Tnx
Open a separate topic for request something new, this section is for what is already ready and work.Someone?
:local emailTo "XXXXXX@gmail.com"
:local emailSubject "Unreachable Gateway Detected"
:local emailBody "An unreachable gateway has been detected."
:local DeviceName [/system identity get name]
:local commentFilters ("From WAN 1", "From WAN 2", "From WAN 3")
:foreach commentFilter in=$commentFilters do={
:local unreachableGateways [:toarray [/routing route find where unreachable and comment=$commentFilter]]
:if ([:len $unreachableGateways] > 0) do={
:log warning ("An unreachable gateway has been detected " . $commentFilter)
/tool e-mail send to="XXXXXX@gmail.com" subject="\E2\9A\A0 [$DeviceName] $emailSubject $commentFilter" body="$emailBody"
}
}
Kepp the working oneSPAM, this topic is for what already work, not for ask support on not working script.…
:foreach item in=[/user/active find] do={:if ([/user find name=[/user/active get $item]->"name"]) do={} else={:do {/user/active request-logout $item} on-error={:put "bugger"}}}
:foreach item in=[/user/active find] do={:if ([/user find name=[/user/active get $item]->"name" disabled] ) do={:do {/user/active request-logout $item} on-error={:put "bugger"}}}
:foreach item in=[/user/active find] do={:if ([/user find name=[/user/active get $item]->"name"] ) do={:if ((([:totime [:pick [/user/active get $item value-name="when"] 11 19]])-23:00:00) > 0) do={:do {/user/active request-logout $item} on-error={:put "bugger"}}}}
# Function to convert date and time to seconds since Unix epoch (1970-01-01)
# Assumes each month is 30 days but this is good enough for me
:local dateTimeToSeconds do={
:local dateTime $1;
:local date [:pick $dateTime 0 10];
:local time [:pick $dateTime 11 19];
:local y [:tonum [:pick $date 0 4]];
:local m [:tonum [:pick $date 5 7]];
:local d [:tonum [:pick $date 8 10]];
:local h [:tonum [:pick $time 0 2]];
:local min [:tonum [:pick $time 3 5]];
:local s [:tonum [:pick $time 6 8]];
:local epoch [:tonum [/system clock get time]];
:return (((((($y - 1970) * 365 + ($y - 1969) / 4 - ($y - 1901) / 100 + ($y - 1601) / 400 + $d + ($m - 1) * 30) * 24 + $h) * 60 + $min) * 60 + $s) - $epoch);
}
:local sessionTimeLimit 28800; # in seconds
# Get current date and time
:local currentDate [/system clock get date];
:local currentTime [/system clock get time];
:local currentDateTime ($currentDate . " " . $currentTime);
# Convert current date and time to seconds since Unix epoch
:local currentDateTimeSec [$dateTimeToSeconds $currentDateTime];
:foreach i in=[/user active find] do={
:put $i
:local userDateTime [/user active get $i value-name=when];
:put $userDateTime
# Convert user login date and time to seconds since Unix epoch
:local userDateTimeSec [$dateTimeToSeconds $userDateTime];
:put $userDateTimeSec
# Calculate the duration of the user session in seconds
:local sessionDuration ($currentDateTimeSec - $userDateTimeSec);
:put $sessionDuration
# Check if the user has been logged in for more than the limit
if ($sessionDuration > $sessionTimeLimit) do={
:do {
# Force log out the user
/user active request-logout numbers=$i
:log info ("Logged out user: " . [/user active get $i value-name=name] . " for exceeding login time limit")
} on-error={
:log warning ("Error logging out user: " . [/user active get $i value-name=name])
};
}
}
It works fine but the active session via Winbox does not disconnect, it only disconnects the active sessions via SSH (CLI).I was surprised that /user active request-logout is undocumented. Also it's not a request
This one uses the date too. Apparently force logging out a user requires reboot permission for this script to work.
:local bot1 ***
:local chatid1 ***
:local src [/system identity get name]
:local ip $host
:local test $type
:local dst $comment
:local time $since
:local stat $status
:local stattext
:if ($stat = "up") do={
:set stattext "UP"
} else={
:set stattext "DOWN"
}
:local logmessage "Src: $src Dst: $dst Stat: $stattext Type: $test Host: $ip Since: $time"
/log warning "$logmessage"
:local tgmessage "Src: *$src* %0ADst: *$dst* %0AStat: *$stattext* %0AType: $test %0AHost: $ip %0ASince: $time"
/tool fetch url="https://api.telegram.org/bot$bot1/sendMessage?chat_id=$chatid1&text=$tgmessage&parse_mode=Markdown" dst-path=telegram.txt
:local cyrb53a do={
:local h1 (0xdeadbeef ^ [:tonum $2])
:local h2 (0x41c6ce57 ^ [:tonum $2])
:local imul do={
:local ah (([:tonum $1] >> 16) & 0xffff)
:local al ([:tonum $1] & 0xffff)
:local bh (([:tonum $2] >> 16) & 0xffff)
:local bl ([:tonum $2] & 0xffff)
:return (($al * $bl + (($ah * $bl + $al * $bh) << 16)) & 0xffffffff)
}
:for i from=0 to=([:len $1] - 1) step=1 do={
:local ch [:tonum "0x$[:convert [:pick $1 $i] to=hex]"]
:set h1 [$imul ($h1 ^ $ch) 0x85ebca77]
:set h2 [$imul ($h2 ^ $ch) 0xc2b2ae3d]
}
:set h1 ($h1 ^ [$imul ($h1 ^ ($h2 >> 15)) 0x735a2d97])
:set h2 ($h2 ^ [$imul ($h2 ^ ($h1 >> 15)) 0xcaf649a9])
:set h1 ($h1 ^ ($h2 >> 16))
:set h2 ($h2 ^ ($h1 >> 16))
:return (2097152 * $h2 + ($h1 >> 11))
}
:put [$cyrb53a "We like MikroTik RouterOS script writing" 0]
:local cyrb53a do={
:local h1 (0xdeadbeef ^ [:tonum $2])
:local h2 (0x41c6ce57 ^ [:tonum $2])
:for i from=0 to=([:len $1] - 1) step=1 do={
:local ch [:tonum "0x$[:convert [:pick $1 $i] to=hex]"]
:set h1 (($h1 ^ $ch) * 0x85ebca77)
:set h2 (($h2 ^ $ch) * 0xc2b2ae3d)
}
:set h1 ($h1 ^ (($h1 ^ ($h2 >> 15)) * 0x735a2d97))
:set h2 ($h2 ^ (($h2 ^ ($h1 >> 15)) * 0xcaf649a9))
:set h1 ($h1 ^ ($h2 >> 16))
:set h2 ($h2 ^ ($h1 >> 16))
:return ((2097152 * $h2 + ($h1 >> 11)) & 0xffffffffffffffff)
}
:put [$cyrb53a "We like MikroTik RouterOS script writing" 0]
:global cyrb53a do={ :local imul do={ :local s1 [:tonum $1] :local s2 [:tonum $2] :local ah (($s1 >> 16) & 0xffff) :local al ( $s1 & 0xffff) :local bh (($s2 >> 16) & 0xffff) :local bl ( $s2 & 0xffff) :return (($al * $bl + (($ah * $bl + $al * $bh) << 16)) & 0xffffffff) } :local p1 [:tostr $1] :local p2 [:tonum $2] :local h1 (0xdeadbeef ^ $p2) :local h2 (0x41c6ce57 ^ $p2) :local ch "" :for i from=0 to=([:len $p1] - 1) step=1 do={ :set ch [:tonum "0x$[:convert [:pick $p1 $i] to=hex]"] :set h1 [$imul ($h1 ^ $ch) 0x85ebca77] :set h2 [$imul ($h2 ^ $ch) 0xc2b2ae3d] } :set h1 ($h1 ^ [$imul ($h1 ^ ($h2 >> 15)) 0x735a2d97]) :set h2 ($h2 ^ [$imul ($h2 ^ ($h1 >> 15)) 0xcaf649a9]) :set h1 ($h1 ^ ($h2 >> 16) ) :set h2 ($h2 ^ ($h1 >> 16) ) :return (2097152 * $h2 + ($h1 >> 11)) } :put [$cyrb53a "We like MikroTik RouterOS script writing" 0]
:global cyrb53a do={ :local p1 [:tostr $1] :local p2 [:tonum $2] :local h1 (0xdeadbeef ^ $p2) :local h2 (0x41c6ce57 ^ $p2) :local ch "" :for i from=0 to=([:len $p1] - 1) step=1 do={ :set ch [:tonum "0x$[:convert [:pick $p1 $i] to=hex]"] :set h1 (($h1 ^ $ch) * 0x85ebca77) :set h2 (($h2 ^ $ch) * 0xc2b2ae3d) } :set h1 ($h1 ^ (($h1 ^ ($h2 >> 15)) * 0x735a2d97)) :set h2 ($h2 ^ (($h2 ^ ($h1 >> 15)) * 0xcaf649a9)) :set h1 ($h1 ^ ($h2 >> 16) ) :set h2 ($h2 ^ ($h1 >> 16) ) :return ((2097152 * $h2 + ($h1 >> 11)) & 0xffffffffffffffff) } :put [$cyrb53a "We like MikroTik RouterOS script writing" 0]
# return common subnet prefix of two ip
:global getIpCommonPrefix do={
:local xored ([:tonum [:toip $1]] ^ [:tonum [:toip $2]])
:local prefix 32
:while ($xored) do={
:set xored ($xored >> 1)
:set prefix ($prefix - 1)
}
:return $prefix
}
:put [$getIpCommonPrefix 192.168.88.77 192.168.88.111]
# return array with subnets between two ip
:global getSubnetsBetweenIp do={
:local ip1 [:toip $1]
:local ip2 [:toip $2]
:local subnets [:toarray ""]
:global getIpCommonPrefix
:local prefix [$getIpCommonPrefix $1 $2]
:local submask (255.255.255.255 << (32 - $prefix))
:local addrspace (~$submask)
:local network
:local broadcast
:if ($prefix = 0) do={
:set network 0.0.0.0
:set broadcast 255.255.255.255
} else={
:set network ($ip1 & $submask)
:set broadcast ($ip1 | $addrspace)
}
:if ($ip1 > $ip2) do={
:set ip1 $ip2
:set ip2 [:toip $1]
}
:if ($ip1 = $network && $ip2 = $broadcast) do={
:set subnets ($subnets, ($network."/".$prefix))
} else={
:local finded1
:local finded2
:while ($prefix < 32 && !($finded1 = $ip1 && $finded2 = $ip2)) do={
:set prefix ($prefix + 1)
:set submask (255.255.255.255 << (32 - $prefix))
:set addrspace (~$submask)
:set network ($ip1 & $submask)
:local loop true
:while ($loop && $network <= $ip2) do={
:if ($network >= $finded1 && $network <= $finded2) do={
:if ($finded2 < 255.255.255.255) do={
:set network ($finded2 + 1)
} else={
:set loop false
}
}
:if ($loop) do={
:set broadcast ($network | $addrspace)
:if ($network >= $ip1 && $broadcast <= $ip2) do={
:if ($network < $finded1 || [:typeof $finded1] = "nothing") do={ :set finded1 $network }
:if ($broadcast > $finded2 || [:typeof $finded2] = "nothing") do={ :set finded2 $broadcast }
:set subnets ($subnets, ($network."/".$prefix))
}
:if ($broadcast < 255.255.255.255) do={
:set network ($broadcast + 1)
} else={
:set loop false
}
}
}
}
}
:return $subnets
}
:put [$getSubnetsBetweenIp 0.0.0.1 255.255.255.254]
:put [$getSubnetsBetweenIp 255.255.255.254 0.0.0.0]
:put [$getSubnetsBetweenIp 0.0.0.1 255.255.255.255]
:put [$getSubnetsBetweenIp 0.0.0.0 255.255.255.255]
# return an array of subnets included in the given subnet
:global getIncludedSubnets do={
:local prefix [:tonum [:pick $1 ([:find $1 "/"] + 1) [:len $1]]]
:local add [:tonum $2]
:local subnets [:toarray ""]
:if ($add >= 0 && $add <= 12 && ($prefix + $add) <= 32) do={
:local ip [:toip [:pick $1 0 [:find $1 "/"]]]
:local submask (255.255.255.255 << (32 - $prefix))
:local addrspace (~$submask)
:local network
:local broadcast
:if ($prefix = 0) do={
:set network 0.0.0.0
:set broadcast 255.255.255.255
} else={
:set network ($ip & $submask)
:set broadcast ($ip | $addrspace)
}
:if ($add = 0) do={
:set subnets ($subnets, ($network."/".$prefix))
} else={
:set prefix ($prefix + $add)
:local step (1 << (32 - $prefix))
:local loop true
:while ($loop && $network <= $broadcast) do={
:set subnets ($subnets, ($network."/".$prefix))
:if ((255.255.255.255 - $network) >= $step) do={
:set network ($network + $step)
} else={
:set loop false
}
}
}
}
:return $subnets
}
:put [$getIncludedSubnets 192.168.88.77/24 5]
:put [$getIncludedSubnets 192.168.88.77/24 0]
:put [$getIncludedSubnets 255.255.255.255/0 0]
:global mylist [:toarray ""]
:global minprefix 32
:local addrlist [/ip firewall address-list print detail as-value where ";allowed-ip;white-list;local-networks;service-addresses;test-list;"~list]
:foreach addr in=$addrlist do={
:local ip
:local prefix
:if ([:find ($addr->"address") "/"] > 0) do={
:set ip [:toip [:pick ($addr->"address") 0 [:find ($addr->"address") "/"]]]
:set prefix [:tonum [:pick ($addr->"address") ([:find ($addr->"address") "/"] + 1) [:len ($addr->"address")]]]
} else={
:set ip [:toip ($addr->"address")]
:set prefix 32
}
:if ([:typeof $ip] != "nil") do={
:local submask (255.255.255.255 << (32 - $prefix))
:local subnet
:if ($prefix = 0) do={
:set subnet "0.0.0.0"
} else={
:set subnet [:tostr ($ip & $submask)]
}
:if ([:typeof ($mylist->$subnet)] = "nothing" || ($mylist->$subnet) > $prefix) do={
:set ($mylist->$subnet) $prefix
}
:if ($minprefix > $prefix) do={
:set minprefix $prefix
}
}
}
:global inMyList do={
:global mylist
:global minprefix
:local network [:toip $1]
:local submask 255.255.255.255
:for prefix from=32 to=$minprefix step=-1 do={
:local subnet [:tostr $network]
:if ([:typeof ($mylist->$subnet)] != "nothing" && ($mylist->$subnet) <= $prefix) do={ :return true }
:set submask ($submask << 1)
:set network ($network & $submask)
}
:return false
}
# Usage test
:local ip 192.168.88.1
:for i from=1 to=254 step=1 do={
:if ([$inMyList $ip]) do={
:put $ip
} else={
:set ($mylist->[:tostr $ip]) 32
# /ip firewall address-list add address=$ip list=test-list
}
:set ip ($ip + 1)
}
:global ipLocation {
"1.0.0.0"={24;"US"};
"1.0.1.0"={24;"CN"};
"1.0.2.0"={23;"CN"};
"1.0.4.0"={22;"AU"};
"1.0.8.0"={21;"CN"};
"1.0.16.0"={20;"JP"};
# . . . . . . . . .
}
:global ipCountries {
"AU"="Australia";
"CN"="China";
"JP"="Japan";
"US"="United States of America";
# . . . . . . . . .
}
:global ipMinPrefix 32
:global ipMaxPrefix 0
:foreach param in=$ipLocation do={
:if (($param->0) < $ipMinPrefix) do={ :set ipMinPrefix ($param->0) }
:if (($param->0) > $ipMaxPrefix) do={ :set ipMaxPrefix ($param->0) }
}
:global ipGetLocation do={
:global ipLocation
:global ipMaxPrefix
:global ipMinPrefix
:local submask (255.255.255.255 << (32 - $ipMaxPrefix))
:local network ([:toip $1] & $submask)
:for prefix from=$ipMaxPrefix to=$ipMinPrefix step=-1 do={
:local subnet [:tostr $network]
:if ([:typeof ($ipLocation->$subnet)] != "nothing" && ($ipLocation->$subnet->0) <= $prefix) do={
:return ($ipLocation->$subnet->1)
}
:set submask ($submask << 1)
:set network ($network & $submask)
}
:return []
}
:global ipGetSubnet do={
:global ipLocation
:global ipMaxPrefix
:global ipMinPrefix
:local submask (255.255.255.255 << (32 - $ipMaxPrefix))
:local network ([:toip $1] & $submask)
:for prefix from=$ipMaxPrefix to=$ipMinPrefix step=-1 do={
:local subnet [:tostr $network]
:if ([:typeof ($ipLocation->$subnet)] != "nothing" && ($ipLocation->$subnet->0) <= $prefix) do={
:return ($subnet."/".($ipLocation->$subnet->0))
}
:set submask ($submask << 1)
:set network ($network & $submask)
}
:return []
}
:global ipGetInfo do={
:global ipLocation
:global ipMaxPrefix
:global ipMinPrefix
:local submask (255.255.255.255 << (32 - $ipMaxPrefix))
:local network ([:toip $1] & $submask)
:for prefix from=$ipMaxPrefix to=$ipMinPrefix step=-1 do={
:local subnet [:tostr $network]
:if ([:typeof ($ipLocation->$subnet)] != "nothing" && ($ipLocation->$subnet->0) <= $prefix) do={
:return {($subnet."/".($ipLocation->$subnet->0)); ($ipLocation->$subnet->1)}
}
:set submask ($submask << 1)
:set network ($network & $submask)
}
:return [:toarray ""]
}
:global ipCountries
:global ipGetLocation
:local allConn [/ip firewall connection print detail as-value]
:foreach conn in=$allConn do={
:local src [:pick ($conn->"src-address") 0 [:find ($conn->"src-address") ":"]]
:local dst [:pick ($conn->"dst-address") 0 [:find ($conn->"dst-address") ":"]]
:local srcWhois $src
:local dstWhois $dst
:if ($src = "Your external ip here") do={
:set srcWhois "Router"
} else={
:local ip [:toip $src]
:if ($ip & 255.0.0.0 = 10.0.0.0 || $ip & 255.255.0.0 = 192.168.0.0 || $ip & 255.240.0.0 = 172.16.0.0) do={
:set srcWhois "Localhost"
} else={
:local ipCode [$ipGetLocation $src]
:if ([:typeof $ipCode] != "nil") do={
:set srcWhois ($ipCountries->$ipCode)
}
}
}
:if ($dst = "Your external ip here") do={
:set dstWhois "Router"
} else={
:local ip [:toip $dst]
:if ($ip & 255.0.0.0 = 10.0.0.0 || $ip & 255.255.0.0 = 192.168.0.0 || $ip & 255.240.0.0 = 172.16.0.0) do={
:set dstWhois "Localhost"
} else={
:local ipCode [$ipGetLocation $dst]
:if ([:typeof $ipCode] != "nil") do={
:set dstWhois ($ipCountries->$ipCode)
}
}
}
:put ($srcWhois." -> ".$dstWhois)
}
# same thing using another function
:global ipGetInfo
:foreach conn in=$allConn do={
:local src [:pick ($conn->"src-address") 0 [:find ($conn->"src-address") ":"]]
:local dst [:pick ($conn->"dst-address") 0 [:find ($conn->"dst-address") ":"]]
:local srcWhois $src
:local dstWhois $dst
:if ($src = "Your external ip here") do={
:set srcWhois "Router"
} else={
:local ip [:toip $src]
:if ($ip & 255.0.0.0 = 10.0.0.0 || $ip & 255.255.0.0 = 192.168.0.0 || $ip & 255.240.0.0 = 172.16.0.0) do={
:set srcWhois "Localhost"
} else={
:local ipInfo [$ipGetInfo $src]
:if ([:len $ipInfo]) do={
:set srcWhois (($ipCountries->($ipInfo->1))." (".($ipInfo->0).")")
}
}
}
:if ($dst = "Your external ip here") do={
:set dstWhois "Router"
} else={
:local ip [:toip $dst]
:if ($ip & 255.0.0.0 = 10.0.0.0 || $ip & 255.255.0.0 = 192.168.0.0 || $ip & 255.240.0.0 = 172.16.0.0) do={
:set dstWhois "Localhost"
} else={
:local ipInfo [$ipGetInfo $dst]
:if ([:len $ipInfo]) do={
:set dstWhois (($ipCountries->($ipInfo->1))." (".($ipInfo->0).")")
}
}
}
:put ($srcWhois." -> ".$dstWhois)
}
import file=MikroTikIpLocation.rsc
COLUMN[3] == '-' ? '' : COLUMN[3]
COLUMN[4]
many thanksMethod of working with regional ip address databases without using a firewall address list - does not take away the performance of executing rules using lists.
t all subnets in the database are unique. And you can get a list of subnets missed in the database.