From: vados-dev <192440777+vados-dev@users.noreply.github.com> Date: Fri, 12 Jun 2026 07:50:05 +0000 (+0300) Subject: Autocommit in repo: ros.vados.ru, generated by owner: root, in 10:50:04 12.06.2026. X-Git-Url: https://git.vados.ru/gitweb.cgi?a=commitdiff_plain;h=6160edd189f83c38fcbf058c98d508e93abfc6ef;p=Mikrotiks%2Fros.vados.ru.git Autocommit in repo: ros.vados.ru, generated by owner: root, in 10:50:04 12.06.2026. --- diff --git a/html/AM-GlobalFunc.rsc b/html/AM-GlobalFunc.rsc index a805c08a9..11bae8cc3 100644 --- a/html/AM-GlobalFunc.rsc +++ b/html/AM-GlobalFunc.rsc @@ -17,9 +17,9 @@ :global GlobalFuncReady false; # Git commit id & info, expected configuration version -:global CommitId "main/681/d4dd28fb"; +:global CommitId "main/682/8d03743d"; :global CommitTAG "unknown"; -:global CommitInfo "Autocommit in repo: ros.vados.ru, generated by owner: root, in 10:45:03 12.06.2026."; +:global CommitInfo "Autocommit in repo: ros.vados.ru, generated by owner: root, in 10:50:04 12.06.2026."; # The variables are received right here. :global GlobalConfVersion 140; diff --git a/html/tmp/Binary.backup b/html/tmp/Binary.backup index 54ea96c7c..8ca2d0d23 100644 Binary files a/html/tmp/Binary.backup and b/html/tmp/Binary.backup differ diff --git a/html/tmp/Config.rsc b/html/tmp/Config.rsc index 1ac8f21c3..127dd4cfe 100644 --- a/html/tmp/Config.rsc +++ b/html/tmp/Config.rsc @@ -1,103 +1,32 @@ -# 2026-05-01 09:20:02 by RouterOS 7.22 -# software id = 2961-C4ZZ +# 2026-06-12 07:20:04 by RouterOS 7.23.1 +# software id = A8L5-07YF # -# model = RBD52G-5HacD2HnD -# serial number = HCX084RAVFA +# model = RB952Ui-5ac2nD +# serial number = D3D50CEDCD38 /interface bridge -add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ - short +add dhcpv6-agent-circuit-id="\$(INTERFACE):\$(VID)" dhcpv6-agent-remote-id=\ + "\$(BRIDGEMAC)" name=Bridge-LAN port-cost-mode=short /interface ethernet -set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ - F6:BE:9D:85:53:F5 name="ether1 - Unet" -set [ find default-name=ether3 ] comment=LEN -set [ find default-name=ether4 ] comment=NUC -/interface l2tp-server -add comment=Server disabled=yes name=l2tp-in1 user=vados -/interface l2tp-client -add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ - user=vados -add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ - vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ - user=vados +set [ find default-name=ether1 ] comment="WAN - Unet" loop-protect=off name=\ + "ether1 - Unet" rx-flow-control=auto tx-flow-control=auto +set [ find default-name=ether2 ] comment=LAN-2 +set [ find default-name=ether3 ] advertise="10M-baseT-half,10M-baseT-full,100M\ + -baseT-half,100M-baseT-full,1G-baseT-full,1G-baseX" comment=LAN-3 +set [ find default-name=ether4 ] comment=LAN-4 +set [ find default-name=ether5 ] advertise="10M-baseT-half,10M-baseT-full,100M\ + -baseT-half,100M-baseT-full,1G-baseT-full,1G-baseX" comment=LAN-5 \ + loop-protect=on poe-out=off rx-flow-control=auto tx-flow-control=auto /interface wireless -# managed by CAPsMAN -# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding -set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ - 2ghz-b/g/n basic-rates-a/g=\ - 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ - 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ - disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ - rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ - station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ - dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ - disabled -# managed by CAPsMAN -# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding -set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ - 5ghz-a/n/ac basic-rates-a/g=\ - 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ - 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ - hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ - skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ - wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ - 802.11 wmm-support=enabled wps-mode=disabled +set [ find default-name=wlan1 ] country=belarus disabled=no mode=ap-bridge \ + ssid=vados wireless-protocol=802.11 +set [ find default-name=wlan2 ] country=belarus disabled=no mode=ap-bridge \ + ssid=vados5g wireless-protocol=802.11 /interface wireguard -add listen-port=13231 mtu=1280 name=WG -/interface wireless nstreme -# managed by CAPsMAN -# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding -set wlan1 enable-nstreme=yes -# managed by CAPsMAN -# channel: 5260/20-Ceee/ac/DP(17dBm), SSID: vados5g, local forwarding -set wlan2 enable-nstreme=yes -/caps-man security -add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ - group-encryption=aes-ccm name=security -/caps-man configuration -add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ - XX country=belarus datapath.client-to-client-forwarding=yes \ - .local-forwarding=yes name=cfg-2ghz security=security ssid=vados -add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ - XXXX country=belarus datapath.client-to-client-forwarding=yes \ - .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g -add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ - country=belarus datapath.client-to-client-forwarding=yes \ - .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g -/disk -add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +add listen-port=29185 mtu=1420 name=WG /interface list -add comment=defconf name=WAN -add comment=defconf name=LAN -/interface lte apn -set [ find default=yes ] ip-type=ipv4 use-network-apn=no -/interface wifi channel -add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX -add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC -add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N -add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX -add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G -add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN -/interface wifi datapath -add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath -/interface wifi security -add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ - group-key-update=1h management-protection=allowed name=sec2g -add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ - group-encryption=ccmp group-key-update=5m management-encryption=cmac \ - management-protection=required name=sec5G -/interface wifi configuration -add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ - security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados -add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ - sec2g security.ft=yes .ft-over-ds=yes ssid=vados -add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ - yes .ft-over-ds=yes ssid=vados -add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ - security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ - ssid=vados -add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ - sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados -add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +add name=LAN +add exclude=LAN name=WAN +add exclude=LAN include=WAN name=Internet /interface wireless security-profiles set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ dynamic-keys supplicant-identity=MikroTik @@ -119,627 +48,285 @@ add name=MikroNUC options=HostName add name=master options=HostName add name=MikroYellow options=HostName add name="=\"Client ID\"" options=HostName -add name=mVados options=HostName -add name=hostname-search-set options=HostName /ip dns forwarders -add comment=BS dns-servers=1.1.1.1,1.0.0.1 name=blsp.at verify-doh-cert=no +add dns-servers=1.1.1.1,1.0.0.1 name=blsp.at verify-doh-cert=no add comment=Kra dns-servers=1.0.0.1,1.1.1.1 name=slon2.to verify-doh-cert=no add dns-servers=1.1.1.1,1.0.0.1 name=slon3.at verify-doh-cert=no add dns-servers=1.0.0.1,1.1.1.1 name=slon3.cc verify-doh-cert=no add dns-servers=1.1.1.1,1.0.0.1 name=bs2web.at verify-doh-cert=no add dns-servers=1.1.1.1,1.0.0.1 name=bs2best.at verify-doh-cert=no add dns-servers=1.0.0.1,1.1.1.1 name=psrms.is verify-doh-cert=no -add dns-servers=1.0.0.1,1.1.1.1 name=m.blsp.at verify-doh-cert=no -add comment=telegram disabled=yes dns-servers=10.30.30.81 name=\ - api.telegram.org verify-doh-cert=no +add dns-servers=10.30.30.81 name=reg.vados.ru verify-doh-cert=no /ip ipsec proposal set [ find default=yes ] disabled=yes /ip pool -add name=dhcp ranges=10.30.30.150-10.30.30.200 +add name=dhcp ranges=10.30.30.83-10.30.30.254 /ip dhcp-server -add add-arp=yes address-pool=dhcp dhcp-option-set=domain-search-set \ - dynamic-lease-identifiers=client-mac,client-id,opt-82 interface=\ - Bridge-LAN lease-time=10m name=masterDHCP server-address=10.30.30.81 \ - use-reconfigure=yes -/ip hotspot user profile -set [ find default=yes ] address-pool=dhcp +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 /ip smb users set [ find default=yes ] disabled=yes add disabled=yes name=vados +/ipv6 dhcp-client option +add code=119 name=domain-search-list value="0x03'WORKGROUP'0x00" +add code=12 name=HostName value="\$(HOSTNAME)" +add code=61 name=DUID value=0x00030001488f5a8e1abc +add code=61 name=clientid +/ipv6 dhcp-server option +add code=119 name=domain-search-list value="0x03'WORKGROUP'0x00" +add code=12 name=HostName value="\$(HOSTNAME)" +add code=61 name=CLIENT_DUID +add code=61 name=CLIENT_MAC /ppp profile set *FFFFFFFE use-upnp=no /routing bgp template set default disabled=no output.network=bgp-networks /routing table add disabled=no fib name=To-VPN -/snmp community -set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ - private /system logging action add email-start-tls=yes email-to=vados@vados.ru name=email target=email /system script -add comment="Example add WU servers to AddrList" dont-require-permissions=no \ - name=WU-add-to-list owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - \_Script to add target web sites DNS IP addresses into address list\r\ - \n# Tested with Mikrotik 6.4x\r\ - \n# Syed Jahanzaib / aacable@hotmail.com\r\ - \n# List name\r\ - \n:local LISTNAME \"windowsupdateslist\"\r\ - \n# Web site names which will be added in address list\r\ - \n:local TARGET1 \"update.microsoft.com\"\r\ - \n:local TARGET2 \"download.windowsupdate.com\"\r\ - \n:local TARGET3 \"download.microsoft.com\"\r\ - \n:local TARGET4 \"windowsupdate.com\"\r\ - \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ - \n:local TARGET6 \"wustat.windows.com\"\r\ - \n:local TARGET7 \"stats.microsoft.com\"\r\ - \n:local TARGET8 \"mp.microsoft.com\"\r\ - \n:local TARGET9 \"ws.microsoft.com\"\r\ - \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ - \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ - \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ - \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ - \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ - \n \r\ - \n# 1st time runner, check if address list is not created previously and a\ - dd entries in it for 1st time usage\r\ - \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ - {\r\ - \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ - \_resolved entry for 1st time usage ... zaib\"\r\ - \n \r\ - \n:local FirstAddr [resolve \$TARGET1];\r\ - \n\r\ - \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ - t=\$TARGET1;\r\ - \n} else={\r\ - \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ - hecking if DNS entries can be added in it ...\"\r\ - \n}\r\ - \n \r\ - \n# Check DNS entries and collect matching names\r\ - \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ - \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ - ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ - \_] do={\r\ - \n \r\ - \n# Get IP Address from the names and hold it in temporary buffer\r\ - \n:local Buffer [/ip dns cache get \$i data];\r\ - \ndelay delay-time=10ms\r\ - \n \r\ - \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ - ation\r\ - \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ - ={\r\ - \n \r\ - \n# Fetch DNS names for the entries\r\ - \n:local sitednsname [/ip dns cache get \$i name] ;\r\ - \n \r\ - \n# Print name in LOG window\r\ - \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ - \n \r\ - \n# Add IP addresses and there names to the address list\r\ - \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ - \$sitednsname;\r\ - \n}\r\ - \n}" -add comment="Add Hosts DNS names to NoWG addres list" \ - dont-require-permissions=no name=Add2vdsina owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - \_Script to add target web sites DNS IP addresses into address list\r\ - \n# Tested with Mikrotik 6.4x\r\ - \n# \r\ - \n# List name\r\ - \n:local LISTNAME \"NoWG\"\r\ - \n#\r\ - \n# Web site names which will be added in address list\r\ - \n:local TARGET1 \"comp-lenta.ru\"\r\ - \n:local TARGET2 \"ok.ru\"\r\ - \n:local TARGET3 \"vk.com\"\r\ - \n#:local TARGET4 \"smtp.mail.me.com\"\r\ - \n#:local TARGET4 \"windowsupdate.com\"\r\ - \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ - \n#:local TARGET6 \"wustat.windows.com\"\r\ - \n#:local TARGET7 \"stats.microsoft.com\"\r\ - \n#:local TARGET8 \"mp.microsoft.com\"\r\ - \n#:local TARGET9 \"ws.microsoft.com\"\r\ - \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ - \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ - \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ - \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ - \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ - \n \r\ - \n# 1st time runner, check if address list is not created previously and a\ - dd entries in it for 1st time usage\r\ - \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ - {\r\ - \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ - \_resolved entry for 1st time usage ... zaib\"\r\ +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ \n\r\ - \n:local FirstAddr [resolve \$TARGET1];\r\ + \n#/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@1\ + 0.30.30.86.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.86.pub\";\ \n\r\ - \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ - t=\$TARGET1;\r\ + \n#:local Script AM-setup\ + \n;\r\ + \n#/system/script/add name=\$Script owner=\$Script source=([ /tool/fetch c\ + heck-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \".r\ + sc\") output=user as-value ]->\"data\");\r\ + \n\ + \n#/usb1/mikro_bak_rsa.pub\ + \n\ \n\r\ - \n} else={\r\ - \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ - hecking if DNS entries can be added in it ...\"\r\ - \n}\r\ + \n#\ \n\r\ - \n# Check DNS entries and collect matching names\r\ - \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ - \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n#/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@1\ + 0.30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\ \n\r\ - \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n#\r\ + \n\ + \n#root.mnuc.backuper\ + \n\ \n\r\ - \n# Get IP Address from the names and hold it in temporary buffer\r\ - \n:local Buffer [/ip dns cache get \$i data];\r\ - \ndelay delay-time=10ms\r\ - \n:log info (\"1: \$Buffer\"); \r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n\ + \n#:local Script AM-GlobalConfig;\ \n\r\ - \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ - ation\r\ - \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ - ={\r\ + \n#/system/script/add name=\$Script owner=\$Script source=([ /tool/fetch c\ + heck-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \".r\ + sc\") output=user as-value ]->\"data\");\r\ + \n\ + \n#/usb1/mikro_bak_rsa.pub\ + \n#:local FetchFile AM-DOHCert.rsc\ + \n\ \n\r\ - \n:log info (\"2: \$Buffer\"); \r\ - \n \r\ - \n# Fetch DNS names for the entries\r\ - \n:local sitednsname [/ip dns cache get \$i name] ;\r\ - \n \r\ - \n# Print name in LOG window\r\ - \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ - \n \r\ - \n# Add IP addresses and there names to the address list\r\ - \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ - \$sitednsname;\r\ - \n}\r\ - \n}" -add comment="Flush DNS Cache" dont-require-permissions=no name=\ - DNS_Flush_Cache owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ - "/ip dns cache flush" -add dont-require-permissions=no name=create_mkdir_function owner=vados \ - policy=read,write source="# Written by Phillip Stromberg in 2019\r\ - \n# Distributed under the MIT license\r\ - \n# \r\ - \n# \r\ - \n# this creates a function called \$mkdir\r\ - \n# from the command line you will be able to just type \"\$mkdir some/new\ - /folder\"\r\ - \n# and all the folders that need to be created will be\r\ - \n# if the folder already existed, it is ignored\r\ - \n\r\ - \n:log info \"Creating \\\$mkdir function...\"\r\ - \n\r\ - \n:global mkdir do={\r\ - \n # \$1 refers to the input variable the user passed in to us\r\ - \n :local newFolder \$1;\r\ - \n\r\ - \n # we'll use this variable to report error messages that may arise\r\ - \n :local errorMsg;\r\ - \n\r\ - \n # if the user put a slash on the end of the new folder name, remove \ - it\r\ - \n # i.e. \"some/test/\" becomes \"some/test\"\r\ - \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ - \r\ - \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ - \n }\r\ \n\r\ - \n # if the user put a slash at the beginning of the new folder name, r\ - emove it\r\ - \n # i.e. \"/some/test\" becomes \"some/test\"\r\ - \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ - \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ - \n }\r\ + \n#\ + \n:global MkDir;\ \n\r\ - \n :if ([/file find name=\$newFolder] != \"\") do={\r\ - \n :set errorMsg \"'\$newFolder' already exists.\";\r\ - \n :log debug \"mkdir: \$errorMsg\";\r\ - \n :return \$newFolder;\r\ - \n }\r\ + \n\ + \n#:local FetchFile Binary.backup\ + \n:local localDir \"\";\ + \n\ + \n\r\ + \n#\$MkDir \$localDir;\r\ + \n\ + \n#\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \$FetchFile) dst-path=(\ + \$localDir . \$FetchFile);\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global GlobalConfReady false;\r\ + \n#\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in AM-Init-Script or AM-setup scripts\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix (a);\r\ + \n:global CheckSumsVerify true;\r\ \n\r\ - \n # the name of the temp file to create\r\ - \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ \n\r\ - \n # port 0 is unlikely to be open to HTTP requests...\r\ - \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ \n\r\ - \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n# Debug output for specific script:\r\ + \n#:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ \n\r\ - \n # this is where the folder creation happens\r\ - \n # `as-value` prevents status messages from printing\r\ - \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ - inting.\r\ - \n :do {\r\ - \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ - on=0.001s as-value;\r\ - \n } on-error={}\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ \n\r\ - \n # this waits for the temporary dir to show up so there isn't a race \ - \r\ - \n # condition where you call mkdir and then try to do something before\ - \_the \r\ - \n # folder is actually created\r\ - \n :local count 0;\r\ - \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ - \n :if (\$count >= 50) do={\r\ - \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ - be long enough\r\ - \n :set errorMsg \"New folder could not be created at \$newFold\ - er\";\r\ - \n :log error \"mkdir: \$errorMsg\"\r\ - \n :error \$errorMsg\r\ - \n }\r\ - \n :delay 0.1s;\r\ - \n :set count (\$count + 1);\r\ - \n }\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ \n\r\ - \n :return \$newFolder;\r\ - \n}\r\ + \n:global EmailGeneralTo \"vados@vados.ru\";\r\ + \n#:global EmailGeneralCc \"\";\r\ \n\r\ - \n:log info \"Created function \\\$mkdir\"\r\ - \n" -add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ - name=CustomUpdate-Certificates owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - \_CloudFlare\r\ - \n/tool/fetch mode=https url=https://developers.cloudflare.com/ssl/static/\ - origin_ca_ecc_root.pem;\r\ - \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ - otCA.crt.pem;\r\ - \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ \";\r\ - \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ - 2TLSRSASHA2562020CA1-1.crt.pem;\r\ - \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ - pem passphrase=\"\";\r\ - \n# Quad9\r\ - \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ - G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ - \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ - pem passphrase=\"\";\r\ - \n\r\ - \n#:global AmScriptsUrl;\r\ - \n#google\r\ - \n#:local CertName \"GTS-Root-R1.pem\";\r\ - \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ - \r\ - \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ - \n#:set CertName \"GTS-Root-R4.pem\";\r\ - \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ - \r\ - \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ - \n#:set CertName \"GTS-Root-RX.pem\";\r\ - \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ - \r\ - \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ - \n#internet\r\ - \n#:set CertName \"ISRG-Root-X1.pem\";\r\ - \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ - \r\ - \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ - \n#:set CertName \"ISRG-Root-X2.pem\";\r\ - \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ - \r\ - \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ - \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ - \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ - \r\ - \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ - \n\r\ - \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ - h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ - .com/dns-query verify-doh-cert=yes;\r\ - \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ - \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ - ment=\"cloudflare-dns IPv4 1\";\r\ - \n#/ip/dns/static remove [find where address=1.0.0.1];\r\ - \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ - ment=\"cloudflare-dns IPv4 2\"\r\ - \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ - e-dns.com type=AAAA\r\ - \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ - e-dns.com type=AAAA\r\ - \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ - \n#/ip/dns set servers=\"\";" -add dont-require-permissions=no name=script1 owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ - tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ - are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ - dFlare-doh IPv4 1\" host=1.1.1.1;\r\ - \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ - s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ - -doh IPv4 2\" host=1.0.0.1;\r\ - \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ - /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ - le-doh IPv4 1\" host=8.8.8.8;\r\ - \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ - /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ - le-doh IPv4 2\" host=8.8.4.4;\r\ - \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ - /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ - uad9-doh IPv4 1\" host=9.9.9.9;\r\ - \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ - /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ - uad9-doh IPv4 2\" host=149.112.112.112;\r\ - \n\r\ - \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ - .189.2;" -add dont-require-permissions=no name=script2 owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - \r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ \n\r\ - \n:global InspectVar;\r\ - \n#:global RouterBoard;\r\ - \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ - r={}\r\ - \n#:global Resources;\r\ - \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ - \r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ \n\r\ - \n#:global Updates;\r\ - \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ - ={}\r\ + \n:global CertRenewUrl (\$GlobalScriptsUrl . \"certs/\" . \$Identity . \"/\ + \");\r\ + \n:global CertRenewTime 2w;\r\ + \n:global CertRenewPass (a); #{\r\ + \n# \"\";\r\ + \n# \"v3ry-s3cr3t\";\r\ + \n# \"4n0th3r-s3cr3t\";\r\ + \n#};\r\ + \n:global CertWarnTime 1w;\r\ + \n:global CertIssuedExportPass (a); # {\r\ + \n# \"\";\r\ + \n# \"cert1-cn\"=\"v3ry-s3cr3t\";\r\ + \n# \"cert2-cn\"=\"4n0th3r-s3cr3t\";\r\ + \n#};\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ \n\r\ - \n#:global PkgUpdStatus \"undefined\";\r\ - \n#:local Update [/system/package/update/get];\r\ - \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ - ax=5 on-error={};\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ \n\r\ - \n#:log warning [\$InspectVar \$RouterBoard];\r\ - \n#:put [\$InspectVar \$RouterBoard];\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ \n\r\ - \n#:retry command={/system/package/update check-for-updates without-paging\ - \_as-value} delay=300ms max=5 on-error={};\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ \n\r\ - \n#:global arrDeviceInfo ({});\r\ - \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ - \r\ - \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ - /get\" ]];\r\ - \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ - /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ - \")};\r\ - \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ - \n# [:toarray \"\"];\r\ - \n:local arrDeviceInfo ({});\r\ - \n\r\ - \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ - \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ - te/get\" ]]} on-error={:log error (\$error)}\r\ - \n\$InspectVar \$arrDeviceInfo;\r\ - \n" -add comment="Script for setup routeros script system" \ - dont-require-permissions=no name=AM-setup owner=AM-setup policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - !rsc by Vados\r\ - \n# RouterOS script: AM-setup\r\ - \n# Script comment: Script for setup routeros script system\r\ - \n# Copyright (c) 2005-2026 Vados \r\ - \n#\r\ - \n#\r\ - \n# requires RouterOS, version=7.19\r\ - \n# requires device-mode, fetch\r\ - \n#\r\ - \n# :local ScriptName [ :jobname ];\r\ - \n# Additional commands:\r\ - \n#\r\ - \n# For scripts:\r\ - \n#:global NewScript \"script_name\"; \r\ - \n#:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ - \n#/system/script/add name=\$NewScript owner=\$NewScript source=([/tool/fe\ - tch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptAdd . \ - \".rsc\") output=user as-value ]->\"data\");\r\ - \n#:global NewScript (a);\r\ - \n#:global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ - \n#\r\ - \n# For run from terminal:\r\ - \n#/system/script/add name=AM-setup owner=AM-Setup source=([/tool/fetch ch\ - eck-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" outp\ - ut=user as-value ]->\"data\");\r\ - \n#\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ \n\r\ - \n:global ScriptUpdatesCRLF \"LF\";\r\ - \n#:if (\$ScriptUpdatesCRLF != false) do={\r\ - \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ - os\" ] do={\r\ - \n# if (\$ScriptUpdatesCRLF = true) do={\r\ - \n# /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$S\ - cript;\r\ - \n# } else={\r\ - \n# /system/script/set source=[ :tolf [ get \$Script source ] ] \$Scr\ - ipt;\r\ - \n# }\r\ - \n# }\r\ - \n#}\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ \n\r\ - \n# /import verbose=no \$ScriptName\r\ - \n:global SetupScript [ :jobname ];\r\ - \n:global RemoveMe;\r\ - \n:global RunOnce;\r\ - \n:global InitSetup true;\r\ - \n:global tmpfs true;\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ \n\r\ - \n{\r\ - \n :local RmMe [:tobool \$1];\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ \n\r\ - \n :global GlobalScriptsUrl;\r\ - \n :global SetupScript;\r\ - \n :global RemoveMe;\r\ - \n :global InitSetup;\r\ - \n :global tmpfs;\r\ - \n \r\ - \n :local CertCommonName \"Root YE\";\r\ - \n :local CertFileName \"Root-YE.pem\";\r\ - \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ - f852f02a708aa5d5666\";\r\ - \n\r\ - \n :if (\$SetupScript = false) do={\r\ - \n :global SetupScript \"AM-setup\";\r\ - \n }\r\ - \n :if (\$RemoveMe != false) do={\r\ - \n :set RemoveMe true;\r\ - \n }\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ \n\r\ - \n :log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ - \n \r\ - \n :local CertSettings [ /certificate/settings/get ];\r\ - \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ - \\\r\ - \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ - \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ - \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ - onName ] ] > 0)) do={\r\ - \n :put \"Importing certificate...\";\r\ - \n \r\ - \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ - ath=\$CertFileName as-value;\r\ - \n :delay 1s;\r\ - \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ - \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ - ] ] != 1) do={\r\ - \n :error \"Something is wrong with your certificates!\";\r\ - \n };\r\ - \n :delay 1s;\r\ - \n };\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ \n\r\ - \n:local MkTmpfs do={\r\ - \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ - \n :if ([ :len \$TmpFs ] = 1) do={\r\ - \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ - \n :log info (\"The tmpfs is disabled, enabling.\");\r\ - \n /disk/enable \$TmpFs;\r\ - \n }\r\ - \n :return true;\r\ - \n }\r\ - \n :log info (\"Try to removing directory 'tmpfs'.\");\r\ - \n :do {\r\ - \n :retry {\r\ - \n /file/remove tmpfs;\r\ - \n :return true;\r\ - \n } delay=100ms max=10;\r\ - \n } on-error={ }\r\ - \n# \$RmDir \"tmpfs\";\r\ - \n :onerror Err {\r\ - \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource/g\ - et total-memory ] / 3);\r\ - \n :do {\r\ - \n :retry {\r\ - \n /file/get tmpfs;\r\ - \n :return true;\r\ - \n } delay=222ms max=10;\r\ - \n } on-error={ }\r\ - \n } do={\r\ - \n :log warning (\"Creating disk of type tmpfs failed: \" . \$Err);\r\ - \n :return false;\r\ - \n }\r\ - \n# :return true;\r\ - \n}\r\ - \n:if (\$tmpfs = true) do={\r\ - \n :put \"Tmpfs variable is true. Checking for tmpfs/scripts directory...\ - \";\r\ - \n :if ([/file find name=\"tmpfs/scripts\"] != \"\") do={\r\ - \n :log info (\$0 . \"Directory tmpfs/scripts exsist.\");\r\ - \n :return \$true;\r\ - \n } else={\r\ - \n :log warning (\$0 . \"Directory tmpfs/scripts does't exsist.\");\r\ - \n :if ([ \$MkTmpfs ] = false) do={\r\ - \n :log error (\$0 . \"Directory tmpfs is not created!\");\r\ - \n :return false;\r\ - \n } else={\r\ - \n :onerror Err {\r\ - \n /file/add type=\"directory\" name=/tmpfs/scripts;\r\ - \n :do {\r\ - \n :retry {\r\ - \n /file/get /tmpfs/scripts;\r\ - \n :return true;\r\ - \n } delay=100ms max=10;\r\ - \n } on-error={ }\r\ - \n } do={\r\ - \n :log warning (\$0 . \"Making directory 'scripts' failed: \" . \$\ - Err);\r\ - \n :return false;\r\ - \n }\r\ - \n# :return true;\r\ - \n# [ /file/get \$FileName ]\r\ - \n }\r\ - \n# :log error (\$0 . \"Directory tmpfs/scripts does not exsist. Remove\ - \_global variable tmpfs!\");\r\ - \n# :global tmpfs (a);\r\ - \n# return false;\r\ - \n }\r\ - \n}\r\ - \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ - \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ - . [ /system/clock/get time ] . \".rsc\");\r\ - \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ - fig\" ];\r\ - \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ - \n :put \"Installing \$Script...\";\r\ - \n /system/script/remove [ find where name=\$Script ];\r\ - \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ - h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ - \".rsc\") output=user as-value ]->\"data\");\r\ - \n \r\ - \n /system/script run \$Script;\r\ - \n :delay 2s;\r\ - \n };\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ \n\r\ - \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ - ] > 0) do={\r\ - \n :put \"Renaming certificate by its common-name...\";\r\ - \n :global CertificateNameByCN;\r\ - \n \$CertificateNameByCN \$CertFingerprint;\r\ - \n };\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ \n\r\ - \n :if (\$RemoveMe = true) do={\r\ - \n :put \"Add Scheduler for remove this script...\";\r\ - \n :local OnEvent (\":delay 30s;\\n\" . \"/system/script/remove [ find \ - where name=\\\"\$SetupScript\\\" ];\\n\" . \\\r\ - \n \":delay 2s;\\n\" . \"/system/scheduler/remove [ find where name=\\\ - \"_RemoveSetup\\\" ];\\n\" . \\\r\ - \n \":delay 2s;\\n\" . \":global RemoveMe (a);\\n\");\r\ - \n :local Comment \"_RemoveSetup tmp scheduler for remove setup script.\ - \";\r\ - \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-\ - time=startup interval=30s on-event=\$OnEvent;\r\ - \n :log warning (\$0 . \"\\nI've done everything, and now I'm tired..\ - . I'm leaving.\\nThere will be an error below, this is normal.\");\r\ - \n }\r\ - \n :delay 1;\r\ - \n :put \"Loading configuration and functions...\";\r\ - \n :do { \r\ - \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ - \n :put \"Normal removing temporary global environment variables.\";\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ \r\ - \n :global SetupScript (a);\r\ - \n :global InitSetup (a);\r\ - \n :global RemoveMe (a);\r\ - \n } on-error={\r\ - \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ - \n :log error (\$0 . \$ErrorMsg . :error);\r\ - \n :error \$ErrorMsg;\r\ - \n }\r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ \n}\r\ - \n" -add dont-require-permissions=no name=fetchCustom owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - \r\ - \n#root.mnuc.backuper\r\ - \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ - \n#/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@1\ - 0.30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ - \n#:local Script AM-GlobalConfig;\r\ - \n#/system/script/add name=\$Script owner=\$Script source=([ /tool/fetch c\ - heck-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \".r\ - sc\") output=user as-value ]->\"data\");\r\ - \n#/usb1/mikro_bak_rsa.pub\r\ - \n:local FetchFile AM-DOHCert.rsc\r\ - \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \$FetchFile) dst-path=(\ - \"[usb1]/scripts/\" . \$FetchFile);\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ \n" add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ owner=AM-GlobalFunc policy=\ @@ -766,13 +353,13 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:global GlobalFuncReady false;\r\ \n\r\ \n# Git commit id & info, expected configuration version\r\ - \n:global CommitId \"main/366/ab812be1\";\r\ + \n:global CommitId \"main/680/f2c803f5\";\r\ \n:global CommitTAG \"unknown\";\r\ \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ - r: root, in 08:50:03 01.05.2026.\";\r\ + r: root, in 21:20:03 11.06.2026.\";\r\ \n\r\ \n# The variables are received right here.\r\ - \n:global GlobalConfVersion 138;\r\ + \n:global GlobalConfVersion 140;\r\ \n\r\ \n:global SumsDirAndFileName \"tmp/checksums.json\";\r\ \n\r\ @@ -795,8 +382,8 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:global BackupAndUpdateMode;\r\ \n\r\ \n# Single functions, without nested functions.\r\ - \n:global GlobalEnvRemove;\r\ \n:global MiniDateTimeStamp;\r\ + \n:global MicroDateTimeStamp;\r\ \n\r\ \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ \n:global LogPrint;\r\ @@ -835,7 +422,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:global RandomDelay;\r\ \n:global GetRandomNumber;\r\ \n:global EscapeForRegEx;\r\ - \n:global ExitError;\r\ \n:global CharacterMultiply;\r\ \n:global CharacterReplace;\r\ \n:global CleanFilePath;\r\ @@ -846,6 +432,8 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:global EitherOr;\r\ \n:global FormatLine;\r\ \n:global GetRandom20CharAlNum;\r\ + \n:global GetRandom20CharHex;\r\ + \n:global GetRandomNumber;\r\ \n:global Grep;\r\ \n:global IfThenElse;\r\ \n:global MAX;\r\ @@ -858,9 +446,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:global IsTimeSyncCached;\r\ \n:global IsTimeSyncResetNtp;\r\ \n\r\ - \n:global WaitDNSResolving;\r\ - \n:global WaitFullyConnected;\r\ - \n:global WaitTimeSync;\r\ \n:global MkDir;\r\ \n:global RmDir;\r\ \n:global RmFile;\r\ @@ -881,8 +466,12 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:global GlobalConfMigration;\r\ \n:global VersionToNum;\r\ \n:global RequiredRouterOS;\r\ - \n:global FetchLargeFiles;\r\ + \n:global ExitError;\r\ + \n:global ExitOnError;\r\ + \n\r\ + \n:global FetchHugeFiles;\r\ \n:global FetchUserAgentStr;\r\ + \n:global FileExists;\r\ \n:global CertificateAvailable;\r\ \n:global CertificateDownload;\r\ \n:global CertificateNameByCN;\r\ @@ -894,41 +483,36 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n\r\ \n:set IsCheckUpdates do={\r\ \n :local isInfo [:tobool \$1];\r\ - \n :global LogPrint;\r\ \n :global updateChannel;\r\ \n :global PkgUpdStatus;\r\ \n :global currentUpdateChannel;\r\ \n :global ROsVerAvail;\r\ \n :global arrDeviceInfo;\r\ - \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :log info (\$0 . \" \\\$isInfo = \" . \$isInfo); \r\ \n :local CurrentChannel [ /system/package/update/get channel ];\r\ \n :if ([ :len \$updateChannel ] > 0 && \$CurrentChannel != \$updateChann\ el) do={\r\ \n :retry command={/system/package/update set channel=\$updateChannel} \ \_delay=300ms max=5 on-error={};\r\ - \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ - \r\ + \n :log info (\$0 . \" Set updates channel to: \$updateChannel\");\r\ \n }\r\ - \n\r\ \n :local Update [ /system/package/update/get ];\r\ \n :local Channel [ :tostr (\$Update->\"channel\") ];\r\ \n :set currentUpdateChannel \$Channel;\r\ - \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ - \n\r\ - \n\r\ + \n :log info (\$0 . \" Update Channel: \" . \$Channel . \".\");\r\ \n :local StatusPkg \"undefined\";\r\ - \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :log info (\$0 . \" Checking for updates...\");\r\ \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ dates without-paging as-value]->\"status\")} \\\r\ \n delay=300ms max=5 on-error={};\r\ - \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :log info (\$0 . \" \\\$StatusPkg = \" . \$StatusPkg);\r\ \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ s true; } else={ :set PkgUpdStatus false; }\r\ \n :set ROsVerAvail [ :tostr [ /system/package/update/get latest-version \ ] ];\r\ - \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :log info (\$0 . \" \\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ - \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :log info (\$0 . \" \\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ \n :if ([ :typeof \$arrDeviceInfo ] != \"array\") do={\r\ \n :set arrDeviceInfo [:toarray \$arrDeviceInfo];\r\ \n }\r\ @@ -946,15 +530,12 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :global currentUpdateChannel;\r\ \n :global ROsVerAvail;\r\ \n :global arrDeviceInfo;\r\ - \n\r\ \n :local Status \"\";\r\ \n :local Update;\r\ \n :local WaitCount 0;\r\ - \n\r\ \n :if ([ \$IsCheckUpdates true ] = false) do={\r\ \n :return false;\r\ \n }\r\ - \n\r\ \n :set Status [ :tostr [ /system/package/update/get status ] ];\r\ \n :while ((\$Status = \"\" || \$Status = \"finding out latest version...\ \") && \$WaitCount < 60) do={\r\ @@ -962,7 +543,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :set WaitCount (\$WaitCount + 1);\r\ \n :set Status [ :tostr [ /system/package/update/get status ] ];\r\ \n }\r\ - \n\r\ \n :set Update [ /system/package/update/get ];\r\ \n :set currentUpdateChannel [ :tostr (\$Update->\"channel\") ];\r\ \n :set ROsVerAvail [ :tostr (\$Update->\"latest-version\") ];\r\ @@ -975,7 +555,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :set arrDeviceInfo [:toarray \$arrDeviceInfo];\r\ \n }\r\ \n :set (\$arrDeviceInfo->\"devUpdates\") \$Update;\r\ - \n\r\ \n :if (\$Status = \"\" || \$Status = \"finding out latest version...\") \ do={\r\ \n :return false;\r\ @@ -993,7 +572,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:set GetArrDeviceInfo do={\r\ \n :global LogPrint;\r\ \n :global arrDeviceInfo;\r\ - \n\r\ \n :global devBoardName;\r\ \n :global devModel;\r\ \n :global devRunning;\r\ @@ -1165,12 +743,18 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n\r\ \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ tionFunctions ({})}\r\ + \n\r\ \n:set GetRandom20CharAlNum do={\r\ \n :global EitherOr;\r\ \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ \n}\r\ \n\r\ + \n:set GetRandom20CharHex do={:global EitherOr; :return [ :rndstr length=[\ + \_\$EitherOr [ :tonum \$1 ] 20 ] from=\"0123456789abcdef\" ]; }\r\ + \n:set GetRandomNumber do={:global EitherOr; :return [ :rndnum from=0 to=[\ + \_\$EitherOr [ :tonum \$1 ] 4294967295 ] ]; }\r\ + \n\r\ \n:global checkRunJob;\r\ \n:set checkRunJob do={\r\ \n :local Script [ :tostr \$1 ];\r\ @@ -1242,37 +826,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return \$Return;\r\ \n}\r\ \n\r\ - \n# !!! The function is not ready !!!\r\ - \n:global FetchHttpInfo do={\r\ - \n :local Mac [ :tostr \$1 ];\r\ - \n :global CertificateAvailable;\r\ - \n :global IsMacLocallyAdministered;\r\ - \n :global LogPrint;\r\ - \n :local Url \"https://api.macvendors.com/\";\r\ - \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ - y administered\";}\r\ - \n :do {\r\ - \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ - o={\r\ - \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ - \");\r\ - \n :error false;\r\ - \n }\r\ - \n :local Vendor ([ /tool/fetch \r\ - \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ - \n :return \$Vendor;\r\ - \n } on-error={\r\ - \n :onerror Err {\r\ - \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ - as-value;\r\ - \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ - );\r\ - \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ - rr); }\r\ - \n :return \"unknown vendor\";\r\ - \n }\r\ - \n}\r\ - \n\r\ \n:set GetPubIp do={\r\ \n :global DetectIpAddrDefault;\r\ \n :global DetectIpAddrFallback;\r\ @@ -1367,33 +920,28 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ erity \$Severity ] . \": \" . \$Message)}\r\ \n}\r\ \n\r\ - \n# check and download required certificate\r\ \n:set CertificateAvailable do={\r\ \n :local CommonName [ :tostr \$1 ];\r\ \n :local UseFor [ :tostr \$2 ];\r\ \n\r\ \n :global CertificateDownload;\r\ - \n :global LogPrint;\r\ \n :global ParseKeyValueStore;\r\ \n\r\ \n :if ([ :len \$UseFor ] = 0) do={\r\ - \n \$LogPrint warning \$0 (\"The intended use is undefined!\");\r\ + \n :log warning (\$0 . \"The intended use is undefined!\");\r\ \n :set UseFor \"undefined\";\r\ \n }\r\ - \n\r\ \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ \n [ /certificate/settings/get crl-download ] = true && \\\r\ \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ - \n \$LogPrint warning \$0 (\"This system has low free flash space but \ - \" . \\\r\ + \n :log warning (\$0 . \"This system has low free flash space but \" . \ + \\\r\ \n \"is configured to download certificate CRLs to system!\");\r\ \n }\r\ - \n\r\ \n :if ([ :len \$CommonName ] = 0) do={\r\ - \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :log warning (\$0 . \"No CommonName given!\");\r\ \n :return false;\r\ \n }\r\ - \n\r\ \n :local CertSettings [ /certificate/settings/get ];\r\ \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ \r\ @@ -1403,23 +951,20 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \_] ] > 0) do={\r\ \n :return true;\r\ \n }\r\ - \n\r\ \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ ) do={\r\ - \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ - e . \"' not available.\");\r\ + \n :log info (\$0 . \"Certificate with CommonName '\" . \$CommonName . \ + \"' not available.\");\r\ \n :if ([ \$CertificateDownload \$CommonName ] = false) do={\r\ \n :return false;\r\ \n }\r\ \n }\r\ - \n\r\ \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ ) do={\r\ - \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ - with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :log info (\$0 . \"There are \" . \$CertCount . \" Certificates with\ + \_CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ \n :return true;\r\ \n }\r\ - \n\r\ \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ e ] ];\r\ \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ @@ -1428,8 +973,8 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \_= 0) do={\r\ \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ >\"CN\");\r\ - \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ - \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :log info (\$0 . \"Certificate chain for '\" . \$CommonName . \"' \ + is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={\r\ \n :return false;\r\ \n }\r\ @@ -1440,34 +985,30 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return true;\r\ \n}\r\ \n\r\ - \n# download and import certificate\r\ \n:set CertificateDownload do={\r\ \n :local CommonName [ :tostr \$1 ];\r\ - \n\r\ \n :global ScriptUpdatesBaseUrl;\r\ \n :global ScriptUpdatesUrlSuffix;\r\ - \n\r\ \n :global CertificateNameByCN;\r\ \n :global CleanName;\r\ \n :global FetchUserAgentStr;\r\ - \n :global LogPrint;\r\ \n :global RmFile;\r\ \n :global WaitForFile;\r\ \n\r\ - \n \$LogPrint info \$0 (\"Downloading and importing certificate with \" .\ - \_\\\r\ + \n :log info (\$0 . \"Downloading and importing certificate with \" . \\\ + \r\ \n \"CommonName '\" . \$CommonName . \"'.\");\r\ \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ \n :do {\r\ - \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ - \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n /tool/fetch check-certificate=yes-without-crl mode=https http-header\ + -field=({ [ \$FetchUserAgentStr \$0 ] }) \\\r\ \n (\$ScriptUpdatesBaseUrl . \"certs/\" . \$FileName . \$ScriptUpdate\ sUrlSuffix) \\\r\ \n dst-path=\$FileName as-value;\r\ \n \$WaitForFile \$FileName;\r\ \n } on-error={\r\ - \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ - Name '\" . \$CommonName . \\\r\ + \n :log warning (\$0 . \" Failed downloading certificate with CommonNam\ + e '\" . \$CommonName . \\\r\ \n \"' from repository! Trying fallback to mkcert.org...\");\r\ \n :do {\r\ \n :local CertSettings [ /certificate/settings/get ];\r\ @@ -1481,40 +1022,37 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \r\ \n [ :len [ /certificate/builtin/find where common-name=\"ISRG\ \_Root X1\" ] ] > 0)) do={\r\ - \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ - );\r\ + \n :log error (\$0 . \" Required certificate is not available.\");\ + \r\ \n :return false;\r\ \n }\r\ - \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ - \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ - \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ - ({ \$CommonName }) ] \\\r\ - \n dst-path=\$FileName as-value;\r\ + \n /tool/fetch check-certificate=yes-without-crl mode=https http-head\ + er-field=({ [ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n url=\"https://mkcert.org/generate/\" http-data=[ :serialize to=jso\ + n ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ \n \$WaitForFile \$FileName;\r\ \n :if ([ /file/get \$FileName size ] = 0) do={\r\ \n \$RmFile \$FileName;\r\ \n :error false;\r\ \n }\r\ \n } on-error={\r\ - \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ - onName '\" . \$CommonName . \"'!\");\r\ + \n :log error (\$0 . \" Failed downloading certificate with CommonNam\ + e '\" . \$CommonName . \"'!\");\r\ \n :return false;\r\ \n }\r\ \n }\r\ - \n\r\ \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ \n :delay 1s;\r\ \n \$RmFile \$FileName;\r\ - \n\r\ \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ ) do={\r\ \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ +\\\$\") ];\r\ - \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ - Name . \"' still unavailable!\");\r\ + \n :log warning (\$0 . \" Certificate with CommonName '\" . \$CommonNam\ + e . \"' still unavailable!\");\r\ \n :return false;\r\ \n }\r\ - \n\r\ \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ \"_[0-9]+\\\$\") ] do={\r\ \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ @@ -1522,17 +1060,13 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return true;\r\ \n}\r\ \n\r\ - \n# name a certificate by its common-name\r\ \n:set CertificateNameByCN do={\r\ \n :local Match [ :tostr \$1 ];\r\ - \n\r\ \n :global CleanName;\r\ - \n :global LogPrint;\r\ - \n\r\ \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ rint=\$Match or name=\$Match) ]->0);\r\ \n :if ([ :len \$Cert ] = 0) do={\r\ - \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :log warning (\$0 .\" No matching certificate found.\");\r\ \n :return false;\r\ \n }\r\ \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ @@ -1549,14 +1083,16 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return \$Return;\r\ \n}\r\ \n\r\ - \n:set FetchUserAgentStr do={\r\ - \n :local Caller [ :tostr \$1 ];\r\ - \n :global IfThenElse;\r\ - \n :local Resource [ /system/resource/get ];\r\ - \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ - \_\$Resource->\"architecture-name\" . \\\r\ - \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ - 19780)\");\r\ + \n:set FileExists do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local Type [ :tostr \$2 ];\r\ + \n :global FileGet;\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={ :return false; }\r\ + \n :if ([ :len (\$FileVal->\"size\") ] = 0) do={ :return false; }\r\ + \n :if ([ :len \$Type ] = 0 || \$FileVal->\"type\" = \$Type) do={ :return\ + \_true; }\r\ + \n :return false;\r\ \n}\r\ \n\r\ \n:set Grep do={\r\ @@ -1599,6 +1135,18 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n }\r\ \n}\r\ \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={ :set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]; }\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={ :set Path [ :pick \$Path 1 [ :le\ + n \$Path ] ]; }\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={ :set Path [ \ + :pick \$Path 0 ([ :len \$Path ] - 1) ]; }\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ \n:set CleanName do={\r\ \n :local Input [ :tostr \$1 ];\r\ \n :local Return \"\";\r\ @@ -1614,12 +1162,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return \$Return;\r\ \n}\r\ \n\r\ - \n:set GetRandomNumber do={\r\ - \n :global EitherOr;\r\ - \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ - \r\ - \n}\r\ - \n\r\ \n:set RandomDelay do={\r\ \n :local Time [ :tonum \$1 ];\r\ \n :local Unit [ :tostr \$2 ];\r\ @@ -1659,7 +1201,20 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n }\r\ \n}\r\ \n\r\ + \n:set ExitOnError do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :local Error [ :tostr \$2 ];\r\ + \n :global IfThenElse;\r\ + \n :log error (\$Name . \" \" . [ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\ + \\\$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with erro\ + r\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \$E\ + rror) \".\" ]);\r\ + \n}\r\ + \n\r\ \n:set MiniDateTimeStamp do={\r\ + \n :local mikro [ :tobool \$1 ];\r\ \n /system/clock;\r\ \n :local vdate [get date];\r\ \n :local vtime [get time];\r\ @@ -1678,7 +1233,15 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :local HH [:pick \$vtime 0 2];\r\ \n :local mm [:pick \$vtime 3 5];\r\ \n :local ss [:pick \$vtime 6 8];\r\ - \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n :local Return;\r\ + \n :if (\$mikro = true) do={\r\ + \n :set Return ([:pick \$yyyy 2 4] . [:pick \$dd 0 1] . [:pick \$HH 0\ + \_1] . [:pick \$mm 3 4] . [:pick \$ss 6 7]);\r\ + \n } else={\r\ + \n :set Return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\ + \r\ + \n }\r\ + \n :return \$Return;\r\ \n}\r\ \n\r\ \n:set WaitForFile do={\r\ @@ -1709,9 +1272,12 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:set FileGet do={\r\ \n :local FileName [ :tostr \$1 ];\r\ \n :global WaitForFile;\r\ - \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ \n :local FileVal false;\r\ - \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n :do {\r\ + \n :set FileVal [ /file/get \$FileName ];\r\ \n } on-error={ }\r\ \n :return \$FileVal;\r\ \n}\r\ @@ -1719,35 +1285,48 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:set RmDir do={\r\ \n :local DirName [ :tostr \$1 ];\r\ \n :global FileGet;\r\ - \n :global LogPrint;\r\ - \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :log debug (\$0 . \" Removing directory: \". \$DirName);\r\ \n :local DirVal [ \$FileGet \$DirName ];\r\ - \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ - exist.\"); :return true};\r\ - \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ - Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ - \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ - ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ - \r\ - \n :return true;\r\ - \n}\r\ - \n\r\ - \n:set RmFile do={\r\ - \n :local FileName [ :tostr \$1 ];\r\ - \n :global FileGet;\r\ - \n :global LogPrint;\r\ - \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :if (\$DirVal = false) do={\r\ + \n :log debug (\$0 . \" ... which does not exist.\");\r\ + \n :return true;\r\ + \n };\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\r\ + \n :log error (\$0 . \" Directory '\" . \$DirName . \"' is not a direct\ + ory.\");\r\ + \n :return false;\r\ + \n };\r\ + \n :onerror Err {\r\ + \n /file/remove \$DirName;\r\ + \n } do={\r\ + \n :log error (\$0 . \" Removing directory '\" . \$DirName . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n };\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :log debug (\$0 . \" Removing file: \". \$FileName);\r\ \n :local FileVal [ \$FileGet \$FileName ];\r\ - \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ - \_exist.\"); :return true}\r\ + \n :if (\$FileVal = false) do={\r\ + \n :log debug (\$0 . \" ... which does not exist.\");\r\ + \n :return true;\r\ + \n }\r\ \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ sk\") do={\r\ - \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ - ); :return false}\r\ + \n :log error (\$0 . \" File '\" . \$FileName . \"' is not a file.\");\ + \r\ + \n :return false;\r\ + \n }\r\ \n :onerror Err {\r\ \n /file/remove \$FileName;\r\ - \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ - led: \" . \$Err); :return false}\r\ + \n } do={\r\ + \n :log error (\$0 . \" Removing file '\" . \$FileName . \"' failed: \"\ + \_. \$Err); :return false;\r\ + \n }\r\ \n :return true;\r\ \n}\r\ \n\r\ @@ -1757,26 +1336,26 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :global FileGet;\r\ \n :global RmDir;\r\ \n :global WaitForFile;\r\ - \n :global LogPrint;\r\ + \n\r\ \n :local MkTmpfs do={\r\ \n :global WaitForFile;\r\ \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ \n :if ([ :len \$TmpFs ] = 1) do={\r\ \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ - \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n :log info (\$0 . \" The tmpfs is disabled, enabling.\");\r\ \n /disk/enable \$TmpFs;\r\ \n }\r\ \n :return true;\r\ \n }\r\ - \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n :log info (\$0 . \" Creating disk of type tmpfs.\");\r\ \n \$RmDir \"tmpfs\";\r\ \n :onerror Err {\r\ \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ /get total-memory ] / 3);\r\ \n \$WaitForFile \"tmpfs\";\r\ \n } do={\r\ - \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ - \_\$Err);\r\ + \n :log warning (\$0 . \" Creating disk of type tmpfs failed: \" . \$\ + Err);\r\ \n :return false;\r\ \n }\r\ \n :return true;\r\ @@ -1785,10 +1364,10 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :if (\$Path = \"\") do={\r\ \n :return true;\r\ \n }\r\ - \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :log debug (\$0 . \" Making directory: \" . \$Path);\r\ \n :local PathVal [ \$FileGet \$Path ];\r\ \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ - \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :log debug (\$0 . \" ... which already exists.\");\r\ \n :return true;\r\ \n }\r\ \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ @@ -1800,8 +1379,8 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n /file/add type=\"directory\" name=\$Path;\r\ \n \$WaitForFile \$Path;\r\ \n } do={\r\ - \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ - : \" . \$Err);\r\ + \n :log warning (\$0 . \" Making directory '\" . \$Path . \"' failed: \ + \" . \$Err);\r\ \n :return false;\r\ \n }\r\ \n :return true;\r\ @@ -1840,18 +1419,6 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return (\$Return . \$String);\r\ \n}\r\ \n\r\ - \n:set CleanFilePath do={\r\ - \n :local Path [ :tostr \$1 ];\r\ - \n :global CharacterReplace;\r\ - \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ - \"//\" \"/\" ]};\r\ - \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ - \_\$Path ] ]};\r\ - \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ - pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ - \n :return \$Path;\r\ - \n}\r\ - \n\r\ \n:set IfThenElse do={\r\ \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ \$2};\r\ @@ -1895,19 +1462,17 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :local Required [ :tostr \$2 ];\r\ \n :local Warn [ :tostr \$3 ];\r\ \n :global IfThenElse;\r\ - \n :global LogPrint;\r\ \n :global VersionToNum;\r\ \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ \\\$\")) do={\r\ - \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ - \r\ + \n :log error (\$0 . \" No valid RouterOS version: \" . \$Required);\r\ \n :return false;\r\ \n }\r\ \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ e/update/get installed-version ] ]) do={\r\ \n :if (\$Warn = \"true\") do={\r\ - \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ - er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n :log warning (\$0 . \" This \" . [ \$IfThenElse ([ :pick \$Caller \ + 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ es RouterOS \" . \$Required . \". Please update!\");\r\ \n }\r\ @@ -1915,6 +1480,19 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n }\r\ \n :return true;\r\ \n}\r\ + \n\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ \n:set VersionToNum do={\r\ \n :local Input [ :tostr \$1 ];\r\ \n :local Multi 0x1000000;\r\ @@ -1946,12 +1524,12 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n }\r\ \n :return \$Return;\r\ \n}\r\ + \n\r\ \n:set ScriptLock do={\r\ \n :local Script [ :tostr \$1 ];\r\ \n :local WaitMax [ :totime \$2 ];\r\ \n :global GetRandom20CharAlNum;\r\ \n :global IfThenElse;\r\ - \n :global LogPrint;\r\ \n :global ScriptLockOrder;\r\ \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ \n :set ScriptLockOrder ({});\r\ @@ -2018,8 +1596,8 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n }\r\ \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ - \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ - \_exist!\");\r\ + \n :log error (\$0 . \" A script named '\" . \$Script . \"' does not ex\ + ist!\");\r\ \n :error false;\r\ \n }\r\ \n :if ([ \$JobCount \$Script ] = 0) do={\r\ @@ -2028,8 +1606,8 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :error false;\r\ \n }\r\ \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ - \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ - ript . \"', resetting!\");\r\ + \n :log error (\$0 . \" More tickets than running scripts '\" . \$Scrip\ + t . \"', resetting!\");\r\ \n :set (\$ScriptLockOrder->\$Script) ({});\r\ \n /system/script/job/remove [ find where script=\$Script ];\r\ \n }\r\ @@ -2056,12 +1634,14 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \_lock\" \"\" ] . \"...\");\r\ \n :return false;\r\ \n}\r\ + \n\r\ \n:set SendNotification do={ :onerror Err {\r\ \n :global SendNotification2;\r\ \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ \_silent=\$4 });\r\ \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ \n}\r\ + \n\r\ \n:set SendNotification2 do={\r\ \n :local Notification \$1;\r\ \n :global NotificationFunctions;\r\ @@ -2070,10 +1650,10 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ \n }\r\ \n}\r\ + \n\r\ \n:set SymbolByUnicodeName do={\r\ \n :local Name [ :tostr \$1 ];\r\ \n :global EitherOr;\r\ - \n :global LogPrint;\r\ \n :global SymbolsExtra;\r\ \n :local Symbols ({\r\ \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ @@ -2119,13 +1699,14 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ - \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ - . \"'!\");\r\ + \n :log warning (\$0 . \"No symbol available for name '\" . \$Name . \"\ + '!\");\r\ \n :return \"\";\r\ \n }\r\ \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ me) ] . \"\\EF\\B8\\8F\");\r\ \n}\r\ + \n\r\ \n:set SymbolForNotification do={\r\ \n :global NotificationsWithSymbols;\r\ \n :global SymbolByUnicodeName;\r\ @@ -2137,6 +1718,7 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ mbolByUnicodeName \$Symbol ])}\r\ \n :return (\$Return . \" \");\r\ \n}\r\ + \n\r\ \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ \n:set UrlEncode do={\r\ \n :local Input [ :tostr \$1 ];\r\ @@ -2158,21 +1740,12 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n }\r\ \n :return \$Return;\r\ \n}\r\ - \n:set ValidateSyntax do={\r\ - \n :local Code [ :tostr \$1 ];\r\ - \n :global LogPrint;\r\ - \n :onerror Err {\r\ - \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ - \n } do={\r\ - \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ - \n :return false;\r\ - \n }\r\ - \n :return true;\r\ - \n}\r\ + \n\r\ \n:set IsDNSResolving do={\r\ \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ \n :return true;\r\ \n}\r\ + \n\r\ \n:set IsFullyConnected do={\r\ \n :global IsDNSResolving;\r\ \n :global IsTimeSync;\r\ @@ -2180,6 +1753,7 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ \n :return true;\r\ \n}\r\ + \n\r\ \n:set IsTimeSync do={\r\ \n :global IsTimeSyncCached;\r\ \n :global IsTimeSyncResetNtp;\r\ @@ -2220,15 +1794,11 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return true;\r\ \n}\r\ \n\r\ - \n# read parts of a large file\r\ - \n:set FetchLargeFiles do={\r\ - \n :local ScriptName [:tostr \$1];\r\ - \n :local fetchUrl [:tostr \$2];\r\ - \n :local CheckCert [:tostr \$3];\r\ - \n :local fetchMode [:tostr \$4];\r\ - \n :local fetchMethod [:tostr \$5];\r\ - \n :local FetchString \"undefined\";\r\ - \n \r\ + \n:set FetchHugeFiles do={\r\ + \n :local ScriptName [ :tostr \$1 ];\r\ + \n :local Url [ :tostr \$2 ];\r\ + \n :local CheckCert [ :tostr \$3 ];\r\ + \n\r\ \n :global CleanName;\r\ \n :global FetchUserAgentStr;\r\ \n :global GetRandom20CharAlNum;\r\ @@ -2241,50 +1811,36 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n\r\ \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ ithout-crl\" ];\r\ - \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ - ode=\" . \$fetchMode)] ];\r\ - \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ - \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ - \n \r\ + \n\r\ \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ \n :if ([ \$MkDir \$DirName ] = false) do={\r\ \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ \n :return false;\r\ \n }\r\ + \n\r\ \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ \$GetRandom20CharAlNum ]);\r\ - \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ - ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ - \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ - \n :onerror Err {\r\ - \n :set FetchString (\"/tool/fetch \" . \\\r\ - \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ - \_. \$fetchMethod . \"\\\" \")] . \\\r\ - \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ - \_. \"\\\") \" . \\\r\ - \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ - e . \" \")] . \\\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName \ + \\\r\ \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ - lue);\r\ - \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ - \n :put [\$FetchString];\r\ - \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ - fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ - \_\$ScriptName ] }) as-value];\r\ + lue;\r\ \n } do={\r\ \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ \n \$RmFile \$FileName;\r\ \n }\r\ - \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ - \_- \" . \$Err);\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$Url . \" - \"\ + \_. \$Err);\r\ \n \$RmDir \$DirName;\r\ \n :return false;\r\ \n }\r\ + \n\r\ \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ - \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ - \" did not show up.\");\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$Url . \" did\ + \_not show up.\");\r\ \n :return false;\r\ \n }\r\ + \n\r\ \n :local FileSize [ /file/get \$FileName size ];\r\ \n :local Return \"\";\r\ \n :local VarSize 0;\r\ @@ -2301,6 +1857,18 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n :return \$Return;\r\ \n}\r\ \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global CommitBrief;\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (\" . \$GlobalScriptsUrl . \"; \" . [ \$\ + CommitBrief ] . \")\");\r\ + \n}\r\ + \n\r\ \n:set ScriptInstallUpdate do={ :onerror Err {\r\ \n :local Scripts [ :toarray \$1 ];\r\ \n :local NewComment [ :tostr \$2 ];\r\ @@ -2613,36 +2181,35 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ \n }\r\ - \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ - ws and changes are not available.\")}\r\ + \n } else={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nNews and\ + \_changes are not available.\");\r\ + \n\r\ + \n }\r\ \n\r\ - \n :set GlobalConfChanges;\r\ - \n :set GlobalConfMigration;\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={ :set GlobalConfChanges; \ + } else={ :global GlobalConfChanges (a); }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={ :set GlobalConfMigrati\ + on; } else={ :global GlobalConfMigration (a); }\r\ \n }\r\ - \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ - \n}\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ \n\r\ - \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ - \n:set GlobalEnvRemove do={\r\ - \n :local doRmEnv [ :tostr \$1 ];\r\ - \n :global GlobalScriptsUrl;\r\ - \n :local ScriptsUrl;\r\ - \n :global LogPrint;\r\ - \n :if (\$doRmEnv != \"True\") do={\r\ - \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ - rue\\\" for confirm to remove global environment variables!\");\r\ - \n :return [];\r\ - \n :error true; \r\ + \n# load modules\r\ + \n:foreach Script in=[ /system/script/find where name ~ \"^(global-functio\ + ns\\\\.d|mod)/.\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :if ([ \$ValidateSyntax (\$ScriptVal->\"source\") ] = true) do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n \$LogPrint error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \"' f\ + ailed to run: \" . \$Err);\r\ + \n }\r\ \n } else={\r\ - \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ - \n :delay 5;\r\ - \n :foreach var in=[/system/script/environment print as-value] do={/sy\ - stem/script/environment remove (\$var->\".id\")}\r\ - \n :delay 5;\r\ - \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ - \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ - \n :return [];\r\ - \n :error false;\r\ + \n \$LogPrint error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \"' fai\ + led syntax validation, skipping.\");\r\ \n }\r\ \n}\r\ \n\r\ @@ -2650,7 +2217,7 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ \n:put \"Add or/and fix Global scheduler...\";\r\ \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ ; }\";\r\ - \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:local Comment \"Every Day Set Global Environment Variables\";\r\ \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ = 0) do={\r\ \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ @@ -2675,2070 +2242,380 @@ add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ start-time=startup interval=1d on-event=\$OnEvent;\r\ \n}\r\ \n\r\ - \n#:local Resource [ /system/resource/get ];\r\ - \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ - . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ - \".\");\r\ - \n\r\ \n:onerror Err {\r\ \n :global GlobalConfReady;\r\ \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ \_not ready.\"); }; } delay=100ms max=5;\r\ \n\r\ - \n# signal we are ready\r\ - \n:set GlobalFuncReady true;\r\ - \n:set ExitOK true;\r\ \n:log warning (\"This script \$ScriptName Loaded \" . \\\r\ \n [ \$IfThenElse (\$CommitId != \"unknown\") ([ \$CommitBrief ] . \" \ \") ] . \\\r\ \n \"on \" . \$devBoardName . \"\\nRouterOS: \" . \$devCurVersion . \"\ \\nArchitecture: \" . \$devCurArch . \"\\nIdentity: \" . \$Identity);\r\ - \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ - \n\r\ - \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ - \n# log the successful load of the script, or an error if it failed\r\ - \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ - \n" -add comment="Import ssh keys for public key authentication" \ - dont-require-permissions=no name=AM-SshKeysImport owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - !rsc by Vados\r\ - \n# RouterOS script: AM-SshKeysImport\r\ - \n# Script comment: Import ssh keys for public key authentication\r\ - \n# Copyright (c) 2005-2026 Vados \r\ - \n#\r\ - \n# requires RouterOS, version=7.19\r\ - \n#\r\ - \n:local ExitOK false;\r\ - \n:onerror Err {\r\ - \n :global GlobalConfReady; :global GlobalFuncReady;\r\ - \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ - \\\r\ - \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ - ay=500ms max=50;\r\ - \n :local ScriptName [ :jobname ];\r\ - \n\r\ - \n:global SSHKeysImport;\r\ - \n:global SSHKeysImportFile;\r\ - \n\r\ - \n# import single key passed as string\r\ - \n:set SSHKeysImport do={ :onerror Err {\r\ - \n :local Key [ :tostr \$1 ];\r\ - \n :local User [ :tostr \$2 ];\r\ - \n :global GetRandom20CharAlNum;\r\ - \n :global LogPrint;\r\ - \n :global MkDir;\r\ - \n :global RmDir;\r\ - \n :global WaitForFile;\r\ - \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ - \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ - ser!\");\r\ - \n :return false;\r\ - \n }\r\ - \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ - \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ - ;\r\ - \n :return false;\r\ - \n }\r\ - \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ - sv.plain ]->0);\r\ - \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ - ={\r\ - \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ - \_not supported.\");\r\ - \n :return false;\r\ - \n }\r\ - \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ - eyVal->1) ];\r\ - \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ - \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ - \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ - \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ - MD5 . \\\r\ - \n \") is already available for user '\" . \$User . \"'.\");\r\ - \n :return false;\r\ - \n }\r\ - \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ - \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ - \_failed!\");\r\ - \n :return false;\r\ - \n }\r\ - \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ - lNum 6 ] . \".pub\");\r\ - \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ - MD5);\r\ - \n \$WaitForFile \$FileName;\r\ - \n :onerror Err {\r\ - \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ - \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ - \", \" . \$KeyVal->0 . \", \" . \\\r\ - \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ - \r\ - \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ - \n } do={\r\ - \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ - \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ - \n :return false;\r\ - \n }\r\ - \n} do={\r\ - \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ - \n} }\r\ + \n # signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ \n\r\ - \n# import keys from a file\r\ - \n:set SSHKeysImportFile do={ :onerror Err {\r\ - \n :local FileName [ :tostr \$1 ];\r\ - \n :local User [ :tostr \$2 ];\r\ - \n :global EitherOr;\r\ - \n :global FileExists;\r\ - \n :global LogPrint;\r\ - \n :global ParseKeyValueStore;\r\ - \n :global SSHKeysImport;\r\ - \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ - \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ - \_and user!\");\r\ - \n :return false;\r\ - \n }\r\ - \n :if ([ \$FileExists \$FileName ] = false) do={\r\ - \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ - .\");\r\ - \n :return false;\r\ - \n }\r\ - \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ - \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ - ons=dsv.plain ] do={\r\ - \n :local Continue false;\r\ - \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ - {\r\ - \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ - . \$KeyVal->2) \$User ] = false) do={\r\ - \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ - User . \"'.\");\r\ - \n }\r\ - \n :set Continue true;\r\ - \n }\r\ - \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ - \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ - user\") \$User ];\r\ - \n :set Continue true;\r\ - \n }\r\ - \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ - \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ - is not supported.\");\r\ - \n }\r\ - \n }\r\ + \n:log info (\$0 . \"Global configs ready!\");\r\ \n} do={\r\ \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ - \n} }\r\ - \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n}\r\ \n" -add comment="Enable or disable ip addresses based on bridge port state" \ - dont-require-permissions=no name=mod/AM-IPbridge owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - !rsc by Vados\r\ - \n# RouterOS script: mod/AM-IPbridge\r\ - \n# Script comment: Enable or disable ip addresses based on bridge port st\ - ate\r\ - \n# Copyright (c) 2005-2026 Vados \r\ +add comment=\ + "Lookup IP addresses for RKN list and add them to firewall address-list" \ + dont-require-permissions=no name=AM-RKN-dnsLookup owner=AM-RKN-dnsLookup \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-RKN-dnsLookup\r\ + \n# Script comment: Lookup IP addresses for RKN list and add them to firew\ + all address-list\r\ + \n# Copyright (c) 2007-2026 Vados \r\ \n#\r\ \n#\r\ \n# requires RouterOS, version=7.19\r\ \n# requires device-mode, fetch\r\ \n#\r\ + \n# Script description: This script is intended to be run periodically, e.\ + g. once a day, to update the IP addresses in the firewall address-list bas\ + ed on the RKN list.\r\ + \n# It resolves the domain names in the RKN list and a\ + dds the corresponding IP addresses to the specified firewall address-list.\ + \r\ + \n# The script also handles CNAME records by following\ + \_them until it finds A records.\r\ + \n# Usage:\r\ + \n# /system/script { run AM-RKN-dnsLookup; }\r\ \n:local ScriptName [ :jobname ];\r\ \n\r\ - \n# Add this Script scheduler\r\ - \n:if ([ :len [ /system/scheduler/find where name=\$ScriptName ] ] = 0) do\ - ={\r\ - \n:log warning (\"SystemScheduler for script: \" . \$ScriptName . \" is NO\ - T SET! Fix It Now!\");\r\ - \n:local OnEvent \"/system/script/run \$ScriptName;\";\r\ - \n:local Comment \"Every Day Check For Fake Bridges\";\r\ - \n/system/scheduler/add name=\$ScriptName comment=\$Comment start-time=sta\ - rtup interval=1d on-event=\$OnEvent;\r\ - \n}\r\ - \n\r\ - \n:foreach Bridge in=[ /interface/bridge/find ] do={\r\ - \n :local BrName [ /interface/bridge/get \$Bridge name ];\r\ - \n :if ([ :len [ /interface/bridge/port/find where bridge=\$BrName ] ] > \ - 0) do={\r\ - \n :if ([ :len [ /interface/bridge/port/find where bridge=\$BrName and \ - inactive=no ] ] = 0) do={\r\ - \n /ip/address/disable [ find where !dynamic interface=\$BrName ];\r\ - \n } else={\r\ - \n /ip/address/enable [ find where !dynamic interface=\$BrName ];\r\ - \n }\r\ - \n }\r\ - \n}\r\ - \n" -add comment="Check for certificates validity" dont-require-permissions=no \ - name=AM-CheckCerts owner=vados policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - !rsc by Vados\r\ - \n# RouterOS script: AM-CheckCerts\r\ - \n# Script comment: Check for certificates validity\r\ - \n# Copyright (c) 2005-2026 Vados \r\ - \n#\r\ - \n#\r\ - \n# requires RouterOS, version=7.19\r\ - \n# requires device-mode, fetch\r\ - \n\r\ - \n:local ExitOK false;\r\ - \n:onerror Err {\r\ - \n :global GlobalConfReady; :global GlobalFuncReady;\r\ - \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ - \\\r\ - \n do={ :error (\"Global config and/or functions not ready.\"); }; } \ - delay=500ms max=50;\r\ - \n :local ScriptName [ :jobname ];\r\ - \n\r\ - \n :global CertRenewTime;\r\ - \n :global CertRenewUrl;\r\ - \n :global CertWarnTime;\r\ - \n :global Identity;\r\ - \n\r\ - \n :global CertificateAvailable;\r\ - \n :global EscapeForRegEx;\r\ - \n :global IfThenElse;\r\ - \n :global LogPrint;\r\ - \n :global ParseKeyValueStore;\r\ - \n :global ScriptLock;\r\ - \n :global SendNotification2;\r\ - \n :global SymbolForNotification;\r\ - \n :global UrlEncode;\r\ - \n# :global WaitFullyConnected;\r\ - \n\r\ - \n# Add this Script scheduler\r\ - \n:if ([ :len [ /system/scheduler/find where name=\$ScriptName ] ] = 0) do\ + \n:global dnsLookupReady false;\r\ + \n:if ([:typeof \$dnsLookupReady] != \"boolean\") do={ :set dnsLookupReady\ + \_true; }\r\ + \nwhile (!\$dnsLookupReady) do={ :nothing; }\r\ + \n:set dnsLookupReady false;\r\ + \n\r\ + \n:local arrRKN {\r\ + \n \"telegra.ph\"\r\ + \n \"grani.ru\"\r\ + \n \"xhamster.com\"\r\ + \n \"lostfilm.tv\"\r\ + \n \"rutracker.org\"\r\ + \n \"lurkmore.to\"\r\ + \n \"dou.ua\"\r\ + \n \"youporn.com\"\r\ + \n \"pornolab.net\"\r\ + \n \"crimerussia.com\"\r\ + \n \"telegram.org\"\r\ + \n \"api.telegram.org\"\r\ + \n \"facebook.com\"\r\ + \n \"instagram.com\"\r\ + \n \"x.com\"\r\ + \n \"twitter.com\"\r\ + \n \"youtube.com\"\r\ + \n \"googleapis.com\"\r\ + \n \"youtu.be\"\r\ + \n \"googlevideo.com\"\r\ + \n \"gstatic.com\"\r\ + \n \"googleusercontent.com\"\r\ + \n \"nhacmp3youtube.com\"\r\ + \n \"telegram.me\"\r\ + \n \"t.me\";}\r\ + \n\r\ + \n:local ListRKN \"RKN-dnsLookup\";\r\ + \n:local ListComment (\"ListRKN managed by \" . \$ScriptName);\r\ + \n:foreach aListItem in=[/ip/firewall/address-list find list=\$ListRKN] do\ ={\r\ - \n:log warning (\"System Scheduler for script: \" . \$ScriptName . \" is N\ - OT SET! Fix It Now!\");\r\ - \n:local OnEvent \"/system/script/run \$ScriptName;\";\r\ - \n:local Comment \"Every Day Check For Renew Certificates\";\r\ - \n/system/scheduler/add name=\$ScriptName comment=\$Comment start-time=sta\ - rtup interval=1d on-event=\$OnEvent;\r\ - \n}\r\ - \n\r\ - \n\r\ - \n :local CheckCertificatesDownloadImport do={\r\ - \n :local ScriptName [ :tostr \$1 ];\r\ - \n :local CertName [ :tostr \$2 ];\r\ - \n :local FetchName [ :tostr \$3 ];\r\ - \n\r\ - \n :global CertRenewUrl;\r\ - \n :global CertRenewPass;\r\ - \n\r\ - \n :global CertificateNameByCN;\r\ - \n :global EscapeForRegEx;\r\ - \n :global FetchUserAgentStr;\r\ - \n :global LogPrint;\r\ - \n :global RmFile;\r\ - \n :global UrlEncode;\r\ - \n :global WaitForFile;\r\ - \n\r\ - \n :foreach Type in={ \"p12\"; \"pem\" } do={\r\ - \n :local CertFileName ([ \$UrlEncode \$FetchName ] . \".\" . \$Type)\ - ;\r\ - \n \$LogPrint debug \$ScriptName (\"Trying type '\" . \$Type . \"' fo\ - r '\" . \$CertName . \\\r\ - \n \"' (file '\" . \$CertFileName . \"')...\");\r\ - \n\r\ - \n :do {\r\ - \n :onerror Err {\r\ - \n /tool/fetch check-certificate=yes-without-crl \\\r\ - \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] \ - }) \\\r\ - \n (\$CertRenewUrl . \$CertFileName) dst-path=\$CertFileName \ - as-value;\r\ - \n } do={\r\ - \n :if (!(\$Err ~ \"[Ss]tatus 404\")) do={\r\ - \n \$LogPrint warning \$0 (\"Failed fetching certificate: \" . \ - \$Err);\r\ - \n }\r\ - \n :error false;\r\ - \n }\r\ - \n \$WaitForFile \$CertFileName; \r\ - \n\r\ - \n :local DecryptionFailed true;\r\ - \n :foreach I,PassPhrase in=\$CertRenewPass do={\r\ - \n :do {\r\ - \n \$LogPrint debug \$ScriptName (\"Trying \" . \$I . \". passp\ - hrase... \");\r\ - \n :local Result [ /certificate/import file-name=\$CertFileName\ - \_passphrase=\$PassPhrase as-value ];\r\ - \n :if (\$Result->\"decryption-failures\" = 0) do={\r\ - \n \$LogPrint debug \$ScriptName (\"Success!\");\r\ - \n :set DecryptionFailed false;\r\ + \n /ip firewall address-list remove \$aListItem;\r\ + \n}\r\ + \n:foreach aItem in=\$arrRKN do={\r\ + \n# :do {\r\ + \n :retry delay=500ms max=5 on-error={:log error \"dns resolve fail\ + ure [ \$aItem - resolve ip ]\"} command={:resolve \$aItem}\r\ + \n# } on-error={\r\ + \n# :log error \"dns resolve failure [ \$arItem - resolve ip ]\";\r\ + \n# }\r\ + \n :foreach dnsRecord in=[/ip dns cache all find where (name=\$aItem)] \ + do={\r\ + \n :if ([/ip dns cache all get \$dnsRecord type]=\"A\") do={\r\ + \n :local newAddress [/ip dns cache all get \$dnsRecord data];\ + \r\ + \n :do {\r\ + \n /ip firewall address-list add list=\$ListRKN address=\$newA\ + ddress comment=\$aItem;\r\ + \n :log warning \"Successfully adding ip to list A record: \ + \$dnsRecord, address: \$newAddress domain: \$aItem\";\r\ + \n } on-error={\r\ + \n :log error \"error when adding ip to list A record: \$dn\ + sRecord, address: \$newAddress domain: \$aItem\";\r\ \n }\r\ - \n } on-error={ }\r\ - \n }\r\ - \n \$RmFile \$CertFileName;\r\ - \n\r\ - \n :if (\$DecryptionFailed = true) do={\r\ - \n \$LogPrint warning \$ScriptName (\"Decryption failed for certi\ - ficate file '\" . \$CertFileName . \"'.\");\r\ - \n }\r\ - \n\r\ - \n :foreach CertInChain in=[ /certificate/find where common-name!=\ - \$CertName !private-key \\\r\ - \n name~(\"^\" . [ \$EscapeForRegEx \$CertFileName ] . \"_[0-9]\ - +\\\$\") \\\r\ - \n !(subject-alt-name~(\"(^|\\\\W)(DNS|IP):\" . [ \$EscapeForRe\ - gEx \$CertName ] . \"(\\\\W|\\\$)\")) \\\r\ - \n !(common-name=[]) ] do={\r\ - \n \$CertificateNameByCN [ /certificate/get \$CertInChain common-\ - name ];\r\ - \n }\r\ - \n\r\ - \n :return true;\r\ - \n } on-error={\r\ - \n \$LogPrint debug \$ScriptName (\"Could not download certificate \ - file '\" . \$CertFileName . \"'.\");\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :return false;\r\ - \n }\r\ - \n\r\ - \n :local FormatInfo do={\r\ - \n :local Cert \$1;\r\ - \n\r\ - \n :global FormatLine;\r\ - \n :global FormatMultiLines;\r\ - \n :global IfThenElse;\r\ - \n\r\ - \n :local FormatExpire do={\r\ - \n :global CharacterReplace;\r\ - \n :return [ \$CharacterReplace [ \$CharacterReplace [ :tostr \$1 ] \ - \"w\" \"w \" ] \"d\" \"d \" ];\r\ - \n }\r\ - \n\r\ - \n :local FormatCertChain do={\r\ - \n :local Cert \$1;\r\ - \n\r\ - \n :global ParseKeyValueStore;\r\ - \n\r\ - \n :local CertVal [ /certificate/get \$Cert ];\r\ - \n\r\ - \n :if ([ :typeof (\$CertVal->\"issuer\") ] = \"nothing\") do={\r\ - \n :return \"self-signed\";\r\ - \n }\r\ - \n\r\ - \n :local Return \"\";\r\ - \n :for I from=0 to=5 do={\r\ - \n :set Return (\$Return . [ \$ParseKeyValueStore (\$CertVal->\"iss\ - uer\") ]->\"CN\");\r\ - \n :if ([ :len [ /certificate/builtin/find where skid=(\$CertVal->\ - \"akid\") ] ] > 0) do={\r\ - \n :return \$Return;\r\ - \n }\r\ - \n :do {\r\ - \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\ - \"akid\") ] ];\r\ - \n } on-error={\r\ - \n :return (\$Return . \" (possibly incomplete!)\");\r\ \n }\r\ - \n :if ((\$CertVal->\"akid\") = \"\" || (\$CertVal->\"akid\") = (\$\ - CertVal->\"skid\")) do={\r\ - \n :return \$Return;\r\ + \n :if ([/ip dns cache all get \$dnsRecord type]=\"CNAME\") do={\r\ + \n :local cname;\r\ + \n :local nextCname;\r\ + \n :local cnameAddress;\r\ + \n :set cname [/ip dns cache all find where (name=\$aItem && ty\ + pe=\"CNAME\")];\r\ + \n :set nextCname [/ip dns cache all find where (name=[/ip dns \ + cache all get \$cname data] && type=\"CNAME\")];\r\ + \n :while (\$nextCname != \"\") do={\r\ + \n :set cname \$nextCname;\r\ + \n :set nextCname [/ip dns cache all find where (name=[/ip \ + dns cache all get \$cname data] && type=\"CNAME\")];\r\ + \n }\r\ + \n :foreach aRecord in=[/ip dns cache all find where (name=[/ip\ + \_dns cache all get \$cname data] && type=\"A\")] do={\r\ + \n :do {\r\ + \n :set cnameAddress [/ip dns cache all get \$aRecord d\ + ata];\r\ + \n /ip firewall address-list add list=\$ListRKN address\ + =\$cnameAddress comment=\$aItem;\r\ + \n :log warning \"Succesfully adding ip to list CNAME r\ + ecord: \$cname, A record: \$aRecord, address: \$newAddress, from domain: \ + \$aItem.\";\r\ + \n# /ip firewall raw add action=add-dst-to-address-list\ + \_address-list=\$ListRKN address-list-timeout=none-dynamic chain=preroutin\ + g comment=\$aItem content=\$aItem;\r\ + \n } on-error={\r\ + \n :log error \"error when adding ip to list CNAME reco\ + rd: \$cname, A record: \$aRecord, address: \$newAddress, from domain: \$aI\ + tem.\";\r\ + \n }\r\ + \n }\r\ \n }\r\ - \n :set Return (\$Return . \" -> \");\r\ - \n }\r\ - \n :return (\$Return . \"...\");\r\ \n }\r\ + \n}\r\ \n\r\ - \n :local CertVal [ /certificate/get \$Cert ];\r\ - \n\r\ - \n :return ( \\\r\ - \n [ \$FormatLine \"Name\" (\$CertVal->\"name\") ] . \"\\n\" . \\\r\ - \n [ \$IfThenElse ([ :len (\$CertVal->\"common-name\") ] > 0) ([ \$Fo\ - rmatLine \"CommonName\" (\$CertVal->\"common-name\") ] . \"\\n\") ] . \\\r\ - \n [ \$IfThenElse ([ :len (\$CertVal->\"subject-alt-name\") ] > 0) ([\ - \_\$FormatMultiLines \"SubjectAltNames\" (\$CertVal->\"subject-alt-name\")\ - \_] . \"\\n\") ] . \\\r\ - \n [ \$FormatLine \"Private key\" [ \$IfThenElse ((\$CertVal->\"priva\ - te-key\") = true) \"available\" \"missing\" ] ] . \"\\n\" . \\\r\ - \n [ \$FormatLine \"Fingerprint\" (\$CertVal->\"fingerprint\") ] . \"\ - \\n\" . \\\r\ - \n [ \$IfThenElse ([ :len (\$CertVal->\"ca\") ] > 0) [ \$FormatLine \ - \"Issuer\" (\$CertVal->\"ca\") ] [ \$FormatLine \"Issuer chain\" [ \$Forma\ - tCertChain \$Cert ] ] ] . \"\\n\" . \\\r\ - \n \"Validity:\\n\" . \\\r\ - \n [ \$FormatLine \" days\" (\$CertVal->\"days-valid\") ] . \"\\n\ - \" . \\\r\ - \n [ \$FormatLine \" from\" (\$CertVal->\"invalid-before\") ] . \"\ - \\n\" . \\\r\ - \n [ \$FormatLine \" to\" (\$CertVal->\"invalid-after\") ] . \"\\n\ - \" . \\\r\ - \n [ \$FormatLine \" time left\" [ \$IfThenElse ((\$CertVal->\"exp\ - ired\") = true) \"expired\" [ \$FormatExpire (\$CertVal->\"expires-after\"\ - ) ] ] ]);\r\ - \n }\r\ - \n\r\ - \n :if ([ \$ScriptLock \$ScriptName ] = false) do={\r\ - \n :set ExitOK true;\r\ - \n :error false;\r\ - \n }\r\ - \n# \$WaitFullyConnected;\r\ - \n\r\ - \n :foreach Cert in=[ /certificate/find where !revoked !ca !scep-url expi\ - res-after<\$CertRenewTime ] do={\r\ - \n :local CertVal [ /certificate/get \$Cert ];\r\ - \n :local LastName;\r\ - \n :local FetchName;\r\ - \n\r\ - \n :do {\r\ - \n :if ([ :len \$CertRenewUrl ] = 0) do={\r\ - \n \$LogPrint info \$ScriptName (\"No CertRenewUrl given.\");\r\ - \n :error false;\r\ - \n }\r\ - \n \$LogPrint info \$ScriptName (\"Attempting to renew certificate '\ - \" . (\$CertVal->\"name\") . \"'.\");\r\ - \n\r\ - \n :local ImportSuccess false;\r\ - \n :if ([ :len (\$CertVal->\"common-name\") ] > 0) do={\r\ - \n :set LastName (\$CertVal->\"common-name\");\r\ - \n :set FetchName \$LastName;\r\ - \n :set ImportSuccess [ \$CheckCertificatesDownloadImport \$ScriptN\ - ame \$LastName \$FetchName ];\r\ - \n }\r\ - \n :foreach SAN in=(\$CertVal->\"subject-alt-name\") do={\r\ - \n :if (\$ImportSuccess = false) do={\r\ - \n :set LastName [ :pick \$SAN ([ :find \$SAN \":\" ] + 1) [ :len\ - \_\$SAN ] ];\r\ - \n :set FetchName \$LastName;\r\ - \n :set ImportSuccess [ \$CheckCertificatesDownloadImport \$Scrip\ - tName \$LastName \$FetchName ];\r\ - \n :if (\$ImportSuccess = false && [ :pick \$LastName 0 2 ] = \"*\ - .\") do={\r\ - \n :set FetchName (\"star.\" . [ :pick \$LastName 2 [ :len \$La\ - stName ] ]);\r\ - \n :set ImportSuccess [ \$CheckCertificatesDownloadImport \$Scr\ - iptName \$LastName \$FetchName ];\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n :if (\$ImportSuccess = false) do={ :error false; }\r\ - \n\r\ - \n :if ([ :len (\$CertVal->\"fingerprint\") ] > 0 && \$CertVal->\"fin\ - gerprint\" != [ /certificate/get \$Cert fingerprint ]) do={\r\ - \n \$LogPrint debug \$ScriptName (\"Certificate '\" . \$CertVal->\"\ - name\" . \"' was updated in place.\");\r\ - \n :set CertVal [ /certificate/get \$Cert ];\r\ - \n } else={\r\ - \n \$LogPrint debug \$ScriptName (\"Certificate '\" . \$CertVal->\"\ - name\" . \"' was not updated, but replaced.\");\r\ - \n\r\ - \n :local CertNew [ /certificate/find where name~(\"^\" . [ \$Escap\ - eForRegEx [ \$UrlEncode \$FetchName ] ] . \"\\\\.(p12|pem)_[0-9]+\\\$\") \ - \\\r\ - \n (common-name=(\$CertVal->\"common-name\") or subject-alt-name~\ - (\"(^|\\\\W)(DNS|IP):\" . [ \$EscapeForRegEx \$LastName ] . \"(\\\\W|\\\$)\ - \")) \\\r\ - \n fingerprint!=[ :tostr (\$CertVal->\"fingerprint\") ] ];\r\ - \n :local CertNewVal [ /certificate/get \$CertNew ];\r\ - \n\r\ - \n :if ((\$CertVal->\"expires-after\") > (\$CertNewVal->\"expires-a\ - fter\")) do={\r\ - \n /certificate/remove \$CertNew;\r\ - \n \$LogPrint warning \$ScriptName (\"Old certificate is newer th\ - an the new one. Aborting renew.\");\r\ - \n :error false;\r\ - \n }\r\ - \n\r\ - \n :if ((\$CertVal->\"private-key\") = true && (\$CertVal->\"privat\ - e-key\") != (\$CertNewVal->\"private-key\")) do={\r\ - \n /certificate/remove \$CertNew;\r\ - \n \$LogPrint warning \$ScriptName (\"Old certificate '\" . (\$Ce\ - rtVal->\"name\") . \"' has a private key, new certificate does not. Aborti\ - ng renew.\");\r\ - \n :error false;\r\ - \n }\r\ - \n\r\ - \n :if ([ \$CertificateAvailable ([ \$ParseKeyValueStore (\$CertNew\ - Val->\"issuer\") ]->\"CN\") \"fetch\" ] = false) do={\r\ - \n \$LogPrint warning \$ScriptName (\"The certificate chain is no\ - t available!\");\r\ - \n }\r\ - \n\r\ - \n /ip/service/set certificate=(\$CertNewVal->\"name\") [ find wher\ - e certificate=(\$CertVal->\"name\") ];\r\ - \n\r\ - \n /ip/ipsec/identity/set certificate=(\$CertNewVal->\"name\") [ fi\ - nd where certificate=(\$CertVal->\"name\") ];\r\ - \n /ip/ipsec/identity/set remote-certificate=(\$CertNewVal->\"name\ - \") [ find where remote-certificate=(\$CertVal->\"name\") ];\r\ - \n\r\ - \n /ip/hotspot/profile/set ssl-certificate=(\$CertNewVal->\"name\")\ - \_[ find where ssl-certificate=(\$CertVal->\"name\") ];\r\ - \n\r\ - \n /certificate/remove \$Cert;\r\ - \n /certificate/set \$CertNew name=(\$CertVal->\"name\");\r\ - \n :set Cert \$CertNew;\r\ - \n :set CertVal [ /certificate/get \$CertNew ];\r\ - \n }\r\ - \n\r\ - \n \$SendNotification2 ({ origin=\$ScriptName; silent=true; \\\r\ - \n subject=([ \$SymbolForNotification \"lock-with-ink-pen\" ] . \"C\ - ertificate renewed: \" . (\$CertVal->\"name\")); \\\r\ - \n message=(\"A certificate on \" . \$Identity . \" has been renewe\ - d.\\n\\n\" . [ \$FormatInfo \$Cert ]) });\r\ - \n \$LogPrint info \$ScriptName (\"The certificate '\" . (\$CertVal->\ - \"name\") . \"' has been renewed.\");\r\ - \n } on-error={\r\ - \n \$LogPrint debug \$ScriptName (\"Could not renew certificate '\" .\ - \_(\$CertVal->\"name\") . \"'.\");\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :foreach Cert in=[ /certificate/find where !revoked !scep-url !(expire\ - s-after=[]) \\\r\ - \n expires-after<\$CertWarnTime !(fingerprint=[]) ] do\ + \n:if ([ :len [ /system/scheduler/find where name=\$ScriptName ] ] = 0) do\ ={\r\ - \n :local CertVal [ /certificate/get \$Cert ];\r\ - \n\r\ - \n :if ([ :len [ /certificate/scep-server/find where ca-cert=(\$CertVal\ - ->\"ca\") ] ] > 0) do={\r\ - \n \$LogPrint debug \$ScriptName (\"Certificate '\" . (\$CertVal->\"n\ - ame\") . \"' is handled by SCEP, skipping.\");\r\ - \n } else={\r\ - \n :local State [ \$IfThenElse ((\$CertVal->\"expired\") = true) \"ex\ - pired\" \"is about to expire\" ];\r\ - \n\r\ - \n \$SendNotification2 ({ origin=\$ScriptName; \\\r\ - \n subject=([ \$SymbolForNotification \"lock-with-ink-pen,warning-s\ - ign\" ] . \"Certificate warning: \" . (\$CertVal->\"name\")); \\\r\ - \n message=(\"A certificate on \" . \$Identity . \" \" . \$State . \ - \".\\n\\n\" . [ \$FormatInfo \$Cert ]) });\r\ - \n \$LogPrint info \$ScriptName (\"The certificate '\" . (\$CertVal->\ - \"name\") . \"' \" . \$State . \\\r\ - \n \", it is invalid after \" . (\$CertVal->\"invalid-after\") . \ - \".\");\r\ - \n }\r\ - \n }\r\ - \n} do={\r\ - \n :global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err;\r\ - \n}\r\ + \n :log error (\$ScriptName . \"System Scheduler for script: \" . \$Scri\ + ptName . \" is NOT SET! Fix It Now!\");\r\ + \n /system/scheduler/add name=\$ScriptName on-event=\"/system/script { \ + run \$ScriptName; }\" comment=\"Update RKN DNS Looup\" interval=00:30:00 p\ + olicy=\"ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon\"\ + \_start-time=startup;\r\ + \n }\r\ + \n:set dnsLookupReady true;\r\ + \ndelay 2s; \r\ + \n:global dnsLookupReady (a);\r\ \n" -add comment="Global Config Script" dont-require-permissions=no name=\ - AM-GlobalConfig owner=vados policy=\ +add dont-require-permissions=no name="renameLists " owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local oldName \"Test\";\ + \n:local newName \"Test-IP\";\ + \n/ip firewall address-list\ + \n:foreach i in=[find list=\$oldName] do={\ + \nset \$i list=\$newName;\ + \n}\ + \n" +add dont-require-permissions=no name=IPv6-Settings owner=vados policy=\ ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - !rsc by Vados\ - \n# RouterOS script: AM-GlobalConfig\ - \n# Script comment: Global Config Script\ - \n# Copyright (c) 2007-2026 Vados \ - \n#\ - \n#\ - \n# Warning: Dont touch this line!\ - \n:global GlobalConfReady false;\ - \n#\ - \n#\ - \n# Global Url For Amster scripts to fetch\ - \n# most be defined in AM-Init-Script or AM-setup scripts\ - \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\ - \n:global ScriptsUrlSuffix \"\";\ - \n:global CheckSumsVerify true;\ - \n\ - \n:global ScriptUpdatesCRLF true;\ - \n:global CommentsInScripts true;\ - \n\ - \n# Debug output:\ - \n:global PrintDebug true; #false;\ - \n\ - \n# Debug output for specific script:\ - \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\ + #############Script Settings##################\ \n\ - \n# Debug logs\ - \n# Other actions (disk, email, remote or support) can be used as well.\ - \n# I do not recommend using echo - use debug output instead (https://rsc.\ - eworm.de/main/DEBUG.html#debug-output).\ - \n#/system/logging/add topics=script,debug action=memory;\ - \n\ - \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\ - \n:global Domain \"WORKGROUP\";\ - \n\ - \n:global EmailGeneralTo \"vados@vados.ru\";\ - \n#:global EmailGeneralCc \"\";\ - \n\ - \n# \$ScriptInstallUpdate mod/notification-telegram\ - \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ - \";\ - \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\ - \n# Use this to send notifications to a specific topic in group.\ - \n#:global TelegramThreadId \"30\";\ - \n# Using telegram-chat you have to define trusted chat ids (not group ids\ - !)\ - \n# or user names. Groups allow to chat with devices simultaneously.\ - \n:global TelegramChatIdsTrusted {\ - \n \"454403445\"\ - \n \"-1003631309063\"\ - \n \"-5124482807\"\ - \n \"1087968824\";\ - \n};\ - \n# \"-5294757340\";\ - \n\ - \n:global TelegramChatGroups \"(all)\";\ - \n#:global TelegramChatGroups \"(all|home|office)\";\ + \n:local \"IF-TUN\" \"6to4-tun\"\ + \n:local \"IF-LOC\" \"Bridge-LAN\"\ + \n:local \"POOL-6TO4\" \"poolV6-local\"\ + \n:local \"force-update\" false\ + \n############ use then static ip #######################\ + \n:local \"lease-address\" [/ip address get [find interface=\$\"IF-LOC\"] \ + address]\ + \n#:local \"interface\" \"ext\"\ + \n:local bound 0\ \n\ - \n:global NotificationFunctions {\ - \n \"email\"\ - \n \"telegram\";\ - \n};\ - \n# Toggle this to disable symbols in notifications.\ - \n:global NotificationsWithSymbols true;\ - \n:global TerminalColorOutput true;\ + \n###############################################\ \n\ - \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\ - \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\ - \n\ - \n## Update channel. Possible values: stable, long-term, testing, developm\ - ent\ - \n:global updateChannel \"stable\";\ - \n\ - \n:global CertRenewUrl (\$GlobalScriptsUrl . \"certs/\");\ - \n:global CertRenewTime 2w;\ - \n:global CertRenewPass {\ - \n \"\";\ - \n# \"v3ry-s3cr3t\";\ - \n# \"4n0th3r-s3cr3t\";\ - \n};\ - \n:global CertWarnTime 1w;\ - \n:global CertIssuedExportPass {\ - \n \"\";\ - \n# \"cert1-cn\"=\"v3ry-s3cr3t\";\ - \n# \"cert2-cn\"=\"4n0th3r-s3cr3t\";\ - \n};\ - \n\ - \n# Script BackupAndUpdate mode, possible values: backup,\ - \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ - n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \ - \n# osupdate - Update if available and creates backups before/after update\ - \_(ignores `forceBackup`)\ - \n# Set `forceBackup` to true to always create backups, even\ - \_without updates\ - \n# osnotify - Set `forceBackup` to always create backups on every run\ - \n:global DevInfoIncludeIP true;\ - \n:global BackupAndUpdateMode \"osnotify\"\ - \n\ - \n:global forceBackup true;\ - \n:global BackupPassword \"Peskar55\";\ - \n\ - \n# SFTP Backup Variables\ - \n:global BackupRandomDelay 0;\ - \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\ - \n:global BackupUploadUser \$Identity;\ - \n:global BackupUploadPass \"root.mnuc.backuper\";\ - \n\ - \n:global BackupSendBinary true;\ - \n:global BackupSendExport true;\ - \n:global BackupSendGlobalConfig true;\ - \n:global BackupSendScripts true;\ - \n\ - \n# Remove local file after uploading if no errors\ - \n:global BackupRmLocal true;\ - \n\ - \n# Local Backups Root Directory \ - \n:global BackupLocalRoot \"tmpfs\";\ - \n\ - \n# Encrypt Backup\ - \n:global BackupEncrypt true;\ - \n\ - \n# Sensitive information in Backups\ - \n:global BackupSens true;\ - \n\ - \n# User Export\ - \n:global BackupUser true;\ - \n\ - \n# License Export (not for CHR, will silently skip)\ - \n:global BackupLicense false;\ - \n\ - \n# SSH Keys\ - \n:global BackupSshKeys true;\ - \n\ - \n# Certificate Export\ - \n:global BackupCerts true;\ + \n:local 6to4prefix do={\ + \n :global dec2hex\ + \n :local ipv4 \$1\ + \n :local ipv6 \"2002:\"\ + \n :for i from=0 to=2 step=1 do={ \ + \n :if ( \$i = 2) do={\ + \n :set ipv6 (\$ipv6.\":\")\ + \n }\ + \n :local fp [:find \$ipv4 \".\"]\ + \n :if ( \$fp > 0 ) do={\ + \n :set ipv6 (\$ipv6.[\$dec2hex [:pick \$ipv4 0 \$fp]])\ + \n :set ipv4 [:pick \$ipv4 (\$fp + 1 ) [:len \$ipv4]]\ + \n }\ + \n }\ + \n :return (\$ipv6.[\$dec2hex \$ipv4])\ + \n}\ + \n:local \"str_replace\" do={\ + \n :local \"str-pos\" [:find \$1 \$2]\ + \n :local \"str-len\" [:len \$2]\ + \n :local str \"\"\ + \n :local rest \$1\ + \n :while (\$\"str-pos\" >= 0) do={\ + \n :local t [:pick \$rest 0 \$\"str-pos\"]\ + \n :if ( \$4 > 0 ) do={\ + \n :for i from=1 to=(\$4 - [:len \$t]) step=1 do={\ + \n :set str (\$str.\$5)\ + \n }\ + \n }\ + \n :set str (\$str.\$t.\$3)\ + \n :set rest [:pick \$rest (\$\"str-pos\"+\$\"str-len\") [:len \$re\ + st]]\ + \n :set \"str-pos\" [:find \$rest \$2]\ + \n }\ + \n :return (\$str.\$rest)\ + \n}\ \n\ - \n# Certificate Password\ - \n:global BackupCertsPasswd \"\";\ + \n:if (\$bound=1) do={\ + \n :local t [:find \$\"lease-address\" \"/\"]\ \n\ - \n# User-Manager Export\ - \n:global BackupUserMan false;\ + \n :if ( \$t >= 0 ) do={\ + \n :set \"lease-address\" [:pick \$\"lease-address\" 0 \$t]\ + \n }\ \n\ - \n# The Dude Export\ - \n:global BackupDude false;\ + \n :if ( [/interface 6to4 print count-only where name=\$\"IF-TUN\"] = 0\ + ) do={\ + \n /interface 6to4 add !keepalive local-address=\$\"lease-address\"\ + \_mtu=1280 name=\$\"IF-TUN\" remote-address=10.30.30.0\ + \n :set \"force-update\" true\ + \n }\ \n\ - \n# User Files to export, comma-separated string or array of strings\ - \n# User Files are not removed on backup\ - \n# Any directory paths will be removed (/ -> _) on remote file\ - \n# Nonpresent files are silently skipped\ - \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\ + \n :local \"IPv4-TUN\" [/interface 6to4 get [find name=\$\"IF-TUN\"] lo\ + cal-address];\ \n\ - \n# load functions and any custom scripts\ - \n# [ /system/script/find where name=\"global-config-ov\ - erlay\" ], \\\ - \n# [ /system/script/find where name~\"^global-config-o\ - verlay\\\\.d/.\" ]\ - \n#\ - \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ - ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ - \n# :onerror Err {\ - \n# /system/script/run \$Script;\ - \n# } do={\ - \n# :log error (\"Loading configuration from configs and functions\"\ - \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\ - \n# }\ - \n#}\ - \n#:log info \"\\ndevMode = \$devMode\";\ - \n#:log info \"\\ndevRunning = \$devRunning\";\ - \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ - GlobalRUN\\r\?\\n\" ] do={\ - \n :onerror Err {\ - \n /system/script/run \$Script;\ - \n } do={\ - \n :log error (\"Run script \" . [ /system/script/get \$Script name \ - ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\ - \n }\ + \n :if ( \$\"lease-address\" != \$\"IPv4-TUN\" || \$\"force-update\" = \ + true) do={\ + \n /interface 6to4 set [find name=\$\"IF-TUN\"] local-address=\$\"l\ + ease-address\"\ + \n /ipv6 address remove [find interface=\$\"IF-TUN\"]\ + \n /ipv6 address remove [find interface=\$\"IF-LOC\"]\ + \n /ipv6 route remove [find gateway ~ \$\"IF-TUN\" and dst-address=\ + \"::/0\"]\ + \n :local \"pool-prefix\" [\$6to4prefix \$\"lease-address\"]\ + \n :if ( [/ipv6 pool print count-only where name=\$\"POOL-6TO4\"] =\ + \_0) do={ \ + \n /ipv6 pool add name=\$\"POOL-6TO4\" prefix=(\$\"pool-prefix\ + \".\":1::/64\") prefix-length=64\ + \n } else={\ + \n /ipv6 pool set [/ipv6 pool find where name=\$\"POOL-6TO4\"] \ + prefix=(\$\"pool-prefix\".\":1::/64\")\ + \n }\ + \n /ipv6 address add address=(\$\"pool-prefix\".\"::\".[\$MAC2EUI64\ + \_[/interface get [find name=\$\"interface\"] mac-address]].\"/3\") interf\ + ace=\$\"IF-TUN\" advertise=no\ + \n /ipv6 address add eui-64=yes from-pool=\$\"POOL-6TO4\" interface\ + =\$\"IF-LOC\" advertise=yes\ + \n /ipv6 route add dst-address=::/0 gateway=(\"::10.30.30.81%\".\$\ + \"IF-TUN\")\ + \n :local t [/ipv6 address get [find interface=\$\"IF-LOC\"] addres\ + s]\ + \n :set t [:pick \$t 0 [:find \$t \"/\"]]\ + \n :if ( [/ipv6 dhcp-server option print count-only where name=DNS]\ + \_= 0) do={\ + \n /ipv6 dhcp-server option add code=23 name=DNS value=(\"0x\".\ + [\$\"str_replace\" \$t \":\" \"\" 4 \"0\"])\ + \n } else={\ + \n /ipv6 dhcp-server option set [/ipv6 dhcp-server option find \ + where name=DNS] value=(\"0x\".[\$\"str_replace\" \$t \":\" \"\" 4 \"0\"])\ + \n }\ + \n :if ( [/ipv6 dhcp-server print count-only where interface=\$\"IF\ + -LOC\"] = 0) do={\ + \n /ipv6 dhcp-server add address-pool=\$\"POOL-6TO4\" dhcp-opti\ + on=DNS interface=\$\"IF-LOC\" lease-time=1d name=\$\"IF-LOC\"\ + \n }\ + \n :if ( [ipv6 nd print count-only where interface=\$\"IF-LOC\"] = \ + 0) do={\ + \n /ipv6 nd add advertise-dns=no interface=\$\"IF-LOC\" other-c\ + onfiguration=yes\ + \n }\ + \n }\ + \n}" +add dont-require-permissions=no name=IPv6-GlobalFunc owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + global MAC2EUI64 do={\ + \n :local EUI64 \"\"\ + \n :local MAC \$1\ + \n :local HEX2DEC \"0123456789ABCDEF\"\ + \n :for i from=0 to=5 step=1 do={\ + \n :if ( \$i = 0 ) do={\ + \n :set EUI64 [:pick \$MAC 0]\ + \n :set EUI64 (\$EUI64.[:tostr [:pick \$\"HEX2DEC\" ([:find \$\ + \"HEX2DEC\" [:pick \$MAC 1]] ^ 2)]])\ + \n }\ + \n :if ( \$i = 1 || \$i = 3) do={\ + \n :set EUI64 (\$EUI64.\":\")\ + \n }\ + \n :if ( \$i = 2 ) do={\ + \n :set EUI64 (\$EUI64.\"FF:FE\")\ + \n }\ + \n :if ( [:find \$MAC \":\"] = 2 ) do={\ + \n :set MAC [:pick \$MAC 3 [:len \$MAC]]\ + \n :set EUI64 (\$EUI64.[:pick \$MAC 0 2])\ + \n }\ + \n }\ + \n :return (\$EUI64)\ \n}\ \n\ - \n# signal we are ready\ - \n:set GlobalConfReady true;\ - \n:while (\$GlobalConfReady != true) do={:delay 500ms};\ - \n" -add comment="Renew locally issued certificates" dont-require-permissions=no \ - name=AM-CertsRenew owner=AM-CertsRenew policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - !rsc by Vados\r\ - \n# RouterOS script: AM-CertsRenew\r\ - \n# Script comment: Renew locally issued certificates\r\ - \n# Copyright (c) 2005-2026 Vados \r\ - \n#\r\ - \n#\r\ - \n# requires RouterOS, version=7.19\r\ - \n#\r\ - \n:local ExitOK false;\r\ - \n:onerror Err {\r\ - \n :global GlobalConfReady; :global GlobalFuncReady;\r\ - \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ - \\\r\ - \n do={ :error (\"Global config and/or functions not ready.\"); }; } \ - delay=500ms max=50;\r\ - \n :local ScriptName [ :jobname ];\r\ - \n\r\ - \n :global CertIssuedExportPass;\r\ - \n\r\ - \n :global LogPrint;\r\ - \n :global MkDir;\r\ - \n :global ScriptLock;\r\ - \n\r\ - \n# Add this Script scheduler\r\ - \n:if ([ :len [ /system/scheduler/find where name=\$ScriptName ] ] = 0) do\ - ={\r\ - \n:log warning (\"System Scheduler for script: \" . \$ScriptName . \" is N\ - OT SET! Fix It Now!\");\r\ - \n:local OnEvent \"/system/script/run \$ScriptName;\";\r\ - \n:local Comment \"Every Day Check For Update Local Issued Certificates.\"\ - ;\r\ - \n#/system/scheduler/add name=\$ScriptName comment=\$Comment start-time=st\ - artup interval=1d on-event=\$OnEvent;\r\ - \n}\r\ - \n\r\ - \n :if ([ \$ScriptLock \$ScriptName ] = false) do={\r\ - \n :set ExitOK true;\r\ - \n :error false;\r\ - \n }\r\ - \n\r\ - \n :foreach Cert in=[ /certificate/find where issued expires-after<3w ] d\ - o={\r\ - \n :local CertVal [ /certificate/get \$Cert ];\r\ - \n /certificate/issued-revoke \$Cert;\r\ - \n /certificate/set name=(\$CertVal->\"name\" . \"-revoked-\" . [ /syst\ - em/clock/get date ]) \$Cert;\r\ - \n /certificate/add name=(\$CertVal->\"name\") common-name=(\$CertVal->\ - \"common-name\") \\\r\ - \n key-usage=(\$CertVal->\"key-usage\") subject-alt-name=(\$CertVal\ - ->\"subject-alt-name\");\r\ - \n /certificate/sign (\$CertVal->\"name\") ca=(\$CertVal->\"ca\");\r\ - \n :if ([ :typeof (\$CertIssuedExportPass->(\$CertVal->\"common-name\")\ - ) ] = \"str\") do={\r\ - \n :if ([ \$MkDir \"cert-issued\" ] = true) do={\r\ - \n /certificate/export-certificate (\$CertVal->\"name\") type=pkcs1\ - 2 \\\r\ - \n file-name=(\"cert-issued/\" . \$CertVal->\"common-name\") \\\ - \r\ - \n export-passphrase=(\$CertIssuedExportPass->(\$CertVal->\"com\ - mon-name\"));\r\ - \n \$LogPrint info \$ScriptName (\"Issued a new certificate for '\"\ - \_. \$CertVal->\"common-name\" . \\\r\ - \n \"', exported to 'cert-issued/\" . \$CertVal->\"common-name\" \ - . \".p12'.\");\r\ - \n } else={\r\ - \n \$LogPrint warning \$ScriptName (\"Failed creating directory, no\ - t exporting certificate.\");\r\ - \n }\r\ - \n } else={\r\ - \n \$LogPrint info \$ScriptName (\"Issued a new certificate for '\" .\ - \_\$CertVal->\"common-name\" . \"'.\");\r\ - \n }\r\ - \n }\r\ - \n} do={\r\ - \n :global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err;\r\ - \n}\r\ - \n" -add comment="Update and Backup send notification to EMail" \ - dont-require-permissions=no name=AM-Backup-UpdateEmail owner=\ - AM-Backup-UpdateEmail policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ - !rsc by Vados\r\ - \n# RouterOS script: AM-Backup-UpdateEmail\r\ - \n# Script comment: Update and Backup send notification to EMail\r\ - \n# Copyright (c) 2007-2026 Vados \r\ - \n#\r\ - \n#\r\ - \n# requires RouterOS, version>=6.43.7\r\ - \n# requires device-mode, fetch\r\ - \n#\r\ - \n# Updated: 15/04/2025\r\ - \n# Website: https://github.com/beeyev\r\ - \n# Notification e-mail (Make sure you have configured Email settings in T\ - ools -> Email)\r\ - \n:local ExitOK false;\r\ - \n:onerror Err {\r\ - \n :global GlobalConfReady; :global GlobalFuncReady;\r\ - \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ - \\\r\ - \n do={ :error (\"Global config and/or functions not ready.\"); }; } \ - delay=500ms max=50;\r\ - \n :local ScriptName [ :jobname ];\r\ - \n\r\ - \n:local IfThenElse do={:if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] \ - = true) do={:return \$2}; :return \$3;}\r\ - \n:local EitherOr do={\r\ - \n :if ([ :typeof \$1 ] = \"num\") do={:if ((\$1 != 0) = true) do={:retur\ - n \$1} else={:return \$2};}\r\ - \n :if ([ :typeof \$1 ] = \"time\") do={:if ((\$1 > 0s) = true) do={:retu\ - rn \$1} else={:return \$2};}\r\ - \n :if ([ :len [ :tostr \$1 ] ] > 0) do={:return \$1} else={:return \$2};\ - \r\ - \n}\r\ - \n:local ExitError do={\r\ - \n :local ExitOK [ :tostr \$1 ];\r\ - \n :local Name [ :tostr \$2 ];\r\ - \n :local Error [ :tostr \$3 ];\r\ - \n :if (\$ExitOK = \"false\") do={:log error (\$Name [ \$IfThenElse ([ :p\ - ick \$Name 0 1 ] = \"\\\$\") \\\r\ - \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ - ror\" . \\\r\ - \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ - \$Error) \".\" ]);}\r\ - \n}\r\ - \n\r\ - \n:global LogPrint;\r\ - \n:global EditSchedulers;\r\ - \n:global DevInfoIncludeIP;\r\ - \n\r\ - \n:local SchedInterval \"7d\";\r\ - \n:local SchedStartTime \"03:41:27\";\r\ - \n:local SchedComment \"Every 7 Day Check For Update and Backup send notif\ - ication to EMail.\";\r\ - \n\r\ - \n# Function to add or edit schedulers for scripts, to ensure they are set\ - \_up correctly\r\ - \n# How to use:\r\ - \n# Call this function with the following parameters:\r\ - \n# 1. \$1 - Scheduler name (usually same as script name) [*]\r\ - \n# 2. \$2 - Interval (e.g. \"1d\" (default is \"1d\")) [**]\r\ - \n# 3. \$3 - Start Time (e.g. \"00:00:00\", default is current time) [**]\ - \r\ - \n# 4. \$4 - Comment (optional, default: \"Scheduler for script: \")\ - \_[**]\r\ - \n# 5. \$5 - On Event command (e.g. \"/system/script { run ; }\" (de\ - fault is \"/system/script { run \$SchedName; }\")) [**]\r\ - \n# 6. \$6 - Policy (e.g. \"ftp,reboot,read,write,policy,test,password,sni\ - ff,sensitive,romon\" (default is the same)) [**]\r\ - \n# 7. \$7 - Start Date (e.g. \"jan/01/1970\", default is current date) [*\ - *]\r\ - \n# Notes:\r\ - \n# * - Scheduler name is required, and is used to identify the scheduler\ - \_to create or edit. It is usually the same as the script name (\$ScriptNa\ - me).\r\ - \n# ** - If optional parameters are not provided, default values will be u\ - sed.\r\ - \n# This allows for quick setup with minimal parameters, while still \ - providing flexibility for customization.\r\ - \n# Example usage:\r\ - \n# :if ([ \$EditSchedulers \"my-script\" ] = false) do={:set ExitOK false\ - ; :error true;}\r\ - \n# :if ([ \$EditSchedulers \"my-script\" \"1d\" \"03:41:27\" \"My custom \ - scheduler comment\" false false \"jan/01/1970\" ] = false) do={:set ExitOK\ - \_false; :error true;}\r\ - \n\r\ - \n:set EditSchedulers do={\r\ - \n :local SchedName [ :tostr \$1 ];\r\ - \n :if ([ :len \$SchedName ] = 0) do={ :return false; }\r\ - \n :local Interval [ :tostr \$2 ];\r\ - \n :if ([ :len \$Interval ] = 0) do={ :set Interval \"1d\"; }\r\ - \n :local StartTime [ :tostr \$3 ];\r\ - \n :if ([ :len \$StartTime ] = 0) do={ :set StartTime [/system/clock/get \ - time]; }\r\ - \n :local Comment [ :tostr \$4 ];\r\ - \n :if ([ :len \$Comment ] = 0) do={ :set Comment \"Scheduler for script:\ - \_\$SchedName\"; }\r\ - \n :local OnEvent [ :tostr \$5 ];\r\ - \n :if ([ :len \$OnEvent ] = 0) do={ :set OnEvent \"/system/script { run \ - \$SchedName; }\"; }\r\ - \n :local Policy [ :tostr \$6 ];\r\ - \n :if ([ :len \$Policy ] = 0) do={ :set Policy \"ftp,reboot,read,write,p\ - olicy,test,password,sniff,sensitive,romon\"; }\r\ - \n :local StartDate [ :tostr \$7 ];\r\ - \n :if ([ :len \$StartDate ] = 0) do={ :set StartDate [/system/clock/get \ - date]; }\r\ - \n\r\ - \n :onerror Err {\r\ - \n # Check if scheduler exists, if not - create it\r\ - \n :if ([ :len [ /system/scheduler/find where name=\$SchedName ] ] = 0)\ - \_do={\r\ - \n :log warning (\$SchedName . \"System Scheduler for script: \" . \$\ - SchedName . \" is NOT SET! Fix It Now!\");\r\ - \n /system/scheduler/add comment=\$Comment interval=\$Interval name=\ - \$SchedName on-event=\$OnEvent policy=\$Policy start-date=\$StartDate star\ - t-time=\$StartTime;\r\ - \n }\r\ - \n # Check if scheduler parameters are correct, if not - fix them\r\ - \n :if ([ /system/scheduler/get \$SchedName comment ] != \$Comment) do=\ - {\r\ - \n /system/scheduler/set \$SchedName comment=\$Comment;\r\ - \n }\r\ - \n :if ([ /system/scheduler/get \$SchedName interval ] != \$Interval) d\ - o={\r\ - \n /system/scheduler/set \$SchedName interval=\$Interval;\r\ - \n }\r\ - \n :if ([ /system/scheduler/get \$SchedName on-event ] != \$OnEvent) do\ - ={\r\ - \n /system/scheduler/set \$SchedName on-event=\$OnEvent;\r\ - \n }\r\ - \n :if ([ /system/scheduler/get \$SchedName policy ] != \$Policy) do={\ - \r\ - \n /system/scheduler/set \$SchedName policy=\$Policy;\r\ - \n }\r\ - \n :if ([ /system/scheduler/get \$SchedName start-date ] != \$StartDate\ - ) do={\r\ - \n /system/scheduler/set \$SchedName start-date=\$StartDate;\r\ - \n }\r\ - \n :if ([ /system/scheduler/get \$SchedName start-time ] != \$StartTime\ - ) do={\r\ - \n /system/scheduler/set \$SchedName start-time=\$StartTime;\r\ - \n }\r\ - \n } do={:log error (\$SchedName . \"Failed to add/modify scheduler for '\ - \" . \$SchedName . \"' failed: \" . \$Err); :return false};\r\ - \n :return true;\r\ - \n}\r\ - \n\r\ - \n:if ([ \$EditSchedulers \$ScriptName \$SchedInterval \$SchedStartTime \$\ - SchedComment ] = false) do={\r\ - \n :log error (\$ScriptName . \"Failed to add/modify scheduler for \" . \ - \$ScriptName . \"!\");\r\ - \n :set ExitOK true;\r\ - \n :error true;\r\ - \n}\r\ - \n\r\ - \n# Local Function CheckOSUpdateMode\r\ - \n:local CheckOSUpdateMode;\r\ - \n:set CheckOSUpdateMode do={\r\ - \n :local NewMode [ :tostr \$1 ];\r\ - \n :if ([ :len \$NewMode ] = 0) do={\r\ - \n :log error (\$0 . \"/nFunction /\$CheckOSUpdateMode received empty v\ - alue!\");\r\ - \n :return false;\r\ - \n :error true;\r\ - \n }\r\ - \n\r\ - \n :global BackupAndUpdateMode;\r\ - \n :global OldMode [ :tostr \$BackupAndUpdateMode ];\r\ - \n :if (\$NewMode != \$BackupAndUpdateMode && \$NewMode = \"updateOnce\")\ - \_do={\r\ - \n :set BackupAndUpdateMode [ :tostr \$NewMode ];\r\ - \n :log info (\$0 . \"/nOk. /\$BackupAndUpdateMode set to: '\" . \$NewM\ - ode . \"'.\\nYou're a good boy! ))\\nI'm launching the update in 5 seconds\ - .\");\r\ - \n :delay 5;\r\ - \n /system/script { run \$ScriptName; };\r\ - \n } else={\r\ - \n :log warning (\$0 . \"/nFunction /\$CheckOSUpdateMode received value: \ - '\" . \$NewMode . \"', but is may be only \\\"updateOnce\\\"!\");\r\ - \n :return false;\r\ - \n }\r\ - \n :return true;\r\ - \n :error false;\r\ - \n}\r\ - \n\r\ - \n# :if ([ :len [ /system/scheduler/find where name=\"running-from-backup\ - -partition\" ] ] > 0) do={\r\ - \n# \$LogPrint warning \$ScriptName (\"Running from backup partition, r\ - efusing to act.\");\r\ - \n# :set ExitOK true;\r\ - \n# :error false;\r\ - \n# }\r\ - \n\r\ - \n:global EmailGeneralTo;\r\ - \n:global BackupAndUpdateMode;\r\ - \n:global forceBackup;\r\ - \n:global BackupPassword;\r\ - \n:global BackupSens;\r\ - \n:global updateChannel;\r\ - \n\r\ - \n:global DevInfoIncludeIP;\r\ - \n\r\ - \n# Installs patch updates only (BackupAndUpdateMode = \"osupdate\").\r\ - \n# Works for `stable` and `long-term` channels.\r\ - \n# Updates only if MAJOR.MINOR match (e.g. 6.43.2 > 6.43.6 allowed, 6.44.\ - 1 skipped).\r\ - \n# Sends info if a newer (non-patch) version is found.\r\ - \n:local installOnlyPatchUpdates false;\r\ - \n:local scriptVersion \"26.04.30\";\r\ - \n:local copyrightUrl \"https://www.github.com/vados-dev/\";\r\ - \n#Script messages prefix\r\ - \n:local SMP \"BkpAndUpdate:\";\r\ - \n\r\ - \n:local exitErrorMessage \"\$SMP script stopped due to an error. Please c\ - heck logs for more details.\";\r\ - \n:log info \"\\n\\n\$SMP Script \\\"Mikrotik RouterOS automatic backup & \ - update\\\" v.\$scriptVersion started.\";\r\ - \n:log info \"\$SMP Script Mode: `\$BackupAndUpdateMode`, Update channel: \ - `\$updateChannel`, Force backup: `\$forceBackup`, Install only patch updat\ - es: `\$installOnlyPatchUpdates`\";\r\ - \n\r\ - \n## vv FUNCTIONS vv ##\r\ - \n:global WaitCheckUpdates; \$WaitCheckUpdates;\r\ - \n:global MiniDateTimeStamp;\r\ - \n:local MDTSFix [\$MiniDateTimeStamp];\r\ - \n:global Identity;\r\ - \n:global IdentityShort;\r\ - \n:global devBoardName;\r\ - \n:global runningVersion;\r\ - \n:global runningChannel;\r\ - \n:global devModel;\r\ - \n:global devRbSerialNumber;\r\ - \n:global ROsVerAvail;\r\ - \n:global PkgUpdStatus;\r\ - \n\r\ - \n# Checks if two RouterOS version strings differ only by the patch versio\ - n\r\ - \n# :put [\$FuncIsPatchUpdateOnly \"6.2.1\" \"6.2.4\"] # Output: true\r\ - \n# :put [\$FuncIsPatchUpdateOnly \"6.2.1\" \"6.3.1\"] # Output: false\r\ - \n:local FuncIsPatchUpdateOnly do={\r\ - \n :local ver1 \$1;\r\ - \n :local ver2 \$2;\r\ - \n # Extract the major and minor components from a version\r\ - \n :local extractMajorMinor do={\r\ - \n :local ver \$1;\r\ - \n :local dot1 [:find \$ver \".\"];\r\ - \n :if (\$dot1 = -1) do={:return \$ver}\r\ - \n :local major [:pick \$ver 0 \$dot1];\r\ - \n :local rest [:pick \$ver (\$dot1 + 1) [:len \$ver]];\r\ - \n :local dot2 [:find \$rest \".\"];\r\ - \n :local minor \$rest;\r\ - \n :if (\$dot2 >= 0) do={:set minor [:pick \$rest 0 \$dot2]}\r\ - \n :return (\$major . \".\" . \$minor);\r\ - \n }\r\ - \n\r\ - \n# Compare the major and minor components of both version strings\r\ - \n:if ([\$extractMajorMinor \$ver1] = [\$extractMajorMinor \$ver2]) do={:r\ - eturn true}\r\ - \n :return false;\r\ - \n}\r\ - \n# Creates backups and returns array of names\r\ - \n# Possible arguments:\r\ - \n# \$1 - file name, without extension\r\ - \n# \$2 - password (optional)\r\ - \n# \$3 - sensitive data in config (optional, default: false)\r\ - \n# Example:\r\ - \n#:put [\$FuncCreateBackups \$backupName]\r\ - \n:local FuncCreateBackups do={\r\ - \n :local backupName [ :tostr \$1 ];\r\ - \n :local BackPass \$2;\r\ - \n :local BackSens \$3;\r\ - \n\r\ - \n #Script messages prefix\r\ - \n :local SMP \"BkpAndUpdate:\";\r\ - \n :local exitErrorMessage \"\$SMP script stopped due to an error. Please\ - \_check logs for more details.\";\r\ - \n :log info (\"\$SMP global function `FuncCreateBackups` started, input:\ - \_`\$backupName`\");\r\ - \n\r\ - \n # validate required parameter: backupName\r\ - \n :if ([:typeof \$backupName] != \"str\" or [:len \$backupName] = 0) do=\ - {\r\ - \n :log error \"\$SMP parameter 'backupName' is required and must be a \ - non-empty string\";\r\ - \n# :log warning \"\$SMP parameter '\\\$backupName' is required and mus\ - t be a non-empty string.\\nI set '\\\$backupName' to 'default-backup'\";\r\ - \n# :set \$backupName \"default-backup\";\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n\r\ - \n :local backupFileSys \"\$backupName.backup\";\r\ - \n :local backupFileConfig \"\$backupName.rsc\";\r\ - \n :local backupNames {\$backupFileSys;\$backupFileConfig};\r\ - \n\r\ - \n ## Perform system backup\r\ - \n :if ([:len \$BackPass] = 0) do={\r\ - \n :log info (\"\$SMP starting backup without password, backup name: `\ - \$backupName`\");\r\ - \n /system backup save dont-encrypt=yes name=\$backupName;\r\ - \n } else={\r\ - \n :log info (\"\$SMP starting backup with password, backup name: `\$ba\ - ckupName`\");\r\ - \n /system backup save password=\$BackPass name=\$backupName;\r\ - \n }\r\ - \n :log info (\"\$SMP system backup created: `\$backupFileSys`\");\r\ - \n ## Export config file\r\ - \n :if (\$BackSens = true) do={\r\ - \n :log info (\"\$SMP starting export config with sensitive data, backu\ - p name: `\$backupName`\");\r\ - \n # Since RouterOS v7 it needs to be explicitly set that we want to ex\ - port sensitive data\r\ - \n :if ([:pick [/system resource get version] 0 1] < 7) do={\r\ - \n :execute \"/export compact terse file=\$backupName\";\r\ - \n } else={\r\ - \n :execute \"/export compact show-sensitive terse file=\$backupName\ - \";\r\ - \n }\r\ - \n } else={\r\ - \n :log info (\"\$SMP starting export config without sensitive data, ba\ - ckup name: `\$backupName`\");\r\ - \n /export compact hide-sensitive terse file=\$backupName;\r\ - \n }\r\ - \n :log info (\"\$SMP Config export complete: `\$backupFileConfig`\");\r\ - \n :log info (\"\$SMP Waiting a little to ensure backup files are written\ - \");\r\ - \n :delay 20;\r\ - \n :if ([:len [/file find name=\$backupFileSys]] > 0) do={\r\ - \n :log info (\"\$SMP system backup file successfully saved to the file\ - \_system: `\$backupFileSys`\");\r\ - \n } else={\r\ - \n :log error (\"\$SMP system backup was not created, file does not exi\ - st: `\$backupFileSys`\");\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n :if ([:len [/file find name=\$backupFileConfig]] > 0) do={\r\ - \n :log info (\"\$SMP config backup file successfully saved to the file\ - \_system: `\$backupFileConfig`\");\r\ - \n } else={\r\ - \n :log error (\"\$SMP config backup was not created, file does not exi\ - st: `\$backupFileConfig`\");\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n :log info (\"\$SMP global function `FuncCreateBackups` finished. Creat\ - ed backups, system: `\$backupFileSys`, config: `\$backupFileConfig`\")\r\ - \n :return \$backupNames;\r\ - \n}\r\ - \n# Sends an email\r\ - \n# Parameters:\r\ - \n# \$1 - to (email address)\r\ - \n# \$2 - subject\r\ - \n# \$3 - body\r\ - \n# \$4 - file attachments (optional; pass \"\" if not needed)\r\ - \n#\r\ - \n# Example:\r\ - \n# \$FuncSendEmailSafe \"admin@domain.com\" \"Backup Done\" \"Backup comp\ - lete.\" \"backup1.backup\"\r\ - \n:local FuncSendEmailSafe do={\r\ - \n :global EmailGeneralTo;\r\ - \n :local emailSubject \$2;\r\ - \n :local emailBody \$3;\r\ - \n :local emailAttachments \$4;\r\ - \n :local SMP \"Bkp&Upd:\";\r\ - \n :local exitErrorMessage \"\$SMP script stopped due to an error. Please\ - \_check logs for more details.\";\r\ - \n :log info \"\$SMP Attempting to send email to `\$EmailGeneralTo`\";\r\ - \n # SAFETY: wait for any previously queued email to finish\r\ - \n :local waitTimeoutPre 60;\r\ - \n :local waitCounterPre 0;\r\ - \n :while (([/tool e-mail get last-status] = \"resolving-dns\" or [/tool \ - e-mail get last-status] = \"in-progress\")) do={\r\ - \n :if (\$waitCounterPre >= \$waitTimeoutPre) do={\r\ - \n :log error \"\$SMP Email send aborted: previous send did not compl\ - ete after \$waitTimeoutPre seconds\";\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n :log info \"\$SMP Waiting for previous email to finish (status: \$[/\ - tool e-mail get last-status])...\";\r\ - \n :delay 1; \r\ - \n :set waitCounterPre (\$waitCounterPre + 1);\r\ - \n }\r\ - \n # Send the email\r\ - \n :do {\r\ - \n /tool e-mail send to=\$EmailGeneralTo subject=\$emailSubject body=\$\ - emailBody file=\$emailAttachments;\r\ - \n } on-error={\r\ - \n :log error \"\$SMP Email send command failed to execute. Check logs \ - and verify email settings.\";\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n # Wait for send status to change from \"in-progress\" / \"resolving-dn\ - s\"\r\ - \n :local waitTimeout 60;\r\ - \n :local waitCounter 0;\r\ - \n :local emailStatus \"\";\r\ - \n :log info \"\$SMP Waiting for email to be sent, timeout in `\$waitTime\ - out` seconds...\";\r\ - \n :while (\$waitCounter < \$waitTimeout) do={\r\ - \n :set emailStatus [/tool e-mail get last-status];\r\ - \n :if (\$emailStatus != \"in-progress\" and \$emailStatus != \"resolvi\ - ng-dns\") do={\r\ - \n :log info \"\$SMP Email send status received: \$emailStatus\";\r\ - \n # exit loop\r\ - \n :set waitCounter \$waitTimeout;\r\ - \n } else={:delay 1; :set waitCounter (\$waitCounter + 1)}\r\ - \n }\r\ - \n # Final decision based on last status\r\ - \n :if (\$emailStatus = \"succeeded\") do={\r\ - \n :log info \"\$SMP Email successfully sent to `\$EmailGeneralTo`\";\ - \r\ - \n } else={\r\ - \n :log error \"\$SMP Email failed to send. Status: `\$emailStatus`. Ch\ - eck logs for more details and verify email settings.\";\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n}\r\ - \n# Global variable to track current update step\r\ - \n# They need to be initialized here first to be available in the script\r\ - \n:global buGlobalVarTargetOsVersion;\r\ - \n:global buGlobalVarScriptStep;\r\ - \n:local scriptStep \$buGlobalVarScriptStep;\r\ - \n:do {\r\ - \n /system/script/environment remove buGlobalVarScriptStep;\r\ - \n} on-error={}\r\ - \n:if ([:len \$scriptStep] = 0) do={\r\ - \n :set scriptStep 1;\r\ - \n}\r\ - \n## ^^ FUNCTIONS ^^ ##\r\ - \n#\r\ - \n# Initial validation\r\ - \n## Check email settings\r\ - \n:if ([:len \$EmailGeneralTo] < 3) do={\r\ - \n :log error (\"\$SMP Parameter `\\\$EmailGeneralTo` is not set, or cont\ - ains invalid value. Script stopped.\");\r\ - \n :error \$exitErrorMessage;\r\ - \n}\r\ - \n# Values will be defined later in the script\r\ - \n:local emailServer \"\";\r\ - \n:local emailFromAddress [/tool e-mail get from];\r\ - \n:log info \"\$SMP Validating email settings...\";\r\ - \n:do {\r\ - \n :set emailServer [/tool e-mail get server];\r\ - \n} on-error={\r\ - \n # This is a workaround for the RouterOS v7.12 and older versions\r\ - \n :set emailServer [/tool e-mail get address];\r\ - \n}\r\ - \n:if (\$emailServer = \"0.0.0.0\") do={\r\ - \n :log error (\"\$SMP Email server address is not correct: `\$emailServe\ - r`, check `Tools -> Email`. Script stopped.\");\r\ - \n :error \$exitErrorMessage;\r\ - \n}\r\ - \n:if ([:len \$emailFromAddress] < 3) do={\r\ - \n :log error (\"\$SMP Email configuration FROM address is not correct: `\ - \$emailFromAddress`, check `Tools -> Email`. Script stopped.\");\r\ - \n :error \$exitErrorMessage;\r\ - \n}\r\ - \n# Script mode validation\r\ - \n:if (\$BackupAndUpdateMode != \"backup\" and \$BackupAndUpdateMode != \"\ - osupdate\" and \$BackupAndUpdateMode != \"updateOnce\" and \$BackupAndUpda\ - teMode != \"osnotify\") do={\r\ - \n :log error (\"\$SMP Script parameter `\\\$BackupAndUpdateMode` is not \ - set, or contains invalid value: `\$BackupAndUpdateMode`. Script stopped.\"\ - );\r\ - \n :error \$exitErrorMessage;\r\ - \n}\r\ - \n# Update channel validation\r\ - \n:if (\$updateChannel != \"stable\" and \$updateChannel != \"long-term\" \ - and \$updateChannel != \"testing\" and \$updateChannel != \"development\")\ - \_do={\r\ - \n :log error (\"\$SMP Script parameter `\\\$updateChannel` is not set, o\ - r contains invalid value: `\$updateChannel`. Script stopped.\");\r\ - \n :error \$exitErrorMessage;\r\ - \n}\r\ - \n# Verify if script is set to install patch updates and if the update cha\ - nnel is valid\r\ - \n:if ((\$BackupAndUpdateMode = \"osupdate\" or \$BackupAndUpdateMode = \"\ - updateOnce\") and \$installOnlyPatchUpdates = true) do={\r\ - \n :if (\$updateChannel != \"stable\" and \$updateChannel != \"long-term\ - \") do={\r\ - \n :log error (\"\$SMP Patch-only updates enabled, but update channel `\ - \$updateChannel` is invalid. Only `stable` and `long-term` are supported. \ - Script stopped\");\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n \r\ - \n :if (\$runningChannel != \"stable\" and \$runningChannel != \"long-ter\ - m\") do={\r\ - \n :log error (\"\$SMP Script is set to install only patch updates, but\ - \_the installed RouterOS version is not from `stable` or `long-term` chann\ - el: `\$runningChannel`. Script stopped\");\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n}\r\ - \n#\r\ - \n\r\ - \n:local rawTime [/system clock get time];\r\ - \n:local rawDate [/system clock get date];\r\ - \n\r\ - \n:local deviceOsVerAndChannelRunning [/system/resource/get version];\r\ - \n\r\ - \n:local backupNameTemplate (\"backup_v\" . \$runningVersion . \"_\" .\ - \_\$runningChannel . \"_\" . \$MDTSFix);\r\ - \n:local backupNameBeforeUpdate (\$backupNameTemplate . \"_before_update\"\ - );\r\ - \n:local backupNameAfterUpdate (\$backupNameTemplate . \"_after_update\")\ - ;\r\ - \n\r\ - \n## Email body template\r\ - \n:local mailSubjectPrefix \"\$SMP Device - `\$IdentityShort`\";\r\ - \n:local mailBodyCopyright \"Mikrotik RouterOS automatic backup & update \ - (ver. \$scriptVersion) \\n\$copyrightUrl\";\r\ - \n:local changelogUrl \"Check RouterOS changelog: https://mikrotik.com\ - /download/changelogs/\";\r\ - \n:local mailBodyDeviceInfo \"\";\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"Device information:\")\ - ;\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\n-------------------\ - --\");\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nName: \$Identity\")\ - ;\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nModel: \$devModel\"\ - );\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nBoard: \$devBoardNa\ - me\");\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nSerial number: \$de\ - vRbSerialNumber\");\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nRouterOS version: v\ - \$deviceOsVerAndChannelRunning\");\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nBuild time: \$[/sys\ - tem/resource/get build-time]\");\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nRouterboard FW Avai\ - lable: \$ROsVerAvail\");\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nDevice date-time: \ - \$rawDate \$rawTime (\$[/system/clock/get time-zone-name ])\");\r\ - \n:set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nUptime: \$[/system/\ - resource/get uptime]\");\r\ - \n## IP address detection\r\ - \n:if ([ \$DevInfoIncludeIP ] = true) do={\r\ - \n :global GetPubIp;\r\ - \n :local PublicIpAddress [ \$GetPubIp ];\r\ - \n :set mailBodyDeviceInfo (\$mailBodyDeviceInfo . \"\\nPublic IP address\ - : \" . \$PublicIpAddress . \".\");\r\ - \n :log info \"\$SMP Public IP address detected: \$PublicIpAddress\";\r\ - \n} \r\ - \n\r\ - \n:local mailAttachments [:toarray \"\"];\r\ - \n:if (\$scriptStep = 1 or \$scriptStep = 3) do={\r\ - \n :if (\$scriptStep = 3) do={\r\ - \n :log info (\"\$SMP Waiting for one minute before continuing to the f\ - inal step.\");\r\ - \n :delay 1m;\r\ - \n }\r\ - \n}\r\ - \n\r\ - \n## STEP 1: Create backups, check for new RouterOS, and send email\r\ - \n## Steps 2\C3\A23 run only if auto-update is enabled and a new version i\ - s available\r\ - \n:if (\$scriptStep = 1) do={\r\ - \n :global BackupPassword;\r\ - \n :global BackupSens;\r\ - \n :local isNewOsUpdateAvailable false;\r\ - \n :local isLatestOsAlreadyInstalled true;\r\ - \n :local isOsNeedsToBeUpdated false;\r\ - \n :local isUpdateCheckSucceeded false;\r\ - \n :local isEmailNeedsToBeSent false;\r\ - \n :local mailSubjectPartAction \"\";\r\ - \n :local mailPtBodyAction \"\";\r\ - \n :local mailPtSubjectBackup \"\";\r\ - \n :local mailPtBodyBackup \"\";\r\ - \n # Checking for new version\r\ - \n :if (\$BackupAndUpdateMode = \"osupdate\" or \$BackupAndUpdateMode = \ - \"osnotify\" or \$BackupAndUpdateMode = \"updateOnce\") do={\r\ - \n :log info (\"\$SMP Setting update channel to `\$updateChannel`\");\r\ - \n /system/package/update/set channel=\$updateChannel;\r\ - \n :log info (\"\$SMP Checking for new RouterOS version. Current instal\ - led version is: `\$runningVersion`\");\r\ - \n \$LogPrint debug \$ScriptName (\"Checking for updates...\");\r\ - \n \r\ - \n# /system/package/update/check-for-updates without-paging as-value;\ - \r\ - \n# /system/package/update check-for-updates;\r\ - \n :delay 5s;\r\ - \n :set PkgUpdStatus [ /system/package/update/get status ];\r\ - \n :if (\$PkgUpdStatus = \"New version is available\") do={\r\ - \n :set ROsVerAvail [/system/package/update/get latest-version];\r\ - \n }\r\ - \n\r\ - \n :if (\$PkgUpdStatus = \"New version is available\") do={\r\ - \n :log info (\"\$SMP New RouterOS version is available: `\$ROsVerAva\ - il`\");\r\ - \n :set isNewOsUpdateAvailable true;\r\ - \n :set isLatestOsAlreadyInstalled false;\r\ - \n :set isUpdateCheckSucceeded true;\r\ - \n :set isEmailNeedsToBeSent true;\r\ - \n :set mailSubjectPartAction \"New RouterOS available\";\r\ - \n :set mailPtBodyAction \"New RouterOS version is available, curren\ - t version: v\$runningVersion, new version: v\$ROsVerAvail. \\n\$changelogU\ - rl\";\r\ - \n } else={\r\ - \n :if (\$PkgUpdStatus = \"System is already up to date\") do={\r\ - \n :log info (\"\$SMP No new RouterOS version is available, the lat\ - est version is already installed: `v\$runningVersion`\");\r\ - \n :set isUpdateCheckSucceeded true;\r\ - \n :set mailSubjectPartAction \"No os update available\";\r\ - \n :set mailPtBodyAction \"No new RouterOS version is available, t\ - he latest version is already installed: `v\$runningVersion`\";\r\ - \n } else={\r\ - \n :log error (\"\$SMP Failed to check for new RouterOS version. Pa\ - ckage check status: `\$PkgUpdStatus`\");\r\ - \n :set isEmailNeedsToBeSent true;\r\ - \n :set mailSubjectPartAction \"Error unable to check new os versio\ - n\";\r\ - \n :set mailPtBodyAction \"An error occurred while checking for a \ - new RouterOS version.\\nStatus returned: `\$PkgUpdStatus`\\n\\nPlease revi\ - ew the logs on the device for more details and verify internet connectivit\ - y.\";\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n # Checking if the script needs to install new os version\r\ - \n :if ((\$BackupAndUpdateMode = \"osupdate\" or \$BackupAndUpdateMode = \ - \"updateOnce\") and \$isNewOsUpdateAvailable = true) do={\r\ - \n :if (\$installOnlyPatchUpdates = true) do={\r\ - \n :if ([\$FuncIsPatchUpdateOnly \$runningVersion \$ROsVerAvail] = tr\ - ue) do={\r\ - \n :log info \"\$SMP New RouterOS version is available, and it is a\ - \_patch update. Current version: v\$runningVersion, new version: v\$ROsVer\ - Avail\";\r\ - \n :set isOsNeedsToBeUpdated true;\r\ - \n } else={\r\ - \n :log info \"\$SMP The script will not install this update, becau\ - se it is not a patch update. Current version: v\$runningVersion, new versi\ - on: v\$ROsVerAvail\";\r\ - \n :set mailPtBodyAction (\$mailPtBodyAction . \"\\nThis update wil\ - l not be installed, because the script is set to install only patch update\ - s.\");\r\ - \n }\r\ - \n } else={\r\ - \n :set isOsNeedsToBeUpdated true;\r\ - \n }\r\ - \n }\r\ - \n # Checking If the script needs to create a backup\r\ - \n :if (\$forceBackup = true or \$BackupAndUpdateMode = \"backup\" or \$i\ - sOsNeedsToBeUpdated = true) do={\r\ - \n :log info (\"\$SMP Starting backup process.\");\r\ - \n :set isEmailNeedsToBeSent true;\r\ - \n :local backupName \$backupNameTemplate;\r\ - \n # This means it's the first step where we create a backup before the\ - \_update process\r\ - \n :if (\$isOsNeedsToBeUpdated = true) do={\r\ - \n :set backupName \$backupNameBeforeUpdate;\r\ - \n #Email body if the purpose of the script is to update the device\r\ - \n :set mailSubjectPartAction \"Update preparation\";\r\ - \n :set mailPtBodyAction (\$mailPtBodyAction . \"\\nThe update proces\ - s for device '\$Identity' is scheduled to upgrade RouterOS from version v.\ - \$runningVersion to version v.\$ROsVerAvail (Update channel: \$updateChann\ - el)\");\r\ - \n :set mailPtBodyAction (\$mailPtBodyAction . \"\\nPlease note: The \ - update will proceed only after a successful backup.\");\r\ - \n :set mailPtBodyAction (\$mailPtBodyAction . \"\\nA final report wi\ - th detailed information will be sent once the update process is completed.\ - \");\r\ - \n :set mailPtBodyAction (\$mailPtBodyAction . \"\\nIf you do not rec\ - eive a second email within the next 10 minutes, there may be an issue. Ple\ - ase check your device logs for further information.\");\r\ - \n }\r\ - \n :do {\r\ - \n :set mailAttachments [\$FuncCreateBackups \$backupName \$BackupPas\ - sword \$BackupSens];\r\ - \n :set mailPtSubjectBackup \"Backup created\";\r\ - \n :set mailPtBodyBackup \"System backups have been successfully crea\ - ted and attached to this email.\";\r\ - \n } on-error={\r\ - \n :set isOsNeedsToBeUpdated false;\r\ - \n :set mailPtSubjectBackup \"Backup failed\";\r\ - \n :set mailPtBodyBackup \"The script failed to create backups. Pleas\ - e check device logs for more details.\";\r\ - \n :log warning \"\$SMP Backup creation failed. Update process will b\ - e canceled if automatic update is enabled\";\r\ - \n }\r\ - \n }\r\ - \n :if (\$isEmailNeedsToBeSent = true) do={\r\ - \n :log info \"\$SMP Preparing to send email...\";\r\ - \n :local mailStep1Subject \$mailSubjectPrefix;\r\ - \n :local mailStep1Body \"\";\r\ - \n # subject\r\ - \n :if (\$mailSubjectPartAction != \"\") do={:set mailStep1Subject (\$\ - mailStep1Subject . \" - \" . \$mailSubjectPartAction)}\r\ - \n :if (\$mailPtSubjectBackup != \"\") do={:set mailStep1Subject (\$ma\ - ilStep1Subject . \" - \" . \$mailPtSubjectBackup)}\r\ - \n # body\r\ - \n :if (\$mailPtBodyAction != \"\") do={:set mailStep1Body (\$mailStep1\ - Body . \$mailPtBodyAction . \"\\n\\n\")}\r\ - \n :if (\$mailPtBodyBackup != \"\") do={:set mailStep1Body (\$mailStep1\ - Body . \$mailPtBodyBackup . \"\\n\\n\")}\r\ - \n :set mailStep1Body (\$mailStep1Body . \$mailBodyDeviceInfo . \"\\n__\ - ________\\n\" . \$mailBodyCopyright);\r\ - \n :set mailStep1Body (\$mailStep1Body . \"\\n[*** TEST START ***]\\n\\\ - \$DeviceInfo: \" . [ \$DeviceInfo ] . \"\\n[*** TEST END ***]\\n\");\r\ - \n # Send email with backups\r\ - \n :do {\$FuncSendEmailSafe \$EmailGeneralTo \$mailStep1Subject \$mailS\ - tep1Body \$mailAttachments} on-error={\r\ - \n :set isOsNeedsToBeUpdated false;\r\ - \n :log error \"\$SMP The script will not proceed with the update pro\ - cess, because the email was not sent.\";\r\ - \n }\r\ - \n }\r\ - \n :if ([:len \$mailAttachments] > 0) do={\r\ - \n :log info \"\$SMP Cleaning up backup files from the file system...\"\ - ;\r\ - \n /file remove \$mailAttachments;\r\ - \n :delay 2s;\r\ - \n }\r\ - \n :if (\$isOsNeedsToBeUpdated = true) do={\r\ - \n :global OldMode;\r\ - \n :log info \"\$SMP everything is ready to install new RouterOS, going\ - \_to start the update process and reboot the device.\";\r\ - \n :do {\r\ - \n :local nextStep 2;\r\ - \n :if (\$isCloudHostedRouter = true) do={\r\ - \n :log info \"\$SMP The device is a cloud hosted router, the secon\ - d step updating the Routerboard firmware will be skipped.\";\r\ - \n :set nextStep 3;\r\ - \n }\r\ - \n :local scheduledCommand (\":delay 5s; /system/scheduler remove BKP\ - UPD-NEXT-BOOT-TASK; \\\r\ - \n :global buGlobalVarScriptStep \$nextStep; :global buGlobalVarTarg\ - etOsVersion \\\"\$ROsVerAvail\\\"; \\\r\ - \n :delay 10s; /system/script { run \$ScriptName; }\");\r\ - \n /system/scheduler add name=BKPUPD-NEXT-BOOT-TASK on-event=\$schedu\ - ledCommand start-time=startup interval=0;\r\ - \n /system/package/update install;\r\ - \n } on-error={\r\ - \n # Failed to install new os version, remove the task and variables\ - \r\ - \n :do {\r\ - \n /system/scheduler remove BKPUPD-NEXT-BOOT-TASK;\r\ - \n :set BackupAndUpdateMode \$OldMode;\r\ - \n :delay 2;\r\ - \n :do {\r\ - \n :global buGlobalVarTargetOsVersion (a);\r\ - \n } on-error={\r\ - \n :set \$mailSubjectPrefix (\$mailSubjectPrefix . \"ERROR Remove\ - \_global variable \\\$buGlobalVarTargetOsVersion failed!\");\r\ - \n }\r\ - \n# :if ([ :len \$OldMode ] > 0) do={\r\ - \n# :do {\r\ - \n# :global OldMode (a);\r\ - \n# } on-error={\r\ - \n# :set \$mailSubjectPrefix (\$mailSubjectPrefix . \" ERROR Re\ - move global variable \\\$OldMode failed!\");\r\ - \n# }\r\ - \n# }\r\ - \n } on-error={\r\ - \n :log error \"\$SMP Failed to install new RouterOS version. Pleas\ - e check device logs for more details. \\\r\ - \n \\nAnd Failed to remove task and variables! Check it!\";\r\ - \n :set \$mailSubjectPrefix (\$mailSubjectPrefix . \" ERROR Remove \ - task and global variables!\");\r\ - \n }\r\ - \n :log error \"\$SMP Failed to install new RouterOS version. Please \ - check device logs for more details.\";\r\ - \n :local mailUpdateErrorSubject (\$mailSubjectPrefix . \" - Update f\ - ailed\");\r\ - \n :local mailUpdateErrorBody \"The script was unable to install new \ - RouterOS version. Please check device logs for more details.\";\r\ - \n # Send email with error\r\ - \n \$FuncSendEmailSafe \$EmailGeneralTo \$mailUpdateErrorSubject \$ma\ - ilUpdateErrorBody \"\";\r\ - \n :error \$exitErrorMessage;\r\ - \n }\r\ - \n }\r\ - \n}\r\ - \n## STEP 2: (Post-reboot) Upgrade RouterBOARD firmware\r\ - \n## Runs only if auto-update is enabled and a new RouterOS version was fo\ - und\r\ - \n:if (\$scriptStep = 2) do={\r\ - \n :log info \"\$SMP The script is in the second step, updating Routerboa\ - rd firmware.\";\r\ - \n :log info \"\$SMP Upgrading routerboard firmware from v.\$deviceRbCurr\ - entFw to v.\$deviceRbUpgradeFw\";\r\ - \n /system routerboard upgrade;\r\ - \n :delay 2;\r\ - \n :log info \"\$SMP routerboard upgrade process was completed, going to \ - reboot in a moment!\";\r\ - \n ## Set task to send final report on the next boot\r\ - \n /system scheduler add name=BKPUPD-NEXT-BOOT-TASK on-event=\":delay 2; \ - :global buGlobalVarScriptStep 3; \\\r\ - \n :global buGlobalVarTargetOsVersion \\\"\$buGlobalVarTargetOsVersion\\\ - \"; :delay 10s; /system/script { run \$ScriptName; }; \\ \r\ - \n :delay 5s; /system/scheduler remove BKPUPD-NEXT-BOOT-TASK;\" start-ti\ - me=startup interval=0;\r\ - \n :delay 2;\r\ - \n /system reboot;\r\ - \n}\r\ - \n\r\ - \n## STEP 3: Final report (after second reboot, with delay).\r\ - \n## Runs only if auto-update is enabled and a new RouterOS version was fo\ - und.\r\ - \n:if (\$scriptStep = 3) do={\r\ - \n :log info (\"\$SMP The script is in the third step, sending final repo\ - rt.\");\r\ - \n :local targetOsVersion \$buGlobalVarTargetOsVersion;\r\ - \n :do {\r\ - \n# /system/script/environment remove [find name=\"buGlobalVarTargetOsV\ - ersion\"];\r\ - \n :global buGlobalVarTargetOsVersion (a);\r\ - \n } on-error={\r\ - \n :set \$mailSubjectPrefix (\$mailSubjectPrefix . \" ERROR Remove glob\ - al variable \\\$buGlobalVarTargetOsVersion failed!\");\r\ - \n }\r\ - \n\r\ - \n :if ([ :len \$OldMode ] != 0) do={\r\ - \n :do {\r\ - \n# /system/script/environment remove [find name=\"OldMode\"];\r\ - \n :global OldMode (a);\r\ - \n } on-error={\r\ - \n :set \$mailSubjectPrefix (\$mailSubjectPrefix . \" ERROR! Remove\ - \_global variable \\\$OldMode failed!\");\r\ - \n }\r\ - \n }\r\ - \n :if ([:len \$targetOsVersion] = 0) do={\r\ - \n :log warning \"\$SMP Something is wrong, the script was unable to ge\ - t the target updated OS version from the global variable.\";\r\ - \n }\r\ - \n :local mailStep3Subject \$mailSubjectPrefix;\r\ - \n :local mailStep3Body \"\";\r\ - \n :if (\$targetOsVersion = \$runningVersion) do={\r\ - \n :log info \"\$SMP Successfully verified new RouterOS version: target\ - : `\$targetOsVersion`, current: `\$runningVersion`\";\r\ - \n :set mailStep3Subject (\$mailStep3Subject . \" - Update completed - \ - Backup created\");\r\ - \n :set mailStep3Body (\$mailStep3Body . \"RouterOS and routerboard upg\ - rade process was completed\");\r\ - \n :set mailStep3Body (\$mailStep3Body . \"\\nNew RouterOS version: v.\ - \$targetOsVersion, routerboard firmware: v.\$deviceRbCurrentFw\");\r\ - \n :set mailStep3Body (\$mailStep3Body . \"\\n\$changelogUrl\\nBackups \ - of the upgraded system are in the attachment of this email.\\n\\n\$mailBod\ - yDeviceInfo\\n\\n\$mailBodyCopyright\");\r\ - \n :set mailAttachments [\$FuncCreateBackups \$backupNameAfterUpdate \$\ - BackupPassword \$BackupSens];\r\ - \n } else={\r\ - \n :log error \"\$SMP Failed to verify new RouterOS version: target: `\ - \$targetOsVersion`, current: `\$runningVersion`\";\r\ - \n :set mailStep3Subject (\$mailStep3Subject . \" - Update failed\");\r\ - \n :set mailStep3Body (\$mailStep3Body . \"The script was unable to ver\ - ify that the new RouterOS version was installed, target version: `\$target\ - OsVersion`, current version: `\$runningVersion`\\nCheck device logs for mo\ - re details.\\n\\n\$mailBodyDeviceInfo\\n\\n\$mailBodyCopyright\");\r\ - \n }\r\ - \n \$FuncSendEmailSafe \$EmailGeneralTo \$mailStep3Subject \$mailStep3Bod\ - y \$mailAttachments;\r\ - \n :if ([:len \$mailAttachments] > 0) do={\r\ - \n :log info \"\$SMP Cleaning up backup files from the file system...\"\ - ;\r\ - \n /file remove \$mailAttachments;\r\ - \n :delay 2;\r\ - \n }\r\ - \n :log info (\"\$SMP Final report email sent successfully, and the scrip\ - t has finished.\");\r\ - \n}\r\ - \n:log info (\"\$SMP the script has finished, script step: `\$scriptStep` \ - \\n\\n\");\r\ - \n\r\ - \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ - \n" -add comment="download, import and update firewall address-lists" \ - dont-require-permissions=no name=AM-FwAddrLists owner=AM-FwAddrLists \ - policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - source="#!rsc by Vados\r\ - \n# RouterOS script: AM-FwAddrLists\r\ - \n# Script comment: download, import and update firewall address-lists\r\ - \n# Copyright (c) 2007-2026 Vados \r\ - \n#\r\ - \n#\r\ - \n# requires RouterOS, version=7.19\r\ - \n# https://ros.vados.ru/doc/fw-addr-lists.md\r\ - \n:local ExitOK false;\r\ - \n:onerror Err {\r\ - \n :global GlobalConfReady; :global GlobalFuncReady;\r\ - \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ - \\\r\ - \n do={ :error (\"Global config and/or functions not ready.\"); }; } \ - delay=500ms max=50;\r\ - \n :local ScriptName [ :jobname ];\r\ - \n\r\ - \n :global GlobalScriptsUrl;\r\ - \n :local FwAddrListsUrl (\$GlobalScriptsUrl . \"fw-addr-lists.d/\");\r\ - \n\r\ - \n :local FwAddrLists {\r\ - \n \"allow\"={\r\ - \n { url=(\$FwAddrListsUrl . \"allow\");\r\ - \n cert=\"ISRG Root X2\"; timeout=1w };\r\ - \n };\r\ - \n \"block\"={\r\ - \n { url=(\$FwAddrListsUrl . \"block\");\r\ - \n cert=\"ISRG Root X2\" };\r\ - \n# { url=\"https://raw.githubusercontent.com/stamparm/ipsum/refs/hea\ - ds/master/levels/4.txt\";\r\ - \n# # higher level (decrease the numerical value) for more addresses, \ - and vice versa\r\ - \n# cert=\"ISRG Root X1\" };\r\ - \n# { url=\"https://www.dshield.org/block.txt\"; cidr=\"/24\";\r\ - \n# cert=\"GTS Root R4\" };\r\ - \n# { url=\"https://lists.blocklist.de/lists/strongips.txt\";\r\ - \n# cert=\"GTS Root R4\" };\r\ - \n# { url=\"https://www.spamhaus.org/drop/drop_v4.json\";\r\ - \n# cert=\"GTS Root R4\" };\r\ - \n# { url=\"https://www.spamhaus.org/drop/drop_v6.json\";\r\ - \n# cert=\"GTS Root R4\" };\r\ - \n };\r\ - \n# \"mikrotik\"={\r\ - \n# { url=(\$FwAddrListsUrl . \"mikrotik\");\r\ - \n# cert=\"ISRG Root X2\"; timeout=1w };\r\ - \n# };\r\ - \n \"FuckRKN\"={\r\ - \n { url=(\$FwAddrListsUrl . \"FuckRKN\");\r\ - \n cert=\"ISRG Root X2\"; timeout=1w };\r\ - \n };\r\ - \n };\r\ - \n :local FwAddrListTimeOut 1d;\r\ - \n\r\ - \n :global CertificateAvailable;\r\ - \n :global EitherOr;\r\ - \n :global FetchHuge;\r\ - \n :global HumanReadableNum;\r\ - \n :global IfThenElse;\r\ - \n :global LogPrint;\r\ - \n\r\ - \n :global NetMask4;\r\ - \n :global NetMask6;\r\ - \n :global ScriptLock;\r\ - \n \r\ - \n :local FindDelim do={\r\ - \n :local ValidChars \"0123456789.:/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi\ - jklmnopqrstuvwxyz-\";\r\ - \n :for I from=0 to=[ :len \$1 ] do={\r\ - \n :if ([ :typeof [ :find \$ValidChars [ :pick (\$1 . \" \") \$I ] ] \ - ] != \"num\") do={\r\ - \n :return \$I;\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :local GetBranch do={\r\ - \n :global EitherOr;\r\ - \n :return [ :pick [ :convert transform=md5 to=hex [ :pick \$1 0 [ \$Ei\ - therOr [ :find \$1 \"/\" ] [ :len \$1 ] ] ] ] 0 2 ];\r\ - \n }\r\ - \n \r\ - \n :if ([ \$ScriptLock \$ScriptName ] = false) do={\r\ - \n :set ExitOK true;\r\ - \n :error false;\r\ - \n }\r\ - \n\r\ - \n :if ([ :len [ /log/find where topics=({\"script\"; \"warning\"}) \\\r\ - \n message=(\"\\\$LogPrint: The message is already in log, scripting \ - subsystem may have crashed before!\") ] ] > 0) do={\r\ - \n :log warning (\$ScriptName . \" Scripting subsystem may have crashed\ - , possibly caused by us. Delaying!\");\r\ - \n :delay 5m;\r\ - \n }\r\ - \n\r\ - \n :local ListComment (\"managed by \" . \$ScriptName);\r\ - \n\r\ - \n :foreach FwListName,FwList in=\$FwAddrLists do={\r\ - \n :local CntAdd 0;\r\ - \n :local CntRenew 0;\r\ - \n :local CntRemove 0;\r\ - \n :local IPv4Addresses ({});\r\ - \n :local IPv6Addresses ({});\r\ - \n :local Failure false;\r\ - \n\r\ - \n :foreach List in=\$FwList do={\r\ - \n :local CheckCertificate false;\r\ - \n :local Data false;\r\ - \n :local TimeOut [ \$EitherOr [ :totime (\$List->\"timeout\") ] \$Fw\ - AddrListTimeOut ];\r\ - \n\r\ - \n :if ([ :len (\$List->\"cert\") ] > 0) do={\r\ - \n :set CheckCertificate true;\r\ - \n :if ([ \$CertificateAvailable (\$List->\"cert\") \"fetch\" ] = f\ - alse) do={\r\ - \n :log warning (\$ScriptName . \" Downloading required certifica\ - te (\" . \$FwListName . \\\r\ - \n \" / \" . \$List->\"url\" . \") failed, trying anyway.\");\ - \r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :for I from=1 to=5 do={\r\ - \n :if (\$Data = false) do={\r\ - \n :set Data [ :tolf [ \$FetchHuge \$ScriptName (\$List->\"url\")\ - \_\$CheckCertificate ] ];\r\ - \n :if (\$Data = false) do={\r\ - \n :if (\$I < 5) do={\r\ - \n :log debug (\$ScriptName . \" Failed downloading for list \ - '\" . \$FwListName . \\\r\ - \n \"', \" . \$I . \". try from: \" . \$List->\"url\");\r\ - \n :delay ((\$I * \$I) . \"s\");\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :if (\$Data = false) do={\r\ - \n :set Data \"\";\r\ - \n :set Failure true;\r\ - \n :log warning (\$ScriptName . \" Failed downloading for list '\" \ - . \$FwListName . \\\r\ - \n \"' from: \" . \$List->\"url\");\r\ - \n } else={\r\ - \n :log debug (\$ScriptName . \" Downloaded \" . [ \$HumanReadableN\ - um [ :len \$Data ] 1024 ] . \\\r\ - \n \"B for list '\" . \$FwListName . \"' from: \" . \$List->\"u\ - rl\");\r\ - \n }\r\ - \n\r\ - \n :foreach Line in=[ :deserialize \$Data delimiter=\"\\n\" from=dsv \ - options=dsv.plain ] do={\r\ - \n :set Line (\$Line->0);\r\ - \n :local Address;\r\ - \n :if ([ :pick \$Line 0 1 ] = \"{\" && [ :pick \$Line ([ :len \$Li\ - ne ] - 1) ] = \"}\") do={\r\ - \n :do {\r\ - \n :set Address [ :tostr ([ :deserialize from=json \$Line ]->\"\ - cidr\") ];\r\ - \n } on-error={ }\r\ - \n } else={\r\ - \n :set Address ([ :pick \$Line 0 [ \$FindDelim \$Line ] ] . (\$L\ - ist->\"cidr\"));\r\ - \n }\r\ - \n :do {\r\ - \n :local Branch;\r\ - \n :if (\$Address ~ \"^[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}\\\ - \\.[0-9]{1,3}(/[0-9]{1,2})\?\\\$\") do={\r\ - \n :local Net \$Address;\r\ - \n :local CIDR 32;\r\ - \n :local Slash [ :find \$Address \"/\" ];\r\ - \n :if ([ :typeof \$Slash ] = \"num\") do={\r\ - \n :set Net [ :toip [ :pick \$Address 0 \$Slash ] ]\r\ - \n :set CIDR [ :pick \$Address (\$Slash + 1) [ :len \$Address\ - \_] ];\r\ - \n :set Address [ :tostr (([ :toip \$Net ] & [ \$NetMask4 \$C\ - IDR ]) . [ \$IfThenElse (\$CIDR < 32) (\"/\" . \$CIDR) ]) ];\r\ - \n }\r\ - \n :set Branch [ \$GetBranch \$Address ];\r\ - \n :set (\$IPv4Addresses->\$Branch->\$Address) \$TimeOut;\r\ - \n :error true;\r\ - \n }\r\ - \n :if (\$Address ~ \"^[0-9a-zA-Z]*:[0-9a-zA-Z:\\\\.]+(/[0-9]{1,3\ - })\?\\\$\") do={\r\ - \n :local Net \$Address;\r\ - \n :local CIDR 128;\r\ - \n :local Slash [ :find \$Address \"/\" ];\r\ - \n :if ([ :typeof \$Slash ] = \"num\") do={\r\ - \n :set Net [ :toip6 [ :pick \$Address 0 \$Slash ] ]\r\ - \n :set CIDR [ :pick \$Address (\$Slash + 1) [ :len \$Address\ - \_] ];\r\ - \n }\r\ - \n :set Address (([ :toip6 \$Net ] & [ \$NetMask6 \$CIDR ]) . \ - \"/\" . \$CIDR);\r\ - \n :set Branch [ \$GetBranch \$Address ];\r\ - \n :set (\$IPv6Addresses->\$Branch->\$Address) \$TimeOut;\r\ - \n :error true;\r\ - \n }\r\ - \n :if (\$Address ~ \"^[\\\\.a-zA-Z0-9-]+\\\\.[a-zA-Z]{2,}\\\$\")\ - \_do={\r\ - \n :set Branch [ \$GetBranch \$Address ];\r\ - \n :set (\$IPv4Addresses->\$Branch->\$Address) \$TimeOut;\r\ - \n :set (\$IPv6Addresses->\$Branch->\$Address) \$TimeOut;\r\ - \n :error true;\r\ - \n }\r\ - \n } on-error={:log error (\$ScriptName . \" Failed parsing address\ - : \" . \$Line->0);}\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :foreach Entry in=[ /ip/firewall/address-list/find where \\\r\ - \n list=\$FwListName comment=\$ListComment ] do={\r\ - \n :local Address [ /ip/firewall/address-list/get \$Entry address ];\ - \r\ - \n :local Branch [ \$GetBranch \$Address ];\r\ - \n :local TimeOut (\$IPv4Addresses->\$Branch->\$Address);\r\ - \n :if ([ :typeof \$TimeOut ] = \"time\") do={\r\ - \n :log debug (\$ScriptName . \" Renewing IPv4 address \" . \$Addre\ - ss . \\\r\ - \n \" in list '\" . \$FwListName . \"' with \" . \$TimeOut . \"\ - .\");\r\ - \n /ip/firewall/address-list/set \$Entry timeout=\$TimeOut;\r\ - \n :set (\$IPv4Addresses->\$Branch->\$Address);\r\ - \n :set CntRenew (\$CntRenew + 1);\r\ - \n } else={\r\ - \n :if (\$Failure = false) do={\r\ - \n :log debug (\$ScriptName . \" Removing IPv4 address \" . \$Add\ - ress . \\\r\ - \n \" from list '\" . \$FwListName . \".\");\r\ - \n /ip/firewall/address-list/remove \$Entry;\r\ - \n :set CntRemove (\$CntRemove + 1);\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :foreach Entry in=[ /ipv6/firewall/address-list/find where \\\r\ - \n list=\$FwListName comment=\$ListComment ] do={\r\ - \n :local Address [ /ipv6/firewall/address-list/get \$Entry address ]\ - ;\r\ - \n :local Branch [ \$GetBranch \$Address ];\r\ - \n :local TimeOut (\$IPv6Addresses->\$Branch->\$Address);\r\ - \n :if ([ :typeof \$TimeOut ] = \"time\") do={\r\ - \n :log debug (\$ScriptName . \" Renewing IPv6 address \" . \$Addre\ - ss . \\\r\ - \n \" in list '\" . \$FwListName . \"' with \" . \$TimeOut . \"\ - .\");\r\ - \n /ipv6/firewall/address-list/set \$Entry timeout=\$TimeOut;\r\ - \n :set (\$IPv6Addresses->\$Branch->\$Address);\r\ - \n :set CntRenew (\$CntRenew + 1);\r\ - \n } else={\r\ - \n :if (\$Failure = false) do={\r\ - \n :log debug (\$ScriptName . \" Removing IPv6 address \" . \$Add\ - ress . \\\r\ - \n \" from list '\" . \$FwListName .\".\");\r\ - \n /ipv6/firewall/address-list/remove \$Entry;\r\ - \n :set CntRemove (\$CntRemove + 1);\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :foreach BranchName,Branch in=\$IPv4Addresses do={\r\ - \n :log debug (\$ScriptName . \" Handling branch: \" . \$BranchName);\ - \r\ - \n :foreach Address,Timeout in=\$Branch do={\r\ - \n :log debug (\$ScriptName . \" Adding IPv4 address \" . \$Address\ - \_. \\\r\ - \n \" to list '\" . \$FwListName . \"' with \" . \$Timeout . \"\ - .\");\r\ - \n :onerror Err {\r\ - \n /ip/firewall/address-list/add list=\$FwListName comment=\$List\ - Comment \\\r\ - \n address=\$Address timeout=\$Timeout;\r\ - \n :set CntAdd (\$CntAdd + 1);\r\ - \n } do={\r\ - \n :log warning (\$ScriptName . \" Failed to add IPv4 address \" \ - . \$Address . \\\r\ - \n \" to list '\" . \$FwListName . \"': \" . \$Err);\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :foreach BranchName,Branch in=\$IPv6Addresses do={\r\ - \n :log debug (\$ScriptName . \" Handling branch: \" . \$BranchName);\ - \r\ - \n :foreach Address,Timeout in=\$Branch do={\r\ - \n :log debug (\$ScriptName . \" Adding IPv6 address \" . \$Address\ - \_. \\\r\ - \n \" to list '\" . \$FwListName . \"' with \" . \$Timeout . \"\ - .\");\r\ - \n :onerror Err {\r\ - \n /ipv6/firewall/address-list/add list=\$FwListName comment=\$Li\ - stComment \\\r\ - \n address=\$Address timeout=\$Timeout;\r\ - \n :set CntAdd (\$CntAdd + 1);\r\ - \n } do={\r\ - \n :log warning (\$ScriptName . \" Failed to add IPv6 address \" \ - . \$Address . \\\r\ - \n \" to list '\" . \$FwListName . \"': \" . \$Err);\r\ - \n }\r\ - \n }\r\ - \n }\r\ - \n\r\ - \n :log info (\$ScriptName . \" list: \" . \$FwListName . \\\r\ - \n \" (\" . [ \$HumanReadableNum (\$CntAdd + \$CntRenew) 1000 ] . \ - \")\" . \\\r\ - \n \" -- added: \" . [ \$HumanReadableNum \$CntAdd 1000 ] . \\\r\ - \n \" - renewed: \" . [ \$HumanReadableNum \$CntRenew 1000 ] . \\\r\ - \n \" - removed: \" . [ \$HumanReadableNum \$CntRemove 1000 ]);\r\ - \n }\r\ - \n} do={\r\ - \n :global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err;\r\ - \n}\r\ - \n" + \n:global dec2hex do={\ + \n :local hex \"\"\ + \n :local dec [:tonum \$1]\ + \n :for i from=0 to=4 step=4 do={\ + \n :set hex ([:pick \"0123456789ABCDEF\" ((\$dec>>\$i)&0xf) (((\$de\ + c>>\$i)&0xf)+1)].\$hex)\ + \n }\ + \n :return ([:tostr \$hex])\ + \n}" /user group add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" -/caps-man provisioning -add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ - cfg-2ghz name-format=prefix-identity name-prefix=2ghz -add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ - cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac -add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ - cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an -/certificate settings -set builtin-trust-store=fetch -/disk settings -set auto-media-interface=lo default-mount-point-template=usb1 /ip smb -set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +set enabled=no interfaces=lo /interface bridge port -add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ - internal-path-cost=10 path-cost=10 -add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ - internal-path-cost=10 path-cost=10 -add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ - internal-path-cost=10 path-cost=10 -add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ - internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN interface=ether5 trusted=yes trusted-dhcpv6=yes +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-LAN interface=ether4 trusted-dhcpv6=yes trusted-ra=yes +add bridge=Bridge-LAN interface=ether3 +add bridge=Bridge-LAN interface=wlan2 +add bridge=Bridge-LAN interface=wlan1 +/interface bridge settings +# ipv6 neighbor configuration has changed, please restart the device in order to apply the new settings +set use-ip-firewall=yes /ip firewall connection tracking +# ipv6 neighbor configuration has changed, please restart the device in order to apply the new settings set udp-timeout=10s /ip neighbor discovery-settings -set discover-interface-list=LAN +# ipv6 neighbor configuration has changed, please restart the device in order to apply the new settings +set discover-interface-list=LAN lldp-med=no lldp-poe-power=no protocol="" /ip settings -set max-neighbor-entries=8192 secure-redirects=no +# ipv6 neighbor configuration has changed, please restart the device in order to apply the new settings +set accept-redirects=yes ipv4-multipath-hash-policy=l4 max-neighbor-entries=\ + 8192 /ipv6 settings -set disable-ipv6=yes max-neighbor-entries=8192 +# ipv6 neighbor configuration has changed, please restart the device in order to apply the new settings +set allow-fast-path=no disable-ipv6=yes disable-link-local-address=yes \ + max-neighbor-entries=8192 multipath-hash-policy=l4 /interface detect-internet -set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ - LAN wan-interface-list=WAN +set detect-interface-list=WAN internet-interface-list=Internet \ + lan-interface-list=LAN wan-interface-list=WAN /interface l2tp-server server set authentication=mschap2 use-ipsec=yes /interface list member -add comment=WAN interface="ether1 - Unet" list=WAN +add interface="ether1 - Unet" list=WAN add interface=Bridge-LAN list=LAN -/interface ovpn-server server -add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 -/interface wifi cap -set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ - wlan1,wlan2 lock-to-caps-man=no slaves-static=no -/interface wifi capsman -set package-path="" require-peer-certificate=no upgrade-policy=none -/interface wifi provisioning -add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ - name-format=2G-%I slave-configurations=2G-G supported-bands=\ - 2ghz-n,2ghz-g,2ghz-g -add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ - name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac /interface wireguard peers -add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ - endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ - MikroVados persistent-keepalive=10s public-key=\ +add allowed-address=0.0.0.0/0 client-allowed-address=0.0.0.0/0 disabled=yes \ + interface=WG name=MikroVados persistent-keepalive=10s public-key=\ "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +add allowed-address=0.0.0.0/0 client-address=10.8.0.1/24 \ + client-allowed-address=0.0.0.0/0 client-dns=8.8.8.8 client-endpoint=\ + 146.120.64.211 client-keepalive=10s interface=WG name=GitHub \ + persistent-keepalive=10s public-key=\ + "HTofQ0KtUsZij7zFn0F72r8oatxGn/el6bzLhM9El1g=" responder=yes /interface wireless cap -# set bridge=Bridge-LAN caps-man-addresses=10.30.30.10 \ caps-man-certificate-common-names=CAPsMAN-51B25E507D07 certificate=\ - CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes interfaces=\ - wlan1,wlan2 lock-to-caps-man=yes -/interface wireless sniffer -set file-name=24g + CAP-488F5A8E1ABC interfaces=wlan2,wlan1 lock-to-caps-man=yes /ip address +add address=10.8.0.2 interface=WG network=10.8.0.0 add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 -add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip cloud +set update-time=no /ip dhcp-client -add add-default-route=special-classless default-route-distance=2 \ - default-route-tables=main interface="ether1 - Unet" name="ether1 - Unet" \ - use-peer-dns=no +add default-route-tables=main dhcp-options=hostname,clientid,clientid_duid \ + interface="ether1 - Unet" name=client1 use-broadcast=never use-peer-dns=\ + no use-peer-ntp=no /ip dhcp-server config set accounting=no /ip dhcp-server lease @@ -4762,12 +2639,16 @@ add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ 10:B1:DF:E9:D0:D5 server=masterDHCP add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ CC:42:10:12:46:94 server=masterDHCP add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ 50:CC:F8:85:96:0A server=masterDHCP add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ mac-address=C4:82:E1:03:49:10 server=masterDHCP add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ @@ -4778,70 +2659,75 @@ add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ server=masterDHCP -add address=10.30.30.74 client-id=1:20:72:a9:d3:34:36 dhcp-option=HostName \ - dhcp-option-set=MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP \ - use-src-mac=yes +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ mac-address=F0:75:5D:1E:5F:71 server=masterDHCP add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ masterDHCP -add address=10.30.30.86 dhcp-option=HostName dhcp-option-set=MikroYellow \ - mac-address=48:8F:5A:8E:1A:C2 server=masterDHCP /ip dhcp-server network -add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=HostName \ - dhcp-option-set=domain-search-set dns-server=10.30.30.81 domain=WORKGROUP \ - gateway=10.30.30.81 netmask=24 ntp-server=10.30.30.81,10.30.30.10 \ - wins-server=10.30.30.95,10.30.30.98 +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81 domain=WORKGROUP gateway=10.30.30.81 netmask=24 ntp-server=\ + 10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 /ip dns set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ - doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 +/ip dns adlist +add disabled=yes url=https://ros.vados.ru/dns/vados.ru.local +add disabled=yes url=https://ros.vados.ru/dns/30.30.10.in-addr.arpa /ip dns static -add address=10.30.30.33 name=amster-nuc type=A +add comment="Local DNS server for vados.ru" ns=10.30.30.81 regexp=*.vados.ru \ + type=NS +add comment="*.vados.ru Regexp" forward-to=10.30.30.81 regexp=\ + "\".*\\\\.vados\\\\.ru\"" type=FWD +add comment="*.30.30.10.in-addr.arpa Regexp" forward-to=10.30.30.81 regexp=\ + "\".*\\\\.30\\\\.30\\\\.10\\\\.in-addr\\\\.arpa" type=FWD +add address=10.30.30.81 comment=NS.vados.ru.local name=ns.vados.ru.local \ + type=A +add comment="DNS ns.vados.ru.local" match-subdomain=yes name=vados.ru ns=\ + ns.vados.ru.local type=NS +add address=10.30.30.33 comment=reg.vados.ru name=reg.vados.ru type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" match-subdomain=yes name=\ + dns.google type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=ros.vados.ru type=A +add address=10.30.30.95 name=vados-nuc type=A +add address=10.30.30.33 name=amster-nuc type=A add address=10.30.30.33 name=amster type=A add address=10.30.30.33 name=amster-reg type=A add address=10.30.30.33 name=mng.vados.ru type=A add address=10.30.30.33 name=mgr.vados.ru type=A add address=10.30.30.33 name=prt.vados.ru type=A -add address=10.30.30.33 name=git.vados.ru type=A -add address=10.30.30.33 name=reg.vados.ru type=A -add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A -add address=10.30.30.33 name=oxidized.vados.ru type=A -add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A -add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A add address=10.30.30.30 name=MILLER-LEN type=A add address=10.30.30.30 name=miller type=A -add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" disabled=yes name=\ security.cloudflare-dns.com type=A -add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" disabled=yes name=\ security.cloudflare-dns.com type=A add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ dns.quad9.net type=A add address=149.112.112.112 comment="Cuad9-dns IPv4 2" disabled=yes name=\ dns.quad9.net type=A -add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ - A +add address=195.133.25.16 comment="DNS Comss" name=dns.comss.one type=A add address=10.30.30.81 comment=LocalNet name=MikroVados type=A add address=10.30.30.10 name=MikroNUC type=A add address=10.30.30.86 name=MikroYellow type=A add address=10.30.30.85 name=MikroMic type=A add address=10.30.30.95 name=VADOS-NUC type=A add address=10.30.30.98 name=VADOS-LEN type=A +add address=91.192.189.2 comment=Unet-DNS name=ns1.unet.ws type=A add address=10.30.30.20 name=garage type=A -add address=2606:4700:4700::1111 disabled=yes name=\ - security.cloudflare-dns.com type=AAAA -add address=2606:4700:4700::1001 disabled=yes name=\ - security.cloudflare-dns.com type=AAAA /ip firewall address-list add address=91.215.120.206 list=TRUSTED add address=185.71.70.78 disabled=yes list=TRUSTED add address=176.53.203.171 disabled=yes list=TRUSTED add address=176.53.203.170 disabled=yes list=TRUSTED add address=176.53.202.194 disabled=yes list=TRUSTED -add address=10.30.30.100-255 list=KIDS add address=8.8.4.0/24 list=YouTube add address=8.8.8.0/24 list=YouTube add address=8.34.208.0/20 list=YouTube @@ -4926,112 +2812,7 @@ add address=209.85.128.0/17 list=YouTube add address=216.58.192.0/19 list=YouTube add address=216.73.80.0/20 list=YouTube add address=216.239.32.0/19 list=YouTube -add address=2ip.ru list=Test -add address=157.240.247.174 list=Instagram -add address=46.53.178.107 list=Instagram -add address=179.60.195.174 list=Instagram -add address=157.240.205.174 list=Instagram -add address=31.13.24.0/21 list=Instagram -add address=31.13.64.0/18 list=Instagram -add address=45.64.40.0/22 list=Instagram -add address=66.220.144.0/20 list=Instagram -add address=69.63.176.0/20 list=Instagram -add address=69.171.224.0/19 list=Instagram -add address=74.119.76.0/22 list=Instagram -add address=103.4.96.0/22 list=Instagram -add address=129.134.0.0/16 list=Instagram -add address=157.240.0.0/16 list=Instagram -add address=173.252.64.0/18 list=Instagram -add address=179.60.192.0/22 list=Instagram -add address=185.60.216.0/22 list=Instagram -add address=204.15.20.0/22 list=Instagram -add address=157.240.200.63 list=Instagram -add address=185.60.219.63 list=Instagram -add address=129.134.31.12 list=Instagram -add address=66.81.203.132 list=Instagram -add address=185.89.218.12 list=Instagram -add address=31.13.66.63 list=Instagram -add address=84.15.65.162 list=Instagram -add address=68.66.224.28 list=Instagram -add address=157.240.253.63 list=Instagram -add address=83.174.11.224 list=Instagram -add address=157.240.9.52 list=Instagram -add address=157.240.252.174 list=Instagram -add address=157.240.195.63 list=Instagram -add address=31.13.71.52 list=Instagram -add address=57.144.110.192 list=Instagram -add address=157.240.252.17 list=Instagram -add address=84.15.66.97 list=Instagram -add address=217.168.6.33 list=Instagram -add address=31.13.83.52 list=Instagram -add address=157.240.241.63 list=Instagram -add address=129.134.30.12 list=Instagram -add address=185.89.219.12 list=Instagram -add address=157.240.252.10 list=Instagram -add address=157.240.201.63 list=Instagram -add address=66.81.203.197 list=Instagram -add address=179.60.195.52 list=Instagram -add address=66.81.203.7 list=Instagram -add address=216.40.34.41 list=Instagram -add address=157.240.202.63 list=Instagram -add address=157.240.229.63 list=Instagram -add address=157.240.252.63 list=Instagram -add address=31.13.72.53 list=Instagram -add address=124.108.16.224 list=Instagram -add address=157.240.205.63 list=Instagram -add address=92.46.37.96 list=Instagram -add address=157.240.247.63 list=Instagram -add address=157.240.234.63 list=Instagram -add address=157.240.235.63 list=Instagram -add address=87.245.208.97 list=Instagram -add address=216.58.192.0/19 list=Instagram -add address=209.85.128.0/17 list=Instagram -add address=198.105.240.0/20 list=Instagram -add address=173.194.0.0/16 list=Instagram -add address=172.217.0.0/16 list=Instagram -add address=142.250.0.0/15 list=Instagram -add address=108.177.0.0/17 list=Instagram -add address=87.245.197.140 list=Instagram -add address=74.125.0.0/16 list=Instagram -add address=64.233.160.0/19 list=Instagram -add address=157.240.0.1 list=Instagram -add address=157.240.238.63 list=Instagram -add address=157.240.238.174 list=Instagram -add address=157.240.0.63 list=Instagram -add address=157.240.224.63 list=Instagram -add address=157.240.224.174 list=Instagram -add address=157.240.251.36 list=Instagram -add address=157.240.253.12 list=Instagram -add address=157.240.253.35 list=Instagram -add address=157.240.238.13 list=Instagram -add address=157.240.238.56 list=Instagram -add address=157.240.238.175 list=Instagram -add address=57.144.112.141 list=Instagram -add address=157.240.251.60 list=Instagram -add address=157.240.251.128 list=Instagram -add address=157.240.238.5 list=Instagram -add address=157.240.253.13 list=Instagram -add address=157.240.253.5 list=Instagram -add address=157.240.238.2 list=Instagram -add address=157.240.238.37 list=Instagram -add address=157.240.251.5 list=Instagram -add address=157.240.251.34 list=Instagram -add address=57.144.112.1 list=Instagram -add address=157.240.238.54 list=Instagram -add address=129.134.26.123 list=Instagram -add address=157.240.252.3 list=Instagram -add address=31.13.84.4 list=Instagram -add address=157.240.224.12 list=Instagram -add address=157.240.238.4 list=Instagram -add address=157.240.0.13 list=Instagram -add address=3.33.139.32 list=Instagram -add address=157.240.0.35 list=Instagram -add address=157.240.238.14 list=Instagram -add address=157.240.238.60 list=Instagram -add address=57.144.112.145 list=Instagram -add address=157.240.251.35 list=Instagram -add address=151.101.84.159 list=Twitter -add address=pbs.twimg.com list=Twitter +add address=2ip.ru list=Test-IP add address=89.110.101.17 comment=VDSIna list=TRUSTED add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina @@ -5042,11 +2823,8 @@ add address=vdsina.com list=NoVdsina add address=vdsina.ru list=NoVdsina add address=youla.ru list=NoVdsina add address=kupiprodai.ru list=NoVdsina -add address=myip.ru list=Test +add address=myip.ru list=Test-IP add address=geoip.co list=NoVdsina -add address=x.com list=Twitter -add address=facebook.com list=facebook -add address=fbcd.net list=facebook add address=comp-lenta.ru list=NoVdsina add address=128.85.102.70 comment=update.microsoft.com list=\ windowsupdateslist @@ -5238,9 +3016,6 @@ add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ windowsupdateslist add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ windowsupdateslist -add address=82.202.162.184 comment=comp-lenta.ru list=NoWG -add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG -add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ windowsupdateslist @@ -5443,236 +3218,252 @@ add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ windowsupdateslist add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ paymentinstruments.mp.microsoft.com list=windowsupdateslist -add address=10.30.30.33 comment=amster-nuc disabled=yes list=NoWG -add address=10.30.30.11 comment=MikroNUC list=NoWG -add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG -add address=89.110.101.17 list=VPN-Server +add address=10.30.30.33 comment=amster disabled=yes list=NoWG +add address=10.30.30.10 comment=MikroNUC disabled=yes list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! disabled=yes list=NoWG +add address=wg.vados.ru comment=VDSina-vpn list=VDSina add address=80.85.244.9 list=TRUSTED -add address=8.8.8.8 list=TRUSTED -add address=8.8.4.4 list=TRUSTED add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist -add address=10.30.30.95 comment=NUC list=NoWG -add address=glb.tas02.cws-prod.dcat.dsp.mp.microsoft.com. comment=\ - tas02.cws.update.microsoft.com list=windowsupdateslist -add address=glb.cwsapp.prod.dcat.dsp.trafficmanager.net. comment=\ - glb.tas01.cwsapp-prod.dcat.dsp.mp.microsoft.com list=windowsupdateslist -add address=glb.tas01.cwsapp-prod.dcat.dsp.mp.microsoft.com. comment=\ - tas01.cwsapp.update.microsoft.com list=windowsupdateslist -add address=disc601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ - disc601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=89.110.101.17 comment="!!!VDSina Server!!!" list=NoVdsina +add address=dns.quad9.net comment=Quad9-dns disabled=yes list=Trusted-DNS +add address=dns.google comment=Google-dns list=Trusted-DNS +add address=security.cloudflare-dns.com comment=CloudFlare-dns list=\ + Trusted-DNS +add address=time.google.com comment=Google-time list=Trusted-NTP +add address=0.ru.pool.ntp.org comment=ru.pool.ntp.org disabled=yes list=\ + Trusted-NTP +add address=1.ru.pool.ntp.org disabled=yes list=Trusted-NTP +add address=2.ru.pool.ntp.org comment=2.ru.pool.ntp.org disabled=yes list=\ + Trusted-NTP +add address=3.ru.pool.ntp.org comment=3.ru.pool.ntp.org disabled=yes list=\ + Trusted-NTP +add address=cp.vdsina.com comment=VDSina-vpn list=VDSina +add address=vdsina.ru comment=VDSina-vpn list=VDSina +add address=ns.vados.ru comment=VDSina-vpn list=VDSina +add address=vdsina.com comment=VDSina-vpn list=VDSina +add address=cp.vdsina.ru comment=VDSina-vpn list=VDSina +add address=ns1.vdsina.ru comment=VDSina-vpn list=VDSina +add address=10.30.30.0/24 comment="Local Network" list=Local-Net +add address=10.8.0.0/24 comment="WireGuard Network" list=Local-Net +add address=146.120.64.208/29 comment="External Net" list=Unet +add address=esia.gosuslugi.ru comment=esia.gosuslugi.ru list=NoVdsina +add address=lk.gosuslugi.ru comment=lk.gosuslugi.ru list=NoVdsina +add address=trudvsem.ru comment=trudvsem.ru list=NoVdsina +add address=10.30.30.30 comment=miller disabled=yes list=NoWG +add address=10.30.30.33 comment="Direct connet to DNS servers" list=\ + Direct-DNS /ip firewall filter add action=add-src-to-address-list address-list="Honeypot Hacker" \ address-list-timeout=12h chain=input comment="block honeypot DNS" \ connection-state=new dst-port=53 in-interface="ether1 - Unet" protocol=\ - udp + udp src-address-list=!Trusted-DNS add action=add-src-to-address-list address-list="Honeypot Hacker" \ address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ - in-interface="ether1 - Unet" protocol=tcp + in-interface="ether1 - Unet" protocol=tcp src-address-list=!Trusted-DNS add action=add-src-to-address-list address-list="Honeypot Hacker" \ address-list-timeout=4w2d chain=input comment=\ - "block honeypot ssh rdp winbox" connection-state=new dst-port=\ - 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ - !TRUSTED + "block honeypot ssh rdp winbox" connection-state=new dst-port=22,8291 \ + in-interface="ether1 - Unet" protocol=tcp src-address-list=!TRUSTED add action=add-src-to-address-list address-list="Honeypot Hacker" \ address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ udp add action=add-src-to-address-list address-list="Honeypot Hacker" \ - address-list-timeout=5d chain=input comment="block honeypot NTP" \ + address-list-timeout=4w2d chain=input comment="block honeypot NTP" \ connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ - udp src-address=!10.30.30.0/24 -add action=accept chain=input comment=\ - "accept NTP clients on local area network" dst-port=123 in-interface=\ - Bridge-LAN in-interface-list=LAN protocol=udp -add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ - in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server -add action=accept chain=input disabled=yes dst-port=443 in-interface=\ - "ether1 - Unet" protocol=tcp -add action=accept chain=output disabled=yes protocol=tcp src-port=443 + udp +add action=accept chain=input dst-port=29185 in-interface="ether1 - Unet" \ + protocol=tcp +add action=accept chain=input dst-port=29185 in-interface="ether1 - Unet" \ + protocol=udp +add action=accept chain=input comment="tcp Accept input DNS queries from LAN" \ + disabled=yes dst-port=53 in-interface=Bridge-LAN protocol=tcp \ + src-address=10.30.30.0/24 +add action=accept chain=input comment="udp Accept input DNS queries" \ + disabled=yes dst-port=53 in-interface=Bridge-LAN protocol=udp \ + src-address=10.30.30.0/24 add action=fasttrack-connection chain=forward comment=\ "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ connection-state=established,related,new disabled=yes +add action=accept chain=output comment="accept WireGuard" disabled=yes \ + dst-address-list=VPN-Server out-interface="ether1 - Unet" protocol=udp \ + src-port=13231 +add action=accept chain=output disabled=yes dst-address-list=VPN-Server \ + dst-port=29185 out-interface="ether1 - Unet" protocol=udp add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ connection-state=established,related,new disabled=yes routing-mark=\ !To-VPN -add action=accept chain=input comment=\ - "defconf: accept established,related,untracked" connection-state=\ - established,related,untracked -add action=drop chain=input comment="defconf: drop invalid" connection-state=\ - invalid -add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ - protocol=icmp -add action=accept chain=input comment=\ - "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ - dst-address=127.0.0.1 +add action=accept chain=output disabled=yes protocol=tcp src-port=443 add action=accept chain=output disabled=yes src-address=127.0.0.1 add action=accept chain=forward comment="defconf: accept in ipsec policy" \ - ipsec-policy=in,ipsec + disabled=yes ipsec-policy=in,ipsec add action=accept chain=forward comment="defconf: accept out ipsec policy" \ - ipsec-policy=out,ipsec + disabled=yes ipsec-policy=out,ipsec add action=accept chain=forward comment=\ "defconf: accept established,related, untracked" connection-state=\ established,related,untracked add action=drop chain=forward comment="defconf: drop invalid" \ - connection-state=invalid disabled=yes + connection-state=invalid in-interface="ether1 - Unet" src-address=\ + !10.30.30.0/24 add action=drop chain=forward comment=\ "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ - connection-state=new in-interface="ether1 - Unet" -add action=accept chain=input connection-state=established disabled=yes -add action=accept chain=input connection-state=related disabled=yes -add action=drop chain=input disabled=yes in-interface-list=!LAN + connection-state=new in-interface="ether1 - Unet" src-address-list=\ + !VDSina add action=drop chain=forward comment=\ "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ facebook add action=drop chain=forward comment=\ "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ dst-address-list=YouTube -add action=fasttrack-connection chain=forward comment=\ - "FastTrack main traffic" connection-state=established,related disabled=\ - yes +add action=accept chain=input protocol=icmp +add action=accept chain=input connection-state=established +add action=accept chain=input connection-state=related +add action=drop chain=input in-interface-list=!LAN /ip firewall mangle +add action=mark-routing chain=prerouting comment=\ + "Mark Routing main for NoVdsina" disabled=yes dst-address=!10.30.30.0/24 \ + dst-address-list=NoVdsina new-routing-mark=main passthrough=no \ + src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=\ + "Mark Routing main for VDSina" disabled=yes dst-address=!10.30.30.0/24 \ + dst-address-list=VDSina new-routing-mark=main passthrough=no src-address=\ + 10.30.30.0/24 +add action=mark-routing chain=prerouting comment=\ + "!!!ERROR Mark Routing main for Unet!!!" disabled=yes dst-address-list=\ + Unet new-routing-mark=main passthrough=no +add action=mark-routing chain=prerouting comment="Test-IP sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test-IP new-routing-mark=\ + To-VPN src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=FuckRKN disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=RKN-dnsLookup \ + new-routing-mark=To-VPN passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment="Mark Routing main for NoWG" \ + disabled=yes new-routing-mark=main passthrough=no src-address=\ + 10.30.30.0/24 src-address-list=NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + disabled=yes new-routing-mark=To-VPN src-address=10.30.30.0/24 \ + src-address-list=!NoWG add action=mark-connection chain=prerouting comment=\ - "Mark VPN connections to exclude from FastTrack" in-interface=WG \ - log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack -add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ - dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + "Mark VPN connections to exclude from FastTrack" disabled=yes \ + new-connection-mark=VPN_No_FastTrack +add action=change-mss chain=forward comment="MSS on WG" disabled=yes new-mss=\ + 1380 out-interface=WG protocol=tcp routing-mark=To-VPN tcp-flags=syn \ + tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" disabled=yes \ + dst-address=10.8.0.0/24 log-prefix=VPN-Net new-routing-mark=To-VPN \ passthrough=no src-address=10.30.30.0/24 -add action=mark-routing chain=prerouting comment=Instagram dst-address=\ - !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ - src-address=10.30.30.0/24 src-address-list=!NoWG -add action=mark-routing chain=prerouting comment=Twitter dst-address=\ - !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ - src-address=10.30.30.0/24 src-address-list=!NoWG -add action=mark-routing chain=prerouting comment=YouTube dst-address=\ - !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ - src-address=10.30.30.0/24 src-address-list=!NoWG -add action=mark-routing chain=prerouting comment=facebook dst-address=\ - !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ - src-address=10.30.30.0/24 src-address-list=!NoWG -add action=mark-routing chain=prerouting comment=Telegram dst-address=\ - !10.30.30.0/24 dst-address-list=Telegram new-routing-mark=To-VPN \ - src-address=10.30.30.0/24 src-address-list=!NoWG -add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ - dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ - new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG -add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ - out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 -add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ - 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ - new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG /ip firewall nat -add action=redirect chain=dstnat comment=\ - "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 protocol=tcp \ - src-address=10.30.30.0/24 to-ports=53 -add action=redirect chain=dstnat dst-port=53 protocol=udp src-address=\ - 10.30.30.0/24 to-ports=53 -add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ - out,none out-interface="ether1 - Unet" routing-mark=!To-VPN -add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ - in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ - To-VPN -add action=dst-nat chain=dstnat comment=npm disabled=yes dst-port=81 \ - in-interface="ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 \ - to-ports=81 -add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ - dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ - 10.30.30.33 to-ports=443 +add action=redirect chain=dstnat comment="udp Redirect DNS in NAT" disabled=\ + yes dst-port=53 protocol=udp src-address=10.30.30.0/24 to-addresses=\ + 10.30.30.81 to-ports=53 +add action=redirect chain=dstnat comment="tcp Redirect DNS in NAT" disabled=\ + yes dst-port=53 protocol=tcp src-address=10.30.30.0/24 to-addresses=\ + 10.30.30.81 to-ports=53 +add action=masquerade chain=srcnat comment="Default NAT" out-interface=\ + "ether1 - Unet" src-address=10.30.30.0/24 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps dst-port=443 \ + fragment=no in-interface="ether1 - Unet" protocol=tcp src-address=\ + !10.30.30.0/24 to-addresses=10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru 3x-ui" disabled=yes \ + dst-port=2904 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=2904 +add action=dst-nat chain=dstnat comment=reg.vados.ru disabled=yes dst-port=\ + 5000 in-interface="ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 \ + to-ports=5000 +add action=dst-nat chain=dstnat comment="Docker swarm" disabled=yes dst-port=\ + 2377 in-interface="ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 \ + to-ports=2377 add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ - disabled=yes dst-port=80 in-interface="ether1 - Unet" protocol=tcp \ - to-addresses=10.30.30.33 to-ports=80 -add action=dst-nat chain=dstnat disabled=yes dst-port=80 in-interface=\ - "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=80 + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp routing-mark=To-VPN to-addresses=10.30.30.33 \ + to-ports=81 +add action=dst-nat chain=dstnat comment=SSH dst-port=22 in-interface=\ + "ether1 - Unet" protocol=tcp src-address-list=TRUSTED to-addresses=\ + 10.30.30.33 to-ports=22 +add action=masquerade chain=srcnat comment=WG disabled=yes dst-address-list=\ + !NoVdsina out-interface=WG src-address-list=!NoWG +add action=dst-nat chain=dstnat comment="portainer agent" disabled=yes \ + dst-port=2377 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=2377 +add action=dst-nat chain=dstnat disabled=yes dst-port=22 in-interface=\ + "ether1 - Unet" protocol=tcp routing-mark=!To-VPN to-addresses=\ + 10.30.30.33 to-ports=22 add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ Bridge-LAN protocol=tcp src-address-list=KIDS time=\ 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 -add action=dst-nat chain=dstnat dst-address=146.120.64.211 dst-port=32000 \ - in-interface="ether1 - Unet" protocol=tcp to-addresses=10.30.30.95 \ - to-ports=32000 -add action=dst-nat chain=dstnat dst-address=146.120.64.211 dst-port=32000 \ - in-interface="ether1 - Unet" protocol=udp to-addresses=10.30.30.95 \ - to-ports=32000 -add action=dst-nat chain=dstnat dst-port=32000 protocol=tcp routing-mark=\ - To-VPN to-addresses=10.30.30.95 to-ports=32000 -add action=dst-nat chain=dstnat dst-port=32000 protocol=udp routing-mark=\ - To-VPN to-addresses=10.30.30.95 to-ports=32000 /ip firewall raw add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=accept chain=prerouting comment="Trusted DNS" disabled=yes \ + in-interface-list=WAN src-address-list=Trusted-DNS add action=add-dst-to-address-list address-list=NoVdsina \ address-list-timeout=none-dynamic chain=prerouting comment=\ extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ content=linux.duke.edu disabled=yes -add action=add-dst-to-address-list address-list=NoVdsina \ - address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ - content=vk.com -add action=add-dst-to-address-list address-list=NoVdsina \ - address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ - ok.ru -add action=add-dst-to-address-list address-list=Instagram \ - address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ - content=instagram.com -add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ - none-dynamic chain=prerouting comment=Twitter content=twimg.com -add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ - none-dynamic chain=prerouting content=x.com -add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ - none-dynamic chain=prerouting content=twitter.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting comment=YouTube content=youtube.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=googleapis.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=ggpht.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=youtu.be -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=ytimg.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=googlevideo.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=gstatic.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=googleusercontent.com -add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ - none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=youtube.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + googleapis.com disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=ggpht.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=youtu.be \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=ytimg.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + googlevideo.com disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=gstatic.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + googleusercontent.com disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + nhacmp3youtube.com disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ - content=rutube.ru -add action=add-dst-to-address-list address-list=NoVdsina \ - address-list-timeout=none-dynamic chain=prerouting comment=me.com \ - content=me.com + content=rutube.ru disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ - address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ - content=icloud.com -add action=add-dst-to-address-list address-list=facebook \ - address-list-timeout=none-dynamic chain=prerouting comment=facebook \ - content=fbcd.net -add action=add-dst-to-address-list address-list=facebook \ - address-list-timeout=none-dynamic chain=prerouting content=facebook.com + address-list-timeout=none-dynamic chain=prerouting comment="me.com raw" \ + content=me.com disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ - address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ - content=comp-lenta.ru + address-list-timeout=none-dynamic chain=prerouting comment=\ + "icloud.com raw" content=icloud.com disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ address-list-timeout=none-dynamic chain=prerouting comment=\ - smtp.mail.me.com content=smtp.mail.me.com log=yes + "smtp.mail.me.com raw" content=smtp.mail.me.com disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ - address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ - content=gov.ru + address-list-timeout=none-dynamic chain=prerouting comment=\ + "smtp.mail.me.com.akadns.net raw" content=smtp.mail.me.com.akadns.net \ + disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ address-list-timeout=none-dynamic chain=prerouting comment=\ - r78.fssp.gov.ru content=r78.fssp.gov.ru + "api.db-ip.com raw" content=api.db-ip.com disabled=yes add action=add-dst-to-address-list address-list=NoVdsina \ - address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ - content=api.db-ip.com -add action=add-dst-to-address-list address-list=Telegram \ address-list-timeout=none-dynamic chain=prerouting comment=\ - api.telegram.org content=api.telegram.org + esia.gosuslugi.ru content=esia.gosuslugi.ru disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gosuslugi.ru \ + content=gosuslugi.ru disabled=yes /ip firewall service-port set ftp disabled=yes set tftp disabled=yes @@ -5680,8 +3471,6 @@ set irc disabled=no set sip disabled=yes set pptp disabled=yes set rtsp disabled=no -/ip hotspot walled-garden -add server=*1 /ip ipsec settings set accounting=no /ip ipsec policy @@ -5692,22 +3481,17 @@ set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 set cache-administrator="" max-cache-size=none port=80,443 src-address=\ 0.0.0.0 /ip route -add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn -add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn -add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn -add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn -add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ - To-VPN scope=30 target-scope=10 -add disabled=yes distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ - routing-table=main scope=30 target-scope=10 +add check-gateway=ping disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\ + WG routing-table=To-VPN scope=30 target-scope=10 /ip service set ftp disabled=yes set telnet disabled=yes +set reverse-proxy disabled=yes set ssh address=10.30.30.0/24 port=2222 set winbox address=10.30.30.0/24 set api address=10.30.30.0/24 disabled=yes -set api-ssl address=10.30.30.0/24 -set www-ssl port=18443 +set api-ssl address=10.30.30.0/24 disabled=yes +set www-ssl certificate=Root-YE port=18443 set www address=10.30.30.0/24 disabled=yes port=18880 /ip service webserver set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ @@ -5720,81 +3504,30 @@ set forwarding-enabled=both publickey-authentication-options=verify-required \ set enabled=yes /ip upnp interfaces add interface=Bridge-LAN type=internal -add interface="ether1 - Unet" type=external -/ipv6 firewall address-list -add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 -add address=::1/128 comment="defconf: lo" list=bad_ipv6 -add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 -add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 -add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 -add address=100::/64 comment="defconf: discard only " list=bad_ipv6 -add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 -add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 -add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 -/ipv6 firewall filter -add action=add-src-to-address-list address-list=bad_ipv6 \ - address-list-timeout=none-dynamic chain=input comment=\ - "defconf: accept established,related,untracked" connection-state=\ - established,related,untracked in-interface=WG in-interface-list=WAN \ - src-address-list="" -add action=drop chain=input comment="defconf: drop invalid" connection-state=\ - invalid -add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ - icmpv6 -add action=accept chain=input comment="defconf: accept UDP traceroute" \ - dst-port=33434-33534 protocol=udp -add action=accept chain=input comment=\ - "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ - udp src-address=fe80::/10 -add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ - protocol=udp -add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ - ipsec-ah -add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ - ipsec-esp -add action=accept chain=input comment=\ - "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec -add action=drop chain=input comment=\ - "defconf: drop everything else not coming from LAN" in-interface-list=\ - !LAN -add action=accept chain=forward comment=\ - "defconf: accept established,related,untracked" connection-state=\ - established,related,untracked -add action=drop chain=forward comment="defconf: drop invalid" \ - connection-state=invalid -add action=drop chain=forward comment=\ - "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 -add action=drop chain=forward comment=\ - "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 -add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ - hop-limit=equal:1 protocol=icmpv6 -add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ - icmpv6 -add action=accept chain=forward comment="defconf: accept HIP" protocol=139 -add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ - 500,4500 protocol=udp -add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ - ipsec-ah -add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ - ipsec-esp -add action=accept chain=forward comment=\ - "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec -add action=drop chain=forward comment=\ - "defconf: drop everything else not coming from LAN" in-interface-list=\ - !LAN +add forced-ip=146.120.64.211 interface="ether1 - Unet" type=external +add forced-ip=89.110.101.17 interface=WG type=external +add interface=lo type=internal +/ipv6 dhcp-client +add add-default-route=yes disabled=yes interface=*F rapid-commit=no request=\ + info use-interface-duid=yes validate-server-duid=no +/ipv6 dhcp-server option sets +add name=domain-search-set options=domain-search-list +add name="=\"Client ID\"" options=HostName /ipv6 nd -set [ find default=yes ] advertise-dns=yes -/ppp secret -add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ - service=l2tp -/routing bfd configuration -add disabled=no -/snmp -set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ - src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ - 10.30.30.10 +set [ find default=yes ] advertise-dns=yes disabled=yes interface=Bridge-LAN \ + managed-address-configuration=yes other-configuration=yes pref64=::/64 +/ipv6 nd prefix +add autonomous=no disabled=yes interface=Bridge-LAN on-link=no prefix=none +/ipv6 nd prefix default +set dhcp6-pd-preferred=yes +/ipv6 nd proxy +add disabled=yes interface=lo +/ipv6 nd settings +set router-advertisement-route-distance=100 +/routing settings +set single-process=no /system clock -set time-zone-autodetect=no time-zone-name=Europe/Moscow +set time-zone-name=Europe/Moscow /system clock manual set time-zone=+03:00 /system identity @@ -5812,29 +3545,10 @@ add address=1.ru.pool.ntp.org add address=2.ru.pool.ntp.org add address=3.ru.pool.ntp.org add address=time.google.com disabled=yes +/system package update +set check-certificate=yes-without-crl /system scheduler -add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ - on-event=WU-add-to-list policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - start-date=2014-02-11 start-time=00:00:00 -add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ - on-event=BackupAndUpdate policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - start-date=2025-07-07 start-time=03:41:27 -add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ - DNS_Flush_Cache policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - start-date=2019-12-06 start-time=05:30:00 -add comment="Create mkdir function on startup" name=\ - create_mkdir_function_on_startup on-event=\ - "/system script run create_mkdir_function;" policy=read,write,policy,test \ - start-time=startup -add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ - name="Update Certificates CloudFlare Quad9" on-event=\ - "/system/script { run Update-Certificates; }" policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - start-date=2025-11-28 start-time=05:45:40 -add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ +add comment="Every Day Set Global Environment Variables" name=AM-SetGlobalEnv \ on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ start-time=startup @@ -5843,24 +3557,10 @@ add comment="Every Day Check For Update Scripts" interval=1d name=\ ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ start-time=startup -add comment="Every Day Check For Fake Bridges" interval=1d name=\ - mod/AM-IPbridge on-event="/system/script/run mod/AM-IPbridge;" policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - start-time=startup -add comment="Every Day Check For Renew Certificates" interval=1d name=\ - AM-CheckCerts on-event="/system/script/run AM-CheckCerts;" policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ +add comment="Update RKN DNS Looup" disabled=yes interval=20m name=\ + AM-RKN-dnsLookup on-event="/system/script { run AM-RKN-dnsLookup; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ start-time=startup -add comment="Auto-update Cloudflare Root CA for DoH" interval=2w name=\ - AM-DOHCert on-event="/import AM-DOHCert.rsc" policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - start-date=2026-04-15 start-time=03:00:00 -add comment=\ - "Every 7 Day Check For Update and Backup send notification to EMail." \ - interval=1w name=AM-Backup-UpdateEmail on-event=\ - "/system/script { run AM-Backup-UpdateEmail; }" policy=\ - ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ - start-date=2026-04-30 start-time=03:41:27 /system watchdog set watchdog-timer=no /tool e-mail @@ -5871,28 +3571,34 @@ set allowed-interface-list=LAN /tool mac-server mac-winbox set allowed-interface-list=LAN /tool netwatch -add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ - y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ - http-codes="" test-script="" type=simple up-script="" +add certificate=DigiCert-Global-Root-CA check-certificate=no comment="doh, doh\ + -url=https://security.cloudflare-dns.com/dns-query, notify, name=CloudFlar\ + e-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 http-codes="" \ + interval=10s name="CloudFlare-doh IPv4 1" port=443 test-script="" type=\ + https-get up-script="" add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ - port=443 test-script="" type=simple up-script="" -add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ - down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + name="CloudFlare-doh IPv4" port=443 test-script="" type=https-get \ up-script="" -add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ - Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ - 8.8.4.4 http-codes="" test-script="" type=simple up-script="" -add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ - host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" -add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ - -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ - test-script="" type=simple up-script="" +add comment="dns, notify, name=Google-DNS IPv4" disabled=yes dns-server=\ + 8.8.8.8 down-script="" host=dns.google http-codes="" name=\ + "Google-DNS IPv4" test-script="" type=dns up-script="" +add certificate=GTS-Root-R4 check-certificate=yes comment="doh-fallback, doh-u\ + rl=https://dns.google/dns-query, doh-cert=GTS Root R1, notify, name=Google\ + -DOH IPv4" disabled=yes dns-server=8.8.4.4 down-script="" host=dns.google \ + http-codes="" name="Google-DOH IPv4" port=443 record-type=NS src-address=\ + "" test-script="" type=dns up-script="" +add comment="dns-fallback, notify, name=Cuad9-DOH IPv4" disabled=yes \ + dns-server=9.9.9.9 down-script="" host=dns9.quad9.net http-codes="" \ + interval=10s name="Cuad9-DOH IPv4" src-address=146.120.64.211 \ + test-script="" timeout=800ms type=dns up-script="" +add certificate=DigiCert-Assured-ID-Root-CA comment="doh-fallback, doh-url=htt\ + ps://dns.quad9.net/dns-query, name=Cuad9-DOH IPv4" disabled=yes \ + down-script="" host=149.112.112.112 http-codes="" interval=10s name=\ + "Cuad9-DOH IPv4" port=443 test-script="" type=https-get up-script="" add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ - down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ - up-script="" -/tool sniffer -set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 + down-script="" host=91.192.189.2 http-codes="" interval=10s name=\ + ns1.unet.ws test-script="" type=simple up-script="" /user aaa set accounting=no