From ccee0140eb4fe0eb11d50f83e9f873e6b496f75d Mon Sep 17 00:00:00 2001 From: vados-dev <192440777+vados-dev@users.noreply.github.com> Date: Thu, 12 Mar 2026 06:43:34 +0300 Subject: [PATCH] Backup for MikroMaster sucessfully creatd at Mar 12 06:43:34. --- .../20260312/20260312064326-Binary.backup | Bin 0 -> 290672 bytes .../20260312/20260312064326-Config.rsc | 3987 +++++++++++++++++ .../20260312/20260312064326-Diff-Config.rsc | 30 + 3 files changed, 4017 insertions(+) create mode 100644 MikroMaster/20260312/20260312064326-Binary.backup create mode 100644 MikroMaster/20260312/20260312064326-Config.rsc create mode 100644 MikroMaster/history/20260312/20260312064326-Diff-Config.rsc diff --git a/MikroMaster/20260312/20260312064326-Binary.backup b/MikroMaster/20260312/20260312064326-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d49dce372deb388068db29f89dd8ea23efb32075 GIT binary patch literal 290672 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ǎuw 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 literal 0 HcmV?d00001 diff --git a/MikroMaster/20260312/20260312064326-Config.rsc b/MikroMaster/20260312/20260312064326-Config.rsc new file mode 100644 index 0000000..e3fc5a8 --- /dev/null +++ b/MikroMaster/20260312/20260312064326-Config.rsc @@ -0,0 +1,3987 @@ +# 2026-03-12 06:43:27 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# Git commit id & info, expected configuration version\r\ + \n:global CommitId \"main/80/71f092a6\";\r\ + \n:global CommitTAG \"unknown\";\r\ + \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ + r: root, in 14:51:02 09.03.2026.\";\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global SumsDirAndFileName \"tmp/checksums.json\";\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 SumsDirAndFileName;\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 . \$SumsDirAndFileName . \$GlobalScr\ + iptsUrlSuffix);\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/20260312/20260312064326-Diff-Config.rsc b/MikroMaster/history/20260312/20260312064326-Diff-Config.rsc new file mode 100644 index 0000000..dab45e8 --- /dev/null +++ b/MikroMaster/history/20260312/20260312064326-Diff-Config.rsc @@ -0,0 +1,30 @@ +1c1 +< # 2026-03-12 06:43:27 by RouterOS 7.21.2 +--- +> # 2026-03-03 09:00:03 by RouterOS 7.21.2 +2006,2011d2005 +< \n# Git commit id & info, expected configuration version\r\ +< \n:global CommitId \"main/80/71f092a6\";\r\ +< \n:global CommitTAG \"unknown\";\r\ +< \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ +< r: root, in 14:51:02 09.03.2026.\";\r\ +< \n\r\ +2015,2016d2008 +< \n:global SumsDirAndFileName \"tmp/checksums.json\";\r\ +< \n\r\ +2686d2677 +< \n :global SumsDirAndFileName;\r\ +2713c2704 +< \n\r\ +--- +> \n \r\ +2717c2708 +< \n\r\ +--- +> \n \r\ +2721,2722c2712,2713 +< \n :local Url (\$GlobalScriptsUrl . \$SumsDirAndFileName . \$GlobalScr\ +< iptsUrlSuffix);\r\ +--- +> \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ +> tsUrlSuffix);\r\ -- 2.52.0