From b038c3f42722fc76fc7df417f86c09838020169b Mon Sep 17 00:00:00 2001 From: vados-dev Date: Tue, 3 Mar 2026 09:00:09 +0300 Subject: [PATCH] Backup for MikroMaster sucessfully creatd at Mar 03 09:00:09. --- .../20260303/20260303090003-Binary.backup | Bin 0 -> 290359 bytes .../20260303/20260303090003-Config.rsc | 3978 +++++++++++++++++ .../20260303/20260303090003-Diff-Config.rsc | 4 + 3 files changed, 3982 insertions(+) create mode 100644 MikroMaster/20260303/20260303090003-Binary.backup create mode 100644 MikroMaster/20260303/20260303090003-Config.rsc create mode 100644 MikroMaster/history/20260303/20260303090003-Diff-Config.rsc diff --git a/MikroMaster/20260303/20260303090003-Binary.backup b/MikroMaster/20260303/20260303090003-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..9d4bb92dabbc1a35bc1391f3c3733637b8722972 GIT binary patch literal 290359 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260303/20260303090003-Config.rsc b/MikroMaster/20260303/20260303090003-Config.rsc new file mode 100644 index 0000000..4447e66 --- /dev/null +++ b/MikroMaster/20260303/20260303090003-Config.rsc @@ -0,0 +1,3978 @@ +# 2026-03-03 09:00:03 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no 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 +/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: 5200/20-eCee/ac/P(20dBm), 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 +/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: 5200/20-eCee/ac/P(20dBm), 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 +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/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 +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +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 +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +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 hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/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 +/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 manager +set enabled=yes +/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 crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/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 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN 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=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=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +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 dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +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=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +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=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 +/ip dhcp-server network +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 +/ip dns static +add address=10.30.30.33 name=amster-nuc type=A +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru 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=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.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" 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" 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=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=10.30.30.20 name=garage type=A +/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 +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +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=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 +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +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=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 +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +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 +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 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=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 +/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 +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 +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 +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" \ + 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 +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=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 src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + 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 +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 +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 +/ip firewall mangle +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 \ + 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="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 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=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat 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="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 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +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=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 +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 +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 +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 +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +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 +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=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +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 +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +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=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet 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 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=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +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 +/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 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +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 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="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" 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 +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/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\ + \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\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)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\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:log info (\"1: \$Buffer\"); \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: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\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\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\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\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\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\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\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\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=\"\ + \";\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\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\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\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\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\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 dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \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## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\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:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\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 :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\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\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \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@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +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 GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\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:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\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## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\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 forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\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:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \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# :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\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=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \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\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \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 \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) 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 }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$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 :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\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:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \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\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\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 \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\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 :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\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 :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 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 :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\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 Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \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 (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) 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 \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint 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 \$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 :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 :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\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 :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \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\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\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}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \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\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$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\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \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}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \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 :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \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 :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 :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\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 :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\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 /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint 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 :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint 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 :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \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 :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \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\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \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 :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 \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\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\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \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 :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \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 :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\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:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\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\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \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 :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \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:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \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 :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \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 :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 :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 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\ + \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 \$RmDir \$DirName;\r\ + \n :return false;\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 :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\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 } 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 }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \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:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + 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 on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\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=AM-SshKeysImport \ + 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\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} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +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 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 \ + 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-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 +/user aaa +set accounting=no diff --git a/MikroMaster/history/20260303/20260303090003-Diff-Config.rsc b/MikroMaster/history/20260303/20260303090003-Diff-Config.rsc new file mode 100644 index 0000000..d5dcad3 --- /dev/null +++ b/MikroMaster/history/20260303/20260303090003-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-03 09:00:03 by RouterOS 7.21.2 +--- +> # 2026-03-03 08:40:04 by RouterOS 7.21.2 -- 2.52.0