From bfce7a642f2f82644a50f8789aabd8ccfeaef2b3 Mon Sep 17 00:00:00 2001 From: vados-dev Date: Sun, 28 Jun 2026 12:41:22 +0300 Subject: [PATCH] Backup for MikroGig created successfully at Jun 28 12:41:22. --- .../20260628/20260628124118-Binary.backup | Bin 0 -> 177026 bytes MikroGig/20260628/20260628124118-Config.rsc | 2774 +++++++++++++ .../20260628/20260628124118-Diff-Config.rsc | 8 + .../20260628/20260628104001-Config.rsc | 3692 +++++++++++++++++ 4 files changed, 6474 insertions(+) create mode 100644 MikroGig/20260628/20260628124118-Binary.backup create mode 100644 MikroGig/20260628/20260628124118-Config.rsc create mode 100644 MikroGig/history/20260628/20260628124118-Diff-Config.rsc create mode 100644 MikroMaster/20260628/20260628104001-Config.rsc diff --git a/MikroGig/20260628/20260628124118-Binary.backup b/MikroGig/20260628/20260628124118-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ca1e72cc38186a73cad819497a22771f17c2740e GIT binary patch literal 177026 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[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

MPE#*u`o1< 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 literal 0 HcmV?d00001 diff --git a/MikroGig/20260628/20260628124118-Config.rsc b/MikroGig/20260628/20260628124118-Config.rsc new file mode 100644 index 0000000..41ce106 --- /dev/null +++ b/MikroGig/20260628/20260628124118-Config.rsc @@ -0,0 +1,2774 @@ +# 2026-06-28 11:41:19 by RouterOS 7.23.1 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=18:FD:74:6E:58:14 auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +add name=br-awg +/interface wireless +# managed by CAPsMAN +set [ find default-name=wlan2 ] country=belarus mode=ap-bridge name=wlan1 \ + ssid=vados wps-mode=disabled +# managed by CAPsMAN +set [ find default-name=wlan1 ] country=belarus mode=ap-bridge name=wlan2 \ + ssid=vados5g wps-mode=disabled +/interface ethernet +set [ find default-name=ether1 ] mac-address=48:8F:5A:8E:1A:BC +/interface veth +add address=10.9.9.2/24 container-mac-address=78:60:DB:55:90:E3 dhcp=no \ + gateway=10.9.9.1 gateway6="" mac-address=78:60:DB:55:90:E2 name=veth-awg +/disk +add mount-point-template="[tmpfs]" slot=ram tmpfs-max-size=64 type=tmpfs +/interface list +add name=WAN +add name=LAN +add exclude=LAN include=WAN name=Internet +/interface wireless security-profiles +set [ find default=yes ] supplicant-identity=MikroTik +/routing table +add disabled=no fib name=r_to_vpn +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/system script +add comment="Script for setup routeros script system" \ + dont-require-permissions=no name=AM-setup owner=AM-setup policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-setup\r\ + \n# Script comment: Script for setup routeros script system\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:global NewScript \"script_name\"; \r\ + \n#:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n#/system/script/add name=\$NewScript owner=\$NewScript source=([/tool/fe\ + tch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptAdd . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n#:global NewScript (a);\r\ + \n#:global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n#\r\ + \n# For run from terminal:\r\ + \n#/system/script/add name=AM-setup owner=AM-Setup source=([/tool/fetch ch\ + eck-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" outp\ + ut=user as-value ]->\"data\");\r\ + \n#\r\ + \n\r\ + \n:global ScriptUpdatesCRLF \"LF\";\r\ + \n#:if (\$ScriptUpdatesCRLF != false) do={\r\ + \n# :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vad\ + os\" ] do={\r\ + \n# if (\$ScriptUpdatesCRLF = true) do={\r\ + \n# /system/script/set source=[ :tocrlf [ get \$Script source ] ] \$S\ + cript;\r\ + \n# } else={\r\ + \n# /system/script/set source=[ :tolf [ get \$Script source ] ] \$Scr\ + ipt;\r\ + \n# }\r\ + \n# }\r\ + \n#}\r\ + \n\r\ + \n# /import verbose=no \$ScriptName\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global SetupScript [ :jobname ];\r\ + \n:global RemoveMe true;\r\ + \n:global RunOnce (a);\r\ + \n:global InitSetup true;\r\ + \n:global tmpfs false;\r\ + \n\r\ + \n{\r\ + \n :local RmMe [:tobool \$1];\r\ + \n\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global SetupScript;\r\ + \n :global RemoveMe;\r\ + \n :global InitSetup;\r\ + \n :global tmpfs;\r\ + \n\r\ + \n :local UrlSuffix \$Identity;\r\ + \n :local UrlDir \"certs/\";\r\ + \n :local CertUrl (\$GlobalScriptsUrl . \$UrlDir . \$UrlSuffix .\"/\"); \ + \r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :if (\$SetupScript = false) do={\r\ + \n :global SetupScript \"AM-setup\";\r\ + \n }\r\ + \n :if (\$RemoveMe != false) do={\r\ + \n :set RemoveMe true;\r\ + \n }\r\ + \n\r\ + \n :log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n \r\ + \n\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 /tool/fetch (\$CertUrl . \$CertFileName) dst-path=\$CertFileName\ + \_as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n /certificate/set name=\"Root-YE\" [ find where common-name=\"Roo\ + t YE\" ];\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n\r\ + \n:local MkTmpfs do={\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n :log info (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :log info (\"Try to removing directory 'tmpfs'.\");\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/remove tmpfs;\r\ + \n :return true;\r\ + \n } delay=100ms max=10;\r\ + \n } on-error={ }\r\ + \n# \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource/g\ + et total-memory ] / 3);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get tmpfs;\r\ + \n :return true;\r\ + \n } delay=222ms max=10;\r\ + \n } on-error={ }\r\ + \n } do={\r\ + \n :log warning (\"Creating disk of type tmpfs failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n# :return true;\r\ + \n}\r\ + \n:if (\$tmpfs = true) do={\r\ + \n :put \"Tmpfs variable is true. Checking for tmpfs/scripts directory...\ + \";\r\ + \n :if ([/file find name=\"tmpfs/scripts\"] != \"\") do={\r\ + \n :log info (\$0 . \"Directory tmpfs/scripts exsist.\");\r\ + \n :return \$true;\r\ + \n } else={\r\ + \n :log warning (\$0 . \"Directory tmpfs/scripts does't exsist.\");\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :log error (\$0 . \"Directory tmpfs is not created!\");\r\ + \n :return false;\r\ + \n } else={\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=/tmpfs/scripts;\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get /tmpfs/scripts;\r\ + \n :return true;\r\ + \n } delay=100ms max=10;\r\ + \n } on-error={ }\r\ + \n } do={\r\ + \n :log warning (\$0 . \"Making directory 'scripts' failed: \" . \$\ + Err);\r\ + \n :return false;\r\ + \n }\r\ + \n# :return true;\r\ + \n# [ /file/get \$FileName ]\r\ + \n }\r\ + \n# :log error (\$0 . \"Directory tmpfs/scripts does not exsist. Remove\ + \_global variable tmpfs!\");\r\ + \n# :global tmpfs (a);\r\ + \n# return false;\r\ + \n }\r\ + \n}\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n \r\ + \n /system/script run \$Script;\r\ + \n :delay 2s;\r\ + \n };\r\ + \n\r\ + \n :local Script \"mod/AM-Certs-By-Ident\";\r\ + \n \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/fetch \ + check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \".\ + rsc\") output=user as-value ]->\"data\");\r\ + \n /system/script run \$Script;\r\ + \n :global tmpAddCerts;\r\ + \n :while ([ \$tmpAddCerts ] = true) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n :delay 1s;\r\ + \n :put \"Removing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\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 :if (\$RemoveMe = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :local OnEvent (\":delay 30s;\\n\" . \"/system/script/remove [ find \ + where name=\\\"\$SetupScript\\\" ];\\n\" . \\\r\ + \n \":delay 2s;\\n\" . \"/system/scheduler/remove [ find where name=\\\ + \"_RemoveSetup\\\" ];\\n\" . \\\r\ + \n \":delay 2s;\\n\" . \":global RemoveMe (a);\\n\");\r\ + \n :local Comment \"_RemoveSetup tmp scheduler for remove setup script.\ + \";\r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-\ + time=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$0 . \"\\nI've done everything, and now I'm tired..\ + . I'm leaving.\\nThere will be an error below, this is normal.\");\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :put \"Normal removing temporary global environment variables.\";\ + \r\ + \n :global SetupScript (a);\r\ + \n :global InitSetup (a);\r\ + \n :global RemoveMe (a);\r\ + \n } on-error={\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$0 . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n}\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global GlobalConfReady false;\r\ + \n#\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in AM-Init-Script or AM-setup scripts\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix (a);\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n: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\";\r\ + \n#: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:global CertRenewUrl (\$GlobalScriptsUrl . \"certs/\" . \$Identity . \"/\ + \");\r\ + \n:global CertRenewTime 2w;\r\ + \n:global CertRenewPass (a); #{\r\ + \n# \"\";\r\ + \n# \"v3ry-s3cr3t\";\r\ + \n# \"4n0th3r-s3cr3t\";\r\ + \n#};\r\ + \n:global CertWarnTime 1w;\r\ + \n:global CertIssuedExportPass (a); # {\r\ + \n# \"\";\r\ + \n# \"cert1-cn\"=\"v3ry-s3cr3t\";\r\ + \n# \"cert2-cn\"=\"4n0th3r-s3cr3t\";\r\ + \n#};\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global 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# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\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/702/b3f31455\";\r\ + \n:global CommitTAG \"unknown\";\r\ + \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ + r: root, in 07:15:04 28.06.2026.\";\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 140;\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 MiniDateTimeStamp;\r\ + \n:global MicroDateTimeStamp;\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 CharacterMultiply;\r\ + \n:global CharacterReplace;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n\r\ + \n:global CommitBrief;\r\ + \n\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global GetRandom20CharHex;\r\ + \n:global GetRandomNumber;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \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 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 ExitError;\r\ + \n:global ExitOnError;\r\ + \n\r\ + \n:global FetchHugeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global FileExists;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \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 updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n :global currentUpdateChannel;\r\ + \n :global ROsVerAvail;\r\ + \n :global arrDeviceInfo;\r\ + \n :log info (\$0 . \" \\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if ([ :len \$updateChannel ] > 0 && \$CurrentChannel != \$updateChann\ + el) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n :log info (\$0 . \" Set updates channel to: \$updateChannel\");\r\ + \n }\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel [ :tostr (\$Update->\"channel\") ];\r\ + \n :set currentUpdateChannel \$Channel;\r\ + \n :log info (\$0 . \" Update Channel: \" . \$Channel . \".\");\r\ + \n :local StatusPkg \"undefined\";\r\ + \n :log info (\$0 . \" Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n :log info (\$0 . \" \\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n :set ROsVerAvail [ :tostr [ /system/package/update/get latest-version \ + ] ];\r\ + \n :log info (\$0 . \" \\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n :log info (\$0 . \" \\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([ :typeof \$arrDeviceInfo ] != \"array\") do={\r\ + \n :set arrDeviceInfo [:toarray \$arrDeviceInfo];\r\ + \n }\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [ /system/pac\ + kage/update/get ]} delay=500ms max=5 on-error={:log error (\"Error\")};\r\ + \n :return true;\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitCheckUpdates do={\r\ + \n :global IsCheckUpdates;\r\ + \n :global PkgUpdStatus;\r\ + \n :global currentUpdateChannel;\r\ + \n :global ROsVerAvail;\r\ + \n :global arrDeviceInfo;\r\ + \n :local Status \"\";\r\ + \n :local Update;\r\ + \n :local WaitCount 0;\r\ + \n :if ([ \$IsCheckUpdates true ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n :set Status [ :tostr [ /system/package/update/get status ] ];\r\ + \n :while ((\$Status = \"\" || \$Status = \"finding out latest version...\ + \") && \$WaitCount < 60) do={\r\ + \n :delay 1s;\r\ + \n :set WaitCount (\$WaitCount + 1);\r\ + \n :set Status [ :tostr [ /system/package/update/get status ] ];\r\ + \n }\r\ + \n :set Update [ /system/package/update/get ];\r\ + \n :set currentUpdateChannel [ :tostr (\$Update->\"channel\") ];\r\ + \n :set ROsVerAvail [ :tostr (\$Update->\"latest-version\") ];\r\ + \n :if ((\$Update->\"status\") = \"New version is available\") do={\r\ + \n :set PkgUpdStatus true;\r\ + \n } else={\r\ + \n :set PkgUpdStatus false;\r\ + \n }\r\ + \n :if ([ :typeof \$arrDeviceInfo ] != \"array\") do={\r\ + \n :set arrDeviceInfo [:toarray \$arrDeviceInfo];\r\ + \n }\r\ + \n :set (\$arrDeviceInfo->\"devUpdates\") \$Update;\r\ + \n :if (\$Status = \"\" || \$Status = \"finding out latest version...\") \ + do={\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\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 :global arrDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devBuildTime;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global currentUpdateChannel;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :local DeviceInfo;\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local VersionString [ :tostr (\$Resource->\"version\") ];\r\ + \n :local ChannelStart [ :find \$VersionString \" (\" ];\r\ + \n :local RouterBoard;\r\ + \n :local IsRouterBoard false;\r\ + \n :local RunningMode \"\";\r\ + \n\r\ + \n :set devCurArch [ :tostr (\$Resource->\"architecture-name\") ];\r\ + \n :set devBuildTime [ :tostr (\$Resource->\"build-time\") ];\r\ + \n :set runningChannelVersion \$VersionString;\r\ + \n :set runningVersion \$VersionString;\r\ + \n :set runningChannel \"\";\r\ + \n\r\ + \n :if ([ :typeof \$ChannelStart ] = \"num\" && \$ChannelStart >= 0) do=\ + {\r\ + \n :set runningVersion [ :pick \$VersionString 0 \$ChannelStart ];\r\ + \n :local ChannelRest [ :pick \$VersionString (\$ChannelStart + 2) [ :\ + len \$VersionString ] ];\r\ + \n :local ChannelEnd [ :find \$ChannelRest \")\" ];\r\ + \n :if ([ :typeof \$ChannelEnd ] = \"num\" && \$ChannelEnd >= 0) do={\ + \r\ + \n :set runningChannel [ :pick \$ChannelRest 0 \$ChannelEnd ];\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :do {\r\ + \n :set RouterBoard [[ :parse \"/system/routerboard/get\" ]];\r\ + \n# :set RouterBoard [ /system/routerboard/get ];\r\ + \n :if ((\$RouterBoard->\"routerboard\") = true) do={\r\ + \n :set IsRouterBoard true;\r\ + \n }\r\ + \n } on-error={}\r\ + \n }\r\ + \n\r\ + \n :do {\r\ + \n :set RunningMode [ /system/device-mode/get mode ];\r\ + \n } on-error={\r\ + \n :do {\r\ + \n :set RunningMode [ /system/device-mode/get running ];\r\ + \n } on-error={\r\ + \n :set RunningMode \"\";\r\ + \n }\r\ + \n }\r\ + \n :set devRunning \$RunningMode;\r\ + \n\r\ + \n :if (\$IsRouterBoard = true) do={\r\ + \n :set devModel [ :tostr (\$RouterBoard->\"model\") ];\r\ + \n :set devRbRevision [ :tostr (\$RouterBoard->\"revision\") ];\r\ + \n :set devRbSerialNumber [ :tostr (\$RouterBoard->\"serial-number\") \ + ];\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n :set devRbRevision \"\";\r\ + \n :set devRbSerialNumber \"\";\r\ + \n }\r\ + \n\r\ + \n :set currentUpdateChannel [ :tostr (\$Update->\"channel\") ];\r\ + \n :set ROsVerAvail [ :tostr (\$Update->\"latest-version\") ];\r\ + \n\r\ + \n :set (\$DeviceInfo->\"board-name\") \$devBoardName;\r\ + \n :set (\$DeviceInfo->\"architecture-name\") \$devCurArch;\r\ + \n :set (\$DeviceInfo->\"model\") \$devModel;\r\ + \n :set (\$DeviceInfo->\"revision\") \$devRbRevision;\r\ + \n :set (\$DeviceInfo->\"serial-number\") \$devRbSerialNumber;\r\ + \n :set (\$DeviceInfo->\"running-mode\") \$devRunning;\r\ + \n :set (\$DeviceInfo->\"build-time\") \$devBuildTime;\r\ + \n :set (\$DeviceInfo->\"running-channel-version\") \$runningChannelVers\ + ion;\r\ + \n :set (\$DeviceInfo->\"running-version\") \$runningVersion;\r\ + \n :set (\$DeviceInfo->\"running-channel\") \$runningChannel;\r\ + \n :set (\$DeviceInfo->\"routerboard\") \$IsRouterBoard;\r\ + \n :set (\$DeviceInfo->\"current-firmware\") [ :tostr (\$RouterBoard->\"\ + current-firmware\") ];\r\ + \n :set (\$DeviceInfo->\"upgrade-firmware\") [ :tostr (\$RouterBoard->\"\ + upgrade-firmware\") ];\r\ + \n :set (\$DeviceInfo->\"package-channel\") \$currentUpdateChannel;\r\ + \n :set (\$DeviceInfo->\"installed-version\") [ :tostr (\$Update->\"inst\ + alled-version\") ];\r\ + \n :set (\$DeviceInfo->\"latest-version\") \$ROsVerAvail;\r\ + \n :set (\$DeviceInfo->\"update-status\") [ :tostr (\$Update->\"status\"\ + ) ];\r\ + \n\r\ + \n :set arrDeviceInfo \$DeviceInfo;\r\ + \n :return \$DeviceInfo;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :global CommitBrief;\r\ + \n\r\ + \n :local License [/system/license/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Info [ \$GetArrDeviceInfo ];\r\ + \n\r\ + \n :if ([ :typeof \$Info ] != \"array\") do={\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :return ( \\\r\ + \n [ \$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\" (\$Info->\"board-name\") ] . \"\\n\" . \ + \\\r\ + \n [ \$FormatLine \" Arch\" (\$Info->\"architecture-name\") ] . \"\\\ + n\" . \\\r\ + \n [ \$FormatLine \" Model\" (\$Info->\"model\") ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"revision\") ] > 0) \\\r\ + \n (\" \" . (\$Info->\"revision\")) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"serial-number\") ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial\" (\$Info->\"serial-number\") ] . \"\ + \\n\") ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License\" (\"level \" . (\$License->\"nlevel\ + \")) ] . \"\\n\") ] . \\\r\ + \n \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \" Channel\" (\$Info->\"package-channel\") ] . \"\ + \\n\" . \\\r\ + \n [ \$FormatLine \" Installed\" (\$Info->\"installed-version\") ] .\ + \_\"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"running-channel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" Running\" ((\$Info->\"running-version\") . \ + \" (\" . (\$Info->\"running-channel\") . \")\") ] . \"\\n\") \\\r\ + \n ([ \$FormatLine \" Running\" (\$Info->\"running-version\") ] . \ + \"\\n\") ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"latest-version\") ] > 0 && \\\r\ + \n (\$Info->\"installed-version\") != (\$Info->\"latest-version\"))\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Info->\"latest-version\") ] .\ + \_\"\\n\") ] . \\\r\ + \n [ \$IfThenElse ((\$Info->\"routerboard\") = true && \\\r\ + \n (\$Info->\"current-firmware\") != (\$Info->\"upgrade-firmware\")\ + ) \\\r\ + \n ([ \$FormatLine \" Firmware\" ((\$Info->\"current-firmware\") .\ + \_\" -> \" . (\$Info->\"upgrade-firmware\")) ] . \"\\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\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:set GetRandom20CharHex do={:global EitherOr; :return [ :rndstr length=[\ + \_\$EitherOr [ :tonum \$1 ] 20 ] from=\"0123456789abcdef\" ]; }\r\ + \n:set GetRandomNumber do={:global EitherOr; :return [ :rndnum from=0 to=[\ + \_\$EitherOr [ :tonum \$1 ] 4294967295 ] ]; }\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \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 CommitBrief do={\r\ + \n :global CommitId;\r\ + \n :global CommitInfo;\r\ + \n :if (\$CommitId = \"unknown\") do={\r\ + \n :return \"unknown\";\r\ + \n }\r\ + \n :return (\$CommitInfo . \"/\" . [ :pick \$CommitId 0 8 ]);\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:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n\r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n :local JobName [ :jobname ];\r\ + \n\r\ + \n :do {\r\ + \n :log debug (\$0 . \" Trying to detect public IP using default serv\ + ice: \" . \$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={:log error (\$JobName . \" Failed to \ + detect public IP using default service: \" . \$Url . \".\")}\r\ + \n } on-error={\r\ + \n :log error (\$0 . \" Failed to detect public IP using default serv\ + ice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n :log debug (\$0 . \" Trying to detect public IP using fallback ser\ + vice: \" . \$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={:log error (\$JobName . \" Failed to\ + \_detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :local IpLen ([ :len \$PubIpAddr ] -1);\r\ + \n :if (\$PubIpAddr = false) do={:set PubIpAddr \"not-detected\"} else=\ + {:set PubIpAddr [:pick \$PubIpAddr 0 \$IpLen]}\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\r\ + \n :global CertificateDownload;\r\ + \n :global ParseKeyValueStore;\r\ + \n\r\ + \n :if ([ :len \$UseFor ] = 0) do={\r\ + \n :log warning (\$0 . \"The intended use is undefined!\");\r\ + \n :set UseFor \"undefined\";\r\ + \n }\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n :log warning (\$0 . \"This system has low free flash space but \" . \ + \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n :log 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 :log info (\$0 . \"Certificate with CommonName '\" . \$CommonName . \ + \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n :log 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 :log info (\$0 . \"Certificate chain for '\" . \$CommonName . \"' \ + is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \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 ScriptUpdatesBaseUrl;\r\ + \n :global ScriptUpdatesUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :log info (\$0 . \"Downloading and importing certificate with \" . \\\ + \r\ + \n \"CommonName '\" . \$CommonName . \"'.\");\r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl mode=https http-header\ + -field=({ [ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$ScriptUpdatesBaseUrl . \"certs/\" . \$FileName . \$ScriptUpdate\ + sUrlSuffix) \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n :log warning (\$0 . \" Failed downloading certificate with CommonNam\ + e '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0 && \\\r\ + \n !(((\$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=\"ISRG\ + \_Root X1\" ] ] > 0)) do={\r\ + \n :log error (\$0 . \" Required certificate is not available.\");\ + \r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl mode=https http-head\ + er-field=({ [ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n url=\"https://mkcert.org/generate/\" http-data=[ :serialize to=jso\ + n ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n :log error (\$0 . \" Failed downloading certificate with CommonNam\ + e '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n :log warning (\$0 . \" Certificate with CommonName '\" . \$CommonNam\ + e . \"' 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 :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 :log 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 FileExists do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local Type [ :tostr \$2 ];\r\ + \n :global FileGet;\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={ :return false; }\r\ + \n :if ([ :len (\$FileVal->\"size\") ] = 0) do={ :return false; }\r\ + \n :if ([ :len \$Type ] = 0 || \$FileVal->\"type\" = \$Type) do={ :return\ + \_true; }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \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 CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={ :set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]; }\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={ :set Path [ :pick \$Path 1 [ :le\ + n \$Path ] ]; }\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={ :set Path [ \ + :pick \$Path 0 ([ :len \$Path ] - 1) ]; }\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \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 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\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 :if (\$ExitOK = \"false\") do={\r\ + \n :log 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 ExitOnError do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :local Error [ :tostr \$2 ];\r\ + \n :global IfThenElse;\r\ + \n :log error (\$Name . \" \" . [ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\ + \\\$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with erro\ + r\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \$E\ + rror) \".\" ]);\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n :local mikro [ :tobool \$1 ];\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \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 :local Return;\r\ + \n :if (\$mikro = true) do={\r\ + \n :set Return ([:pick \$yyyy 2 4] . [:pick \$dd 0 1] . [:pick \$HH 0\ + \_1] . [:pick \$mm 3 4] . [:pick \$ss 6 7]);\r\ + \n } else={\r\ + \n :set Return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\ + \r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \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={\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileVal false;\r\ + \n :do {\r\ + \n :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 :log debug (\$0 . \" Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\r\ + \n :log debug (\$0 . \" ... which does not exist.\");\r\ + \n :return true;\r\ + \n };\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\r\ + \n :log error (\$0 . \" Directory '\" . \$DirName . \"' is not a direct\ + ory.\");\r\ + \n :return false;\r\ + \n };\r\ + \n :onerror Err {\r\ + \n /file/remove \$DirName;\r\ + \n } do={\r\ + \n :log error (\$0 . \" Removing directory '\" . \$DirName . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n };\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :log debug (\$0 . \" Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\r\ + \n :log debug (\$0 . \" ... which does not exist.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n :log error (\$0 . \" File '\" . \$FileName . \"' is not a file.\");\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\r\ + \n :log error (\$0 . \" Removing file '\" . \$FileName . \"' failed: \"\ + \_. \$Err); :return false;\r\ + \n }\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\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 :log info (\$0 . \" The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :log info (\$0 . \" Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n :log 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 :log debug (\$0 . \" Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n :log 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 :log 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 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 VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n :log error (\$0 . \" No valid RouterOS version: \" . \$Required);\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n :log warning (\$0 . \" This \" . [ \$IfThenElse ([ :pick \$Caller \ + 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \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\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 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 :log error (\$0 . \" A script named '\" . \$Script . \"' does not ex\ + ist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \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 :log error (\$0 . \" More tickets than running scripts '\" . \$Scrip\ + t . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \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\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global 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 :log warning (\$0 . \"No symbol available for name '\" . \$Name . \"\ + '!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \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\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\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \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:set FetchHugeFiles do={\r\ + \n :local ScriptName [ :tostr \$1 ];\r\ + \n :local Url [ :tostr \$2 ];\r\ + \n :local CheckCert [ :tostr \$3 ];\r\ + \n\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \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\r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName \ + \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue;\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$Url . \" - \"\ + \_. \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$Url . \" did\ + \_not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \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:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global CommitBrief;\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (\" . \$GlobalScriptsUrl . \"; \" . [ \$\ + CommitBrief ] . \")\");\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global CommitId;\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 CommitIdBefore \$CommitId;\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={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nNews and\ + \_changes are not available.\");\r\ + \n\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={ :set GlobalConfChanges; \ + } else={ :global GlobalConfChanges (a); }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={ :set GlobalConfMigrati\ + on; } else={ :global GlobalConfMigration (a); }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# load modules\r\ + \n:foreach Script in=[ /system/script/find where name ~ \"^(global-functio\ + ns\\\\.d|mod)/.\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :if ([ \$ValidateSyntax (\$ScriptVal->\"source\") ] = true) do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n \$LogPrint error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \"' f\ + ailed to run: \" . \$Err);\r\ + \n }\r\ + \n } else={\r\ + \n \$LogPrint error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \"' fai\ + led syntax validation, skipping.\");\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 \"Every Day Set Global Environment Variables\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + 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: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:log warning (\"This script \$ScriptName Loaded \" . \\\r\ + \n [ \$IfThenElse (\$CommitId != \"unknown\") ([ \$CommitBrief ] . \" \ + \") ] . \\\r\ + \n \"on \" . \$devBoardName . \"\\nRouterOS: \" . \$devCurVersion . \"\ + \\nArchitecture: \" . \$devCurArch . \"\\nIdentity: \" . \$Identity);\r\ + \n # signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n\r\ + \n:log info (\$0 . \"Global configs ready!\");\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n}\r\ + \n" +add comment="Download custom Certificates By Routers Identity " \ + dont-require-permissions=no name=mod/AM-Certs-By-Ident owner=\ + mod/AM-Certs-By-Ident policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-Certs-By-Ident\r\ + \n# Script comment: Download custom Certificates By Routers Identity \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n#:local ScriptName [ :jobname ];\r\ + \n#\r\ + \n# CloudFlare\r\ + \n#/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalR\ + ootCA.crt.pem;\r\ + \n#/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\ + \"\";\r\ + \n#/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobal\ + G2TLSRSASHA2562020CA1-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/DigiCertGloba\ + lG3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n#/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt\ + .pem passphrase=\"\";\r\ + \n:global tmpAddCerts true; \r\ + \n\r\ + \n:global GlobalScriptsUrl;\r\ + \n:local UrlSuffix [/system/identity/get name];\r\ + \n:local UrlDir \"certs/\";\r\ + \n:local CertUrl (\$GlobalScriptsUrl . \$UrlDir . \$UrlSuffix .\"/\");\r\ + \n\r\ + \n:log error \$CertUrl;\r\ + \n\r\ + \n:local CertName \"DigiCert-Global-Root-CA.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Global-Root-CA\" [ find where common-na\ + me=\"DigiCert Global Root CA\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Assured-ID-Root-CA.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Assured-ID-Root-CA\" [ find where commo\ + n-name=\"DigiCert Assured ID Root CA\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Assured-ID-Root-G2.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Assured-ID-Root-G2\" [ find where commo\ + n-name=\"DigiCert Assured ID Root G3\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Assured-ID-Root-G3.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Assured-ID-Root-G3\" [ find where commo\ + n-name=\"DigiCert Assured ID Root G3\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Global-G2-TLS-RSA-SHA256-2020-CA1.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Global-G2-TLS-RSA-SHA256-2020-CA1\" [ f\ + ind where common-name=\"DigiCert Global G2 TLS RSA SHA256 2020 CA1\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Global-G3-TLS-ECC-SHA384-2020-CA1.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Global-G3-TLS-ECC-SHA384-2020-CA1\" [ f\ + ind where common-name=\"DigiCert Global G3 TLS ECC SHA384 2020 CA1\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Global-Root-G2.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Global-Root-G2\" [ find where common-na\ + me=\"DigiCert Global Root G2\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Global-Root-G3.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Global-Root-G3\" [ find where common-na\ + me=\"DigiCert Global Root G3\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-TLS-ECC-P384-Root-G5.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-TLS-ECC-P384-Root-G5\" [ find where com\ + mon-name=\"DigiCert TLS ECC P384 Root G5\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-TLS-RSA4096-Root-G5.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-TLS-RSA4096-Root-G5\" [ find where comm\ + on-name=\"DigiCert TLS RSA4096 Root G5\" ];\r\ + \n\r\ + \n:set CertName \"DigiCert-Trusted-Root-G4.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"DigiCert-Trusted-Root-G4\" [ find where common-n\ + ame=\"DigiCert Trusted Root G4\" ];\r\ + \n\r\ + \n:set CertName \"GTS-Root-R4.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"GTS-Root-R4\" [ find where common-name=\"GTS Roo\ + t R4\" ];\r\ + \n\r\ + \n:set CertName \"Go-Daddy-Root-Certificate-Authority-G2.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"Go-Daddy-Root-Certificate-Authority-G2\" [ find \ + where common-name=\"Go Daddy Root Certificate Authority - G2\" ];\r\ + \n\r\ + \n:set CertName \"ISRG-Root-X1.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"ISRG-Root-X1\" [ find where common-name=\"ISRG R\ + oot X1\" ];\r\ + \n\r\ + \n:set CertName \"Root-YE.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"Root-YE\" [ find where common-name=\"Root YE\" ]\ + ;\r\ + \n\r\ + \n:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"Starfield-Root-Certificate-Authority-G2\" [ find\ + \_where common-name=\"Starfield Root Certificate Authority - G2\" ];\r\ + \n\r\ + \n:set CertName \"USERTrust-RSA-Certification-Authority.pem\";\r\ + \n/tool/fetch mode=https url=(\$CertUrl . \$CertName);\r\ + \n/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n/certificate/set name=\"USERTrust-RSA-Certification-Authority\" [ find w\ + here common-name=\"USERTrust RSA Certification Authority\" ];\r\ + \n\r\ + \n:global tmpAddCerts (a);\r\ + \n\r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\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#/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\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=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n:global GlobalScriptsUrl;\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.86.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.86.pub\";\ + \n" +add dont-require-permissions=no name=awg2-webui owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + :put \"Download image, and save him to usb1/tmp\"\ + \n#/tool/fetch url=\"https://ros.vados.ru/docker/awg2-webui-arm.tar\" dst-\ + path=usb1/tmp/awg2-webui.tar\ + \n\ + \n:put \"1. Create veth interface\"\ + \n/interface veth add name=veth-awg address=10.9.9.2/24 gateway=10.9.9.1\ + \n\ + \n:put \"2. Create bridge and add veth\"\ + \n/interface bridge add name=br-awg\ + \n/interface bridge port add bridge=br-awg interface=veth-awg\ + \n\ + \n:put \"3. Assign IP to bridge\"\ + \n/ip address add address=10.9.9.1/24 interface=br-awg\ + \n\ + \n:put \"4. NAT: masquerade container traffic\"\ + \n/ip firewall nat add chain=srcnat src-address=10.9.9.0/24 action=masquer\ + ade\ + \n\ + \n:put \"5. Port forward: UDP 443 \? container (AmneziaWG QUIC mimicry)\"\ + \n/ip firewall nat add chain=dstnat protocol=udp dst-port=443 \\\ + \n action=dst-nat to-addresses=10.9.9.2 to-ports=55055 in-interface=eth\ + er1\ + \n\ + \n:put \"6. Port forward: HTTPS 9443 \? container Web UI\"\ + \n/ip firewall nat add chain=dstnat protocol=tcp dst-port=9443 \\\ + \n action=dst-nat to-addresses=10.9.9.2 to-ports=443 in-interface=ether\ + 1\ + \n\ + \n:put \"Create environment list..\"\ + \n/container envs add list=awgui-env key=WEB_USER value=vados\ + \n/container envs add list=awgui-env key=WEB_PASS value=zoomzoomrulezz\ + \n/container envs add list=awgui-env key=SECRET_KEY value=RanDomSecret32Sy\ + mboLs2325272931q\ + \n/container envs add list=awgui-env key=AWG_ENDPOINT value=10.30.30.10:44\ + 3\ + \n\ + \n:put \"Load and start container...\"\ + \n/container add file=usb1/tmp/awg2-webui.tar interface=veth-awg hostname=\ + awg2-webui \\\ + \nroot-dir=usb1/awg2-webui envlist=awgui-env start-on-boot=yes logging=yes\ + \_shm-size=4M\ + \n\ + \n:put \"Start...\"\ + \n/container start 0\ + \n\ + \n:put \"Verify...\"\ + \n/container print\ + \n\ + \n:put \"Should show: status=running\"\ + \n\ + \n/log print where topics~\"container\"\ + \n\ + \n:put \"Should show: AWG started, nginx running\"\ + \n" +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/container +# killed due to out of memory +add cpu-list=cpu1,cpu3 domain-name=vados.ru envlists=awgui-env file=\ + usb1/tmp/awg2-webui.tar hostname=mikronuc interface=veth-awg layer-dir=\ + /usb1/docker logging=yes memory-high=12.0MiB memory-max=16.0MiB name=\ + awg2-webui root-dir=/usb1/awg-webui shm-size=8.0MiB start-on-boot=yes \ + tmpfs=/tmpfs:512.0MiB:01000 +/container config +set layer-dir=/usb1/docker memory-high=2048.0KiB memory-max=2048.0KiB \ + registry-url=https://registry-1.docker.io tmpdir=/tmp username=amsternl +/container envs +add key=AWG_ENDPOINT list=awgui-env value=10.30.30.10:443 +add key=SECRET_KEY list=awgui-env value=RanDomSecret32SymboLs2325272931q +add key=WEB_PASS list=awgui-env value=zoomzoomrulezz +add key=WEB_USER list=awgui-env value=vados +/disk settings +set auto-media-interface=lo +/interface bridge port +add bridge=Bridge-LAN interface=ether1 +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-LAN interface=ether3 +add bridge=Bridge-LAN interface=ether4 +add bridge=Bridge-LAN interface=ether5 +add bridge=Bridge-LAN interface=wlan2 +add bridge=Bridge-LAN interface=wlan1 +add bridge=*D interface=*C +add bridge=*F interface=*E +add bridge=*11 interface=*10 +add bridge=*13 interface=*12 +add bridge=*15 interface=*14 +add bridge=br-awg interface=veth-awg +/ip neighbor discovery-settings +set discover-interface-list=Internet +/ipv6 settings +set allow-fast-path=no disable-ipv6=yes disable-link-local-address=yes \ + forward=no +/interface detect-internet +set detect-interface-list=static internet-interface-list=Internet \ + lan-interface-list=LAN wan-interface-list=WAN +/interface list member +add interface=ether2 list=LAN +add interface=ether3 list=LAN +add interface=ether4 list=LAN +add interface=ether5 list=LAN +add interface=wlan2 list=LAN +add interface=wlan1 list=LAN +add interface=ether1 list=Internet +add interface=Bridge-LAN list=LAN +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-addresses=10.30.30.10 \ + caps-man-certificate-common-names=CAPsMAN-51B25E507D07 certificate=\ + CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes interfaces=\ + wlan1,wlan2 lock-to-caps-man=yes +/ip address +add address=10.30.30.86/24 interface=ether1 network=10.30.30.0 +add address=10.9.9.1/24 interface=br-awg network=10.9.9.0 +/ip dns +set allow-remote-requests=yes servers=10.30.30.33,109.107.177.79 +/ip firewall nat +add action=masquerade chain=srcnat src-address=10.9.9.0/24 +# in/out-interface matcher not possible when interface (ether1) is slave - use master instead (Bridge-LAN) +add action=dst-nat chain=dstnat dst-port=443 in-interface=ether1 protocol=udp \ + to-addresses=10.9.9.2 to-ports=55055 +# in/out-interface matcher not possible when interface (ether1) is slave - use master instead (Bridge-LAN) +add action=dst-nat chain=dstnat dst-port=9443 in-interface=ether1 protocol=\ + tcp to-addresses=10.9.9.2 to-ports=443 +/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 +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 check-gateway=ping disabled=no distance=2 dst-address=0.0.0.0/0 gateway=\ + ether1 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 disabled=yes +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set graphs-plain=no rest-plain=no webfig-plain=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 forced-ip=109.107.177.79 interface=*A type=external +add interface=lo type=internal +add interface=wlan2 type=internal +add interface=wlan1 type=internal +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/system clock +set time-zone-name=Europe/Amsterdam +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroGig +/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=10.30.30.81 +add address=10.30.30.10 +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="Every Day Set Global Environment Variables" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +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 +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com diff --git a/MikroGig/history/20260628/20260628124118-Diff-Config.rsc b/MikroGig/history/20260628/20260628124118-Diff-Config.rsc new file mode 100644 index 0000000..3cf950b --- /dev/null +++ b/MikroGig/history/20260628/20260628124118-Diff-Config.rsc @@ -0,0 +1,8 @@ +483c483 +< \n:global CommitId \"main/702/b3f31455\";\r\ +--- +> \n:global CommitId \"main/700/f14f095d\";\r\ +486c486 +< r: root, in 07:15:04 28.06.2026.\";\r\ +--- +> r: root, in 13:30:03 22.06.2026.\";\r\ diff --git a/MikroMaster/20260628/20260628104001-Config.rsc b/MikroMaster/20260628/20260628104001-Config.rsc new file mode 100644 index 0000000..eb0eb67 --- /dev/null +++ b/MikroMaster/20260628/20260628104001-Config.rsc @@ -0,0 +1,3692 @@ +# 2026-06-28 10:40:06 by RouterOS 7.23.1 +# software id = A8L5-07YF +# +# model = RB952Ui-5ac2nD +# serial number = D3D50CEDCD38 +/interface bridge +add admin-mac=48:8F:5A:8E:1A:BF auto-mac=no dhcpv6-agent-circuit-id=\ + "\$(INTERFACE):\$(VID)" dhcpv6-agent-remote-id="\$(BRIDGEMAC)" name=\ + Bridge-LAN port-cost-mode=short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" loop-protect=off name=\ + "ether1 - Unet" rx-flow-control=auto tx-flow-control=auto +set [ find default-name=ether2 ] comment=LAN-2 +set [ find default-name=ether3 ] advertise="10M-baseT-half,10M-baseT-full,100M\ + -baseT-half,100M-baseT-full,1G-baseT-full,1G-baseX" comment=LAN-3 +set [ find default-name=ether4 ] comment=LAN-4 +set [ find default-name=ether5 ] advertise="10M-baseT-half,10M-baseT-full,100M\ + -baseT-half,100M-baseT-full,1G-baseT-full,1G-baseX" comment=LAN-5 \ + loop-protect=on poe-out=off rx-flow-control=auto tx-flow-control=auto +/interface wireless +# managed by CAPsMAN +set [ find default-name=wlan1 ] country=belarus mode=ap-bridge ssid=vados \ + wireless-protocol=802.11 +# managed by CAPsMAN +set [ find default-name=wlan2 ] country=belarus mode=ap-bridge ssid=vados5g \ + wireless-protocol=802.11 +/interface wireguard +add comment=WG listen-port=13231 mtu=1320 name=WG +/interface list +add include=static name=LAN +add name=Internet +add include=Internet name=WAN +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/iot wiliot servers +set *1 address=mqtt.us-east-2.prod.wiliot.cloud name="Wiliot US East" +/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 +add name=iVados options=HostName +/ip dns forwarders +add dns-servers=1.0.0.1,1.1.1.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.83-10.30.30.254 +/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 smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ipv6 dhcp-client option +add code=119 name=domain-search-list value="0x03'WORKGROUP'0x00" +add code=12 name=HostName value="\$(HOSTNAME)" +add code=61 name=DUID value=0x00030001488f5a8e1abc +add code=61 name=clientid +/ipv6 dhcp-server option +add code=119 name=domain-search-list value="0x03'WORKGROUP'0x00" +add code=12 name=HostName value="\$(HOSTNAME)" +add code=61 name=CLIENT_DUID +add code=61 name=CLIENT_MAC +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/system script +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n#/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@1\ + 0.30.30.86.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.86.pub\";\ + \n\r\ + \n#:local Script AM-setup\ + \n;\r\ + \n#/system/script/add name=\$Script owner=\$Script source=([ /tool/fetch c\ + heck-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \".r\ + sc\") output=user as-value ]->\"data\");\r\ + \n\ + \n#/usb1/mikro_bak_rsa.pub\ + \n\ + \n\r\ + \n#\ + \n\r\ + \n#/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@1\ + 0.30.30.10.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.10.pub\";\ + \n\r\ + \n#\r\ + \n\ + \n#root.mnuc.backuper\ + \n\ + \n\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n\ + \n#:local Script AM-GlobalConfig;\ + \n\r\ + \n#/system/script/add name=\$Script owner=\$Script source=([ /tool/fetch c\ + heck-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \".r\ + sc\") output=user as-value ]->\"data\");\r\ + \n\ + \n#/usb1/mikro_bak_rsa.pub\ + \n#:local FetchFile AM-DOHCert.rsc\ + \n\ + \n\r\ + \n\r\ + \n#\ + \n:global MkDir;\ + \n\r\ + \n\ + \n#:local FetchFile Binary.backup\ + \n:local localDir \"\";\ + \n\ + \n\r\ + \n#\$MkDir \$localDir;\r\ + \n\ + \n#\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \$FetchFile) dst-path=(\ + \$localDir . \$FetchFile);\r\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global GlobalConfReady false;\r\ + \n#\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in AM-Init-Script or AM-setup scripts\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix (a);\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n: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\";\r\ + \n#: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:global CertRenewUrl (\$GlobalScriptsUrl . \"certs/\" . \$Identity . \"/\ + \");\r\ + \n:global CertRenewTime 2w;\r\ + \n:global CertRenewPass (a); #{\r\ + \n# \"\";\r\ + \n# \"v3ry-s3cr3t\";\r\ + \n# \"4n0th3r-s3cr3t\";\r\ + \n#};\r\ + \n:global CertWarnTime 1w;\r\ + \n:global CertIssuedExportPass (a); # {\r\ + \n# \"\";\r\ + \n# \"cert1-cn\"=\"v3ry-s3cr3t\";\r\ + \n# \"cert2-cn\"=\"4n0th3r-s3cr3t\";\r\ + \n#};\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global 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# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\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/700/f14f095d\";\r\ + \n:global CommitTAG \"unknown\";\r\ + \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ + r: root, in 13:30:03 22.06.2026.\";\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 140;\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 MiniDateTimeStamp;\r\ + \n:global MicroDateTimeStamp;\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 CharacterMultiply;\r\ + \n:global CharacterReplace;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n\r\ + \n:global CommitBrief;\r\ + \n\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global GetRandom20CharHex;\r\ + \n:global GetRandomNumber;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \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 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 ExitError;\r\ + \n:global ExitOnError;\r\ + \n\r\ + \n:global FetchHugeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global FileExists;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \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 updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n :global currentUpdateChannel;\r\ + \n :global ROsVerAvail;\r\ + \n :global arrDeviceInfo;\r\ + \n :log info (\$0 . \" \\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if ([ :len \$updateChannel ] > 0 && \$CurrentChannel != \$updateChann\ + el) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n :log info (\$0 . \" Set updates channel to: \$updateChannel\");\r\ + \n }\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel [ :tostr (\$Update->\"channel\") ];\r\ + \n :set currentUpdateChannel \$Channel;\r\ + \n :log info (\$0 . \" Update Channel: \" . \$Channel . \".\");\r\ + \n :local StatusPkg \"undefined\";\r\ + \n :log info (\$0 . \" Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n :log info (\$0 . \" \\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n :set ROsVerAvail [ :tostr [ /system/package/update/get latest-version \ + ] ];\r\ + \n :log info (\$0 . \" \\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n :log info (\$0 . \" \\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([ :typeof \$arrDeviceInfo ] != \"array\") do={\r\ + \n :set arrDeviceInfo [:toarray \$arrDeviceInfo];\r\ + \n }\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [ /system/pac\ + kage/update/get ]} delay=500ms max=5 on-error={:log error (\"Error\")};\r\ + \n :return true;\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitCheckUpdates do={\r\ + \n :global IsCheckUpdates;\r\ + \n :global PkgUpdStatus;\r\ + \n :global currentUpdateChannel;\r\ + \n :global ROsVerAvail;\r\ + \n :global arrDeviceInfo;\r\ + \n :local Status \"\";\r\ + \n :local Update;\r\ + \n :local WaitCount 0;\r\ + \n :if ([ \$IsCheckUpdates true ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n :set Status [ :tostr [ /system/package/update/get status ] ];\r\ + \n :while ((\$Status = \"\" || \$Status = \"finding out latest version...\ + \") && \$WaitCount < 60) do={\r\ + \n :delay 1s;\r\ + \n :set WaitCount (\$WaitCount + 1);\r\ + \n :set Status [ :tostr [ /system/package/update/get status ] ];\r\ + \n }\r\ + \n :set Update [ /system/package/update/get ];\r\ + \n :set currentUpdateChannel [ :tostr (\$Update->\"channel\") ];\r\ + \n :set ROsVerAvail [ :tostr (\$Update->\"latest-version\") ];\r\ + \n :if ((\$Update->\"status\") = \"New version is available\") do={\r\ + \n :set PkgUpdStatus true;\r\ + \n } else={\r\ + \n :set PkgUpdStatus false;\r\ + \n }\r\ + \n :if ([ :typeof \$arrDeviceInfo ] != \"array\") do={\r\ + \n :set arrDeviceInfo [:toarray \$arrDeviceInfo];\r\ + \n }\r\ + \n :set (\$arrDeviceInfo->\"devUpdates\") \$Update;\r\ + \n :if (\$Status = \"\" || \$Status = \"finding out latest version...\") \ + do={\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\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 :global arrDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devBuildTime;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global currentUpdateChannel;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :local DeviceInfo;\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local VersionString [ :tostr (\$Resource->\"version\") ];\r\ + \n :local ChannelStart [ :find \$VersionString \" (\" ];\r\ + \n :local RouterBoard;\r\ + \n :local IsRouterBoard false;\r\ + \n :local RunningMode \"\";\r\ + \n\r\ + \n :set devCurArch [ :tostr (\$Resource->\"architecture-name\") ];\r\ + \n :set devBuildTime [ :tostr (\$Resource->\"build-time\") ];\r\ + \n :set runningChannelVersion \$VersionString;\r\ + \n :set runningVersion \$VersionString;\r\ + \n :set runningChannel \"\";\r\ + \n\r\ + \n :if ([ :typeof \$ChannelStart ] = \"num\" && \$ChannelStart >= 0) do=\ + {\r\ + \n :set runningVersion [ :pick \$VersionString 0 \$ChannelStart ];\r\ + \n :local ChannelRest [ :pick \$VersionString (\$ChannelStart + 2) [ :\ + len \$VersionString ] ];\r\ + \n :local ChannelEnd [ :find \$ChannelRest \")\" ];\r\ + \n :if ([ :typeof \$ChannelEnd ] = \"num\" && \$ChannelEnd >= 0) do={\ + \r\ + \n :set runningChannel [ :pick \$ChannelRest 0 \$ChannelEnd ];\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :do {\r\ + \n :set RouterBoard [[ :parse \"/system/routerboard/get\" ]];\r\ + \n# :set RouterBoard [ /system/routerboard/get ];\r\ + \n :if ((\$RouterBoard->\"routerboard\") = true) do={\r\ + \n :set IsRouterBoard true;\r\ + \n }\r\ + \n } on-error={}\r\ + \n }\r\ + \n\r\ + \n :do {\r\ + \n :set RunningMode [ /system/device-mode/get mode ];\r\ + \n } on-error={\r\ + \n :do {\r\ + \n :set RunningMode [ /system/device-mode/get running ];\r\ + \n } on-error={\r\ + \n :set RunningMode \"\";\r\ + \n }\r\ + \n }\r\ + \n :set devRunning \$RunningMode;\r\ + \n\r\ + \n :if (\$IsRouterBoard = true) do={\r\ + \n :set devModel [ :tostr (\$RouterBoard->\"model\") ];\r\ + \n :set devRbRevision [ :tostr (\$RouterBoard->\"revision\") ];\r\ + \n :set devRbSerialNumber [ :tostr (\$RouterBoard->\"serial-number\") \ + ];\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n :set devRbRevision \"\";\r\ + \n :set devRbSerialNumber \"\";\r\ + \n }\r\ + \n\r\ + \n :set currentUpdateChannel [ :tostr (\$Update->\"channel\") ];\r\ + \n :set ROsVerAvail [ :tostr (\$Update->\"latest-version\") ];\r\ + \n\r\ + \n :set (\$DeviceInfo->\"board-name\") \$devBoardName;\r\ + \n :set (\$DeviceInfo->\"architecture-name\") \$devCurArch;\r\ + \n :set (\$DeviceInfo->\"model\") \$devModel;\r\ + \n :set (\$DeviceInfo->\"revision\") \$devRbRevision;\r\ + \n :set (\$DeviceInfo->\"serial-number\") \$devRbSerialNumber;\r\ + \n :set (\$DeviceInfo->\"running-mode\") \$devRunning;\r\ + \n :set (\$DeviceInfo->\"build-time\") \$devBuildTime;\r\ + \n :set (\$DeviceInfo->\"running-channel-version\") \$runningChannelVers\ + ion;\r\ + \n :set (\$DeviceInfo->\"running-version\") \$runningVersion;\r\ + \n :set (\$DeviceInfo->\"running-channel\") \$runningChannel;\r\ + \n :set (\$DeviceInfo->\"routerboard\") \$IsRouterBoard;\r\ + \n :set (\$DeviceInfo->\"current-firmware\") [ :tostr (\$RouterBoard->\"\ + current-firmware\") ];\r\ + \n :set (\$DeviceInfo->\"upgrade-firmware\") [ :tostr (\$RouterBoard->\"\ + upgrade-firmware\") ];\r\ + \n :set (\$DeviceInfo->\"package-channel\") \$currentUpdateChannel;\r\ + \n :set (\$DeviceInfo->\"installed-version\") [ :tostr (\$Update->\"inst\ + alled-version\") ];\r\ + \n :set (\$DeviceInfo->\"latest-version\") \$ROsVerAvail;\r\ + \n :set (\$DeviceInfo->\"update-status\") [ :tostr (\$Update->\"status\"\ + ) ];\r\ + \n\r\ + \n :set arrDeviceInfo \$DeviceInfo;\r\ + \n :return \$DeviceInfo;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :global CommitBrief;\r\ + \n\r\ + \n :local License [/system/license/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Info [ \$GetArrDeviceInfo ];\r\ + \n\r\ + \n :if ([ :typeof \$Info ] != \"array\") do={\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :return ( \\\r\ + \n [ \$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\" (\$Info->\"board-name\") ] . \"\\n\" . \ + \\\r\ + \n [ \$FormatLine \" Arch\" (\$Info->\"architecture-name\") ] . \"\\\ + n\" . \\\r\ + \n [ \$FormatLine \" Model\" (\$Info->\"model\") ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"revision\") ] > 0) \\\r\ + \n (\" \" . (\$Info->\"revision\")) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"serial-number\") ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial\" (\$Info->\"serial-number\") ] . \"\ + \\n\") ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License\" (\"level \" . (\$License->\"nlevel\ + \")) ] . \"\\n\") ] . \\\r\ + \n \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \" Channel\" (\$Info->\"package-channel\") ] . \"\ + \\n\" . \\\r\ + \n [ \$FormatLine \" Installed\" (\$Info->\"installed-version\") ] .\ + \_\"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"running-channel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" Running\" ((\$Info->\"running-version\") . \ + \" (\" . (\$Info->\"running-channel\") . \")\") ] . \"\\n\") \\\r\ + \n ([ \$FormatLine \" Running\" (\$Info->\"running-version\") ] . \ + \"\\n\") ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Info->\"latest-version\") ] > 0 && \\\r\ + \n (\$Info->\"installed-version\") != (\$Info->\"latest-version\"))\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Info->\"latest-version\") ] .\ + \_\"\\n\") ] . \\\r\ + \n [ \$IfThenElse ((\$Info->\"routerboard\") = true && \\\r\ + \n (\$Info->\"current-firmware\") != (\$Info->\"upgrade-firmware\")\ + ) \\\r\ + \n ([ \$FormatLine \" Firmware\" ((\$Info->\"current-firmware\") .\ + \_\" -> \" . (\$Info->\"upgrade-firmware\")) ] . \"\\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\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:set GetRandom20CharHex do={:global EitherOr; :return [ :rndstr length=[\ + \_\$EitherOr [ :tonum \$1 ] 20 ] from=\"0123456789abcdef\" ]; }\r\ + \n:set GetRandomNumber do={:global EitherOr; :return [ :rndnum from=0 to=[\ + \_\$EitherOr [ :tonum \$1 ] 4294967295 ] ]; }\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \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 CommitBrief do={\r\ + \n :global CommitId;\r\ + \n :global CommitInfo;\r\ + \n :if (\$CommitId = \"unknown\") do={\r\ + \n :return \"unknown\";\r\ + \n }\r\ + \n :return (\$CommitInfo . \"/\" . [ :pick \$CommitId 0 8 ]);\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:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n\r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n :local JobName [ :jobname ];\r\ + \n\r\ + \n :do {\r\ + \n :log debug (\$0 . \" Trying to detect public IP using default serv\ + ice: \" . \$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={:log error (\$JobName . \" Failed to \ + detect public IP using default service: \" . \$Url . \".\")}\r\ + \n } on-error={\r\ + \n :log error (\$0 . \" Failed to detect public IP using default serv\ + ice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n :log debug (\$0 . \" Trying to detect public IP using fallback ser\ + vice: \" . \$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={:log error (\$JobName . \" Failed to\ + \_detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :local IpLen ([ :len \$PubIpAddr ] -1);\r\ + \n :if (\$PubIpAddr = false) do={:set PubIpAddr \"not-detected\"} else=\ + {:set PubIpAddr [:pick \$PubIpAddr 0 \$IpLen]}\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\r\ + \n :global CertificateDownload;\r\ + \n :global ParseKeyValueStore;\r\ + \n\r\ + \n :if ([ :len \$UseFor ] = 0) do={\r\ + \n :log warning (\$0 . \"The intended use is undefined!\");\r\ + \n :set UseFor \"undefined\";\r\ + \n }\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n :log warning (\$0 . \"This system has low free flash space but \" . \ + \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n :log 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 :log info (\$0 . \"Certificate with CommonName '\" . \$CommonName . \ + \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n :log 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 :log info (\$0 . \"Certificate chain for '\" . \$CommonName . \"' \ + is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \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 ScriptUpdatesBaseUrl;\r\ + \n :global ScriptUpdatesUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :log info (\$0 . \"Downloading and importing certificate with \" . \\\ + \r\ + \n \"CommonName '\" . \$CommonName . \"'.\");\r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl mode=https http-header\ + -field=({ [ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$ScriptUpdatesBaseUrl . \"certs/\" . \$FileName . \$ScriptUpdate\ + sUrlSuffix) \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n :log warning (\$0 . \" Failed downloading certificate with CommonNam\ + e '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0 && \\\r\ + \n !(((\$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=\"ISRG\ + \_Root X1\" ] ] > 0)) do={\r\ + \n :log error (\$0 . \" Required certificate is not available.\");\ + \r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl mode=https http-head\ + er-field=({ [ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n url=\"https://mkcert.org/generate/\" http-data=[ :serialize to=jso\ + n ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n :log error (\$0 . \" Failed downloading certificate with CommonNam\ + e '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n :log warning (\$0 . \" Certificate with CommonName '\" . \$CommonNam\ + e . \"' 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 :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 :log 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 FileExists do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local Type [ :tostr \$2 ];\r\ + \n :global FileGet;\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={ :return false; }\r\ + \n :if ([ :len (\$FileVal->\"size\") ] = 0) do={ :return false; }\r\ + \n :if ([ :len \$Type ] = 0 || \$FileVal->\"type\" = \$Type) do={ :return\ + \_true; }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \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 CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={ :set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]; }\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={ :set Path [ :pick \$Path 1 [ :le\ + n \$Path ] ]; }\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={ :set Path [ \ + :pick \$Path 0 ([ :len \$Path ] - 1) ]; }\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \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 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\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 :if (\$ExitOK = \"false\") do={\r\ + \n :log 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 ExitOnError do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :local Error [ :tostr \$2 ];\r\ + \n :global IfThenElse;\r\ + \n :log error (\$Name . \" \" . [ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\ + \\\$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with erro\ + r\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \$E\ + rror) \".\" ]);\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n :local mikro [ :tobool \$1 ];\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \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 :local Return;\r\ + \n :if (\$mikro = true) do={\r\ + \n :set Return ([:pick \$yyyy 2 4] . [:pick \$dd 0 1] . [:pick \$HH 0\ + \_1] . [:pick \$mm 3 4] . [:pick \$ss 6 7]);\r\ + \n } else={\r\ + \n :set Return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\ + \r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \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={\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileVal false;\r\ + \n :do {\r\ + \n :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 :log debug (\$0 . \" Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\r\ + \n :log debug (\$0 . \" ... which does not exist.\");\r\ + \n :return true;\r\ + \n };\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\r\ + \n :log error (\$0 . \" Directory '\" . \$DirName . \"' is not a direct\ + ory.\");\r\ + \n :return false;\r\ + \n };\r\ + \n :onerror Err {\r\ + \n /file/remove \$DirName;\r\ + \n } do={\r\ + \n :log error (\$0 . \" Removing directory '\" . \$DirName . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n };\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :log debug (\$0 . \" Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\r\ + \n :log debug (\$0 . \" ... which does not exist.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n :log error (\$0 . \" File '\" . \$FileName . \"' is not a file.\");\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\r\ + \n :log error (\$0 . \" Removing file '\" . \$FileName . \"' failed: \"\ + \_. \$Err); :return false;\r\ + \n }\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\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 :log info (\$0 . \" The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :log info (\$0 . \" Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n :log 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 :log debug (\$0 . \" Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n :log 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 :log 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 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 VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n :log error (\$0 . \" No valid RouterOS version: \" . \$Required);\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n :log warning (\$0 . \" This \" . [ \$IfThenElse ([ :pick \$Caller \ + 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \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\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 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 :log error (\$0 . \" A script named '\" . \$Script . \"' does not ex\ + ist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \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 :log error (\$0 . \" More tickets than running scripts '\" . \$Scrip\ + t . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \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\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global 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 :log warning (\$0 . \"No symbol available for name '\" . \$Name . \"\ + '!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \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\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\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \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:set FetchHugeFiles do={\r\ + \n :local ScriptName [ :tostr \$1 ];\r\ + \n :local Url [ :tostr \$2 ];\r\ + \n :local CheckCert [ :tostr \$3 ];\r\ + \n\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \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\r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName \ + \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue;\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$Url . \" - \"\ + \_. \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$Url . \" did\ + \_not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \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:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global CommitBrief;\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (\" . \$GlobalScriptsUrl . \"; \" . [ \$\ + CommitBrief ] . \")\");\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global CommitId;\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 CommitIdBefore \$CommitId;\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={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nNews and\ + \_changes are not available.\");\r\ + \n\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={ :set GlobalConfChanges; \ + } else={ :global GlobalConfChanges (a); }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={ :set GlobalConfMigrati\ + on; } else={ :global GlobalConfMigration (a); }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# load modules\r\ + \n:foreach Script in=[ /system/script/find where name ~ \"^(global-functio\ + ns\\\\.d|mod)/.\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :if ([ \$ValidateSyntax (\$ScriptVal->\"source\") ] = true) do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n \$LogPrint error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \"' f\ + ailed to run: \" . \$Err);\r\ + \n }\r\ + \n } else={\r\ + \n \$LogPrint error \$0 (\"Module '\" . \$ScriptVal->\"name\" . \"' fai\ + led syntax validation, skipping.\");\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 \"Every Day Set Global Environment Variables\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + 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: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:log warning (\"This script \$ScriptName Loaded \" . \\\r\ + \n [ \$IfThenElse (\$CommitId != \"unknown\") ([ \$CommitBrief ] . \" \ + \") ] . \\\r\ + \n \"on \" . \$devBoardName . \"\\nRouterOS: \" . \$devCurVersion . \"\ + \\nArchitecture: \" . \$devCurArch . \"\\nIdentity: \" . \$Identity);\r\ + \n # signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n\r\ + \n:log info (\$0 . \"Global configs ready!\");\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n}\r\ + \n" +add comment=\ + "Lookup IP addresses for RKN list and add them to firewall address-list" \ + dont-require-permissions=no name=AM-RKN-dnsLookup owner=AM-RKN-dnsLookup \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-RKN-dnsLookup\r\ + \n# Script comment: Lookup IP addresses for RKN list and add them to firew\ + all address-list\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n#\r\ + \n# Script description: This script is intended to be run periodically, e.\ + g. once a day, to update the IP addresses in the firewall address-list bas\ + ed on the RKN list.\r\ + \n# It resolves the domain names in the RKN list and a\ + dds the corresponding IP addresses to the specified firewall address-list.\ + \r\ + \n# The script also handles CNAME records by following\ + \_them until it finds A records.\r\ + \n# Usage:\r\ + \n# /system/script { run AM-RKN-dnsLookup; }\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global dnsLookupReady false;\r\ + \n:if ([:typeof \$dnsLookupReady] != \"boolean\") do={ :set dnsLookupReady\ + \_true; }\r\ + \nwhile (!\$dnsLookupReady) do={ :nothing; }\r\ + \n:set dnsLookupReady false;\r\ + \n\r\ + \n:local arrRKN {\r\ + \n \"telegra.ph\"\r\ + \n \"grani.ru\"\r\ + \n \"xhamster.com\"\r\ + \n \"lostfilm.tv\"\r\ + \n \"rutracker.org\"\r\ + \n \"lurkmore.to\"\r\ + \n \"dou.ua\"\r\ + \n \"youporn.com\"\r\ + \n \"pornolab.net\"\r\ + \n \"crimerussia.com\"\r\ + \n \"telegram.org\"\r\ + \n \"api.telegram.org\"\r\ + \n \"facebook.com\"\r\ + \n \"instagram.com\"\r\ + \n \"x.com\"\r\ + \n \"twitter.com\"\r\ + \n \"youtube.com\"\r\ + \n \"googleapis.com\"\r\ + \n \"youtu.be\"\r\ + \n \"googlevideo.com\"\r\ + \n \"gstatic.com\"\r\ + \n \"googleusercontent.com\"\r\ + \n \"nhacmp3youtube.com\"\r\ + \n \"telegram.me\"\r\ + \n \"t.me\";}\r\ + \n\r\ + \n:local ListRKN \"RKN-dnsLookup\";\r\ + \n:local ListComment (\"ListRKN managed by \" . \$ScriptName);\r\ + \n:foreach aListItem in=[/ip/firewall/address-list find list=\$ListRKN] do\ + ={\r\ + \n /ip firewall address-list remove \$aListItem;\r\ + \n}\r\ + \n:foreach aItem in=\$arrRKN do={\r\ + \n# :do {\r\ + \n :retry delay=500ms max=5 on-error={:log error \"dns resolve fail\ + ure [ \$aItem - resolve ip ]\"} command={:resolve \$aItem}\r\ + \n# } on-error={\r\ + \n# :log error \"dns resolve failure [ \$arItem - resolve ip ]\";\r\ + \n# }\r\ + \n :foreach dnsRecord in=[/ip dns cache all find where (name=\$aItem)] \ + do={\r\ + \n :if ([/ip dns cache all get \$dnsRecord type]=\"A\") do={\r\ + \n :local newAddress [/ip dns cache all get \$dnsRecord data];\ + \r\ + \n :do {\r\ + \n /ip firewall address-list add list=\$ListRKN address=\$newA\ + ddress comment=\$aItem;\r\ + \n :log warning \"Successfully adding ip to list A record: \ + \$dnsRecord, address: \$newAddress domain: \$aItem\";\r\ + \n } on-error={\r\ + \n :log error \"error when adding ip to list A record: \$dn\ + sRecord, address: \$newAddress domain: \$aItem\";\r\ + \n }\r\ + \n }\r\ + \n :if ([/ip dns cache all get \$dnsRecord type]=\"CNAME\") do={\r\ + \n :local cname;\r\ + \n :local nextCname;\r\ + \n :local cnameAddress;\r\ + \n :set cname [/ip dns cache all find where (name=\$aItem && ty\ + pe=\"CNAME\")];\r\ + \n :set nextCname [/ip dns cache all find where (name=[/ip dns \ + cache all get \$cname data] && type=\"CNAME\")];\r\ + \n :while (\$nextCname != \"\") do={\r\ + \n :set cname \$nextCname;\r\ + \n :set nextCname [/ip dns cache all find where (name=[/ip \ + dns cache all get \$cname data] && type=\"CNAME\")];\r\ + \n }\r\ + \n :foreach aRecord in=[/ip dns cache all find where (name=[/ip\ + \_dns cache all get \$cname data] && type=\"A\")] do={\r\ + \n :do {\r\ + \n :set cnameAddress [/ip dns cache all get \$aRecord d\ + ata];\r\ + \n /ip firewall address-list add list=\$ListRKN address\ + =\$cnameAddress comment=\$aItem;\r\ + \n :log warning \"Succesfully adding ip to list CNAME r\ + ecord: \$cname, A record: \$aRecord, address: \$newAddress, from domain: \ + \$aItem.\";\r\ + \n# /ip firewall raw add action=add-dst-to-address-list\ + \_address-list=\$ListRKN address-list-timeout=none-dynamic chain=preroutin\ + g comment=\$aItem content=\$aItem;\r\ + \n } on-error={\r\ + \n :log error \"error when adding ip to list CNAME reco\ + rd: \$cname, A record: \$aRecord, address: \$newAddress, from domain: \$aI\ + tem.\";\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:if ([ :len [ /system/scheduler/find where name=\$ScriptName ] ] = 0) do\ + ={\r\ + \n :log error (\$ScriptName . \"System Scheduler for script: \" . \$Scri\ + ptName . \" is NOT SET! Fix It Now!\");\r\ + \n /system/scheduler/add name=\$ScriptName on-event=\"/system/script { \ + run \$ScriptName; }\" comment=\"Update RKN DNS Looup\" interval=00:30:00 p\ + olicy=\"ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon\"\ + \_start-time=startup;\r\ + \n }\r\ + \n:set dnsLookupReady true;\r\ + \ndelay 2s; \r\ + \n:global dnsLookupReady (a);\r\ + \n" +add dont-require-permissions=no name="renameLists " owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + local oldName \"Test\";\ + \n:local newName \"Test-IP\";\ + \n/ip firewall address-list\ + \n:foreach i in=[find list=\$oldName] do={\ + \nset \$i list=\$newName;\ + \n}\ + \n" +add dont-require-permissions=no name=IPv6-Settings owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + #############Script Settings##################\ + \n\ + \n:local \"IF-TUN\" \"6to4-tun\"\ + \n:local \"IF-LOC\" \"Bridge-LAN\"\ + \n:local \"POOL-6TO4\" \"poolV6-local\"\ + \n:local \"force-update\" false\ + \n############ use then static ip #######################\ + \n:local \"lease-address\" [/ip address get [find interface=\$\"IF-LOC\"] \ + address]\ + \n#:local \"interface\" \"ext\"\ + \n:local bound 0\ + \n\ + \n###############################################\ + \n\ + \n:local 6to4prefix do={\ + \n :global dec2hex\ + \n :local ipv4 \$1\ + \n :local ipv6 \"2002:\"\ + \n :for i from=0 to=2 step=1 do={ \ + \n :if ( \$i = 2) do={\ + \n :set ipv6 (\$ipv6.\":\")\ + \n }\ + \n :local fp [:find \$ipv4 \".\"]\ + \n :if ( \$fp > 0 ) do={\ + \n :set ipv6 (\$ipv6.[\$dec2hex [:pick \$ipv4 0 \$fp]])\ + \n :set ipv4 [:pick \$ipv4 (\$fp + 1 ) [:len \$ipv4]]\ + \n }\ + \n }\ + \n :return (\$ipv6.[\$dec2hex \$ipv4])\ + \n}\ + \n:local \"str_replace\" do={\ + \n :local \"str-pos\" [:find \$1 \$2]\ + \n :local \"str-len\" [:len \$2]\ + \n :local str \"\"\ + \n :local rest \$1\ + \n :while (\$\"str-pos\" >= 0) do={\ + \n :local t [:pick \$rest 0 \$\"str-pos\"]\ + \n :if ( \$4 > 0 ) do={\ + \n :for i from=1 to=(\$4 - [:len \$t]) step=1 do={\ + \n :set str (\$str.\$5)\ + \n }\ + \n }\ + \n :set str (\$str.\$t.\$3)\ + \n :set rest [:pick \$rest (\$\"str-pos\"+\$\"str-len\") [:len \$re\ + st]]\ + \n :set \"str-pos\" [:find \$rest \$2]\ + \n }\ + \n :return (\$str.\$rest)\ + \n}\ + \n\ + \n:if (\$bound=1) do={\ + \n :local t [:find \$\"lease-address\" \"/\"]\ + \n\ + \n :if ( \$t >= 0 ) do={\ + \n :set \"lease-address\" [:pick \$\"lease-address\" 0 \$t]\ + \n }\ + \n\ + \n :if ( [/interface 6to4 print count-only where name=\$\"IF-TUN\"] = 0\ + ) do={\ + \n /interface 6to4 add !keepalive local-address=\$\"lease-address\"\ + \_mtu=1280 name=\$\"IF-TUN\" remote-address=10.30.30.0\ + \n :set \"force-update\" true\ + \n }\ + \n\ + \n :local \"IPv4-TUN\" [/interface 6to4 get [find name=\$\"IF-TUN\"] lo\ + cal-address];\ + \n\ + \n :if ( \$\"lease-address\" != \$\"IPv4-TUN\" || \$\"force-update\" = \ + true) do={\ + \n /interface 6to4 set [find name=\$\"IF-TUN\"] local-address=\$\"l\ + ease-address\"\ + \n /ipv6 address remove [find interface=\$\"IF-TUN\"]\ + \n /ipv6 address remove [find interface=\$\"IF-LOC\"]\ + \n /ipv6 route remove [find gateway ~ \$\"IF-TUN\" and dst-address=\ + \"::/0\"]\ + \n :local \"pool-prefix\" [\$6to4prefix \$\"lease-address\"]\ + \n :if ( [/ipv6 pool print count-only where name=\$\"POOL-6TO4\"] =\ + \_0) do={ \ + \n /ipv6 pool add name=\$\"POOL-6TO4\" prefix=(\$\"pool-prefix\ + \".\":1::/64\") prefix-length=64\ + \n } else={\ + \n /ipv6 pool set [/ipv6 pool find where name=\$\"POOL-6TO4\"] \ + prefix=(\$\"pool-prefix\".\":1::/64\")\ + \n }\ + \n /ipv6 address add address=(\$\"pool-prefix\".\"::\".[\$MAC2EUI64\ + \_[/interface get [find name=\$\"interface\"] mac-address]].\"/3\") interf\ + ace=\$\"IF-TUN\" advertise=no\ + \n /ipv6 address add eui-64=yes from-pool=\$\"POOL-6TO4\" interface\ + =\$\"IF-LOC\" advertise=yes\ + \n /ipv6 route add dst-address=::/0 gateway=(\"::10.30.30.81%\".\$\ + \"IF-TUN\")\ + \n :local t [/ipv6 address get [find interface=\$\"IF-LOC\"] addres\ + s]\ + \n :set t [:pick \$t 0 [:find \$t \"/\"]]\ + \n :if ( [/ipv6 dhcp-server option print count-only where name=DNS]\ + \_= 0) do={\ + \n /ipv6 dhcp-server option add code=23 name=DNS value=(\"0x\".\ + [\$\"str_replace\" \$t \":\" \"\" 4 \"0\"])\ + \n } else={\ + \n /ipv6 dhcp-server option set [/ipv6 dhcp-server option find \ + where name=DNS] value=(\"0x\".[\$\"str_replace\" \$t \":\" \"\" 4 \"0\"])\ + \n }\ + \n :if ( [/ipv6 dhcp-server print count-only where interface=\$\"IF\ + -LOC\"] = 0) do={\ + \n /ipv6 dhcp-server add address-pool=\$\"POOL-6TO4\" dhcp-opti\ + on=DNS interface=\$\"IF-LOC\" lease-time=1d name=\$\"IF-LOC\"\ + \n }\ + \n :if ( [ipv6 nd print count-only where interface=\$\"IF-LOC\"] = \ + 0) do={\ + \n /ipv6 nd add advertise-dns=no interface=\$\"IF-LOC\" other-c\ + onfiguration=yes\ + \n }\ + \n }\ + \n}" +add dont-require-permissions=no name=IPv6-GlobalFunc owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":\ + global MAC2EUI64 do={\ + \n :local EUI64 \"\"\ + \n :local MAC \$1\ + \n :local HEX2DEC \"0123456789ABCDEF\"\ + \n :for i from=0 to=5 step=1 do={\ + \n :if ( \$i = 0 ) do={\ + \n :set EUI64 [:pick \$MAC 0]\ + \n :set EUI64 (\$EUI64.[:tostr [:pick \$\"HEX2DEC\" ([:find \$\ + \"HEX2DEC\" [:pick \$MAC 1]] ^ 2)]])\ + \n }\ + \n :if ( \$i = 1 || \$i = 3) do={\ + \n :set EUI64 (\$EUI64.\":\")\ + \n }\ + \n :if ( \$i = 2 ) do={\ + \n :set EUI64 (\$EUI64.\"FF:FE\")\ + \n }\ + \n :if ( [:find \$MAC \":\"] = 2 ) do={\ + \n :set MAC [:pick \$MAC 3 [:len \$MAC]]\ + \n :set EUI64 (\$EUI64.[:pick \$MAC 0 2])\ + \n }\ + \n }\ + \n :return (\$EUI64)\ + \n}\ + \n\ + \n:global dec2hex do={\ + \n :local hex \"\"\ + \n :local dec [:tonum \$1]\ + \n :for i from=0 to=4 step=4 do={\ + \n :set hex ([:pick \"0123456789ABCDEF\" ((\$dec>>\$i)&0xf) (((\$de\ + c>>\$i)&0xf)+1)].\$hex)\ + \n }\ + \n :return ([:tostr \$hex])\ + \n}" +/user group +add name=backup policy="ssh,read,write,policy,test,web,sniff,sensitive,api,res\ + t-api,!local,!telnet,!ftp,!reboot,!winbox,!password,!romon" +/ip smb +set enabled=no interfaces=lo +/interface bridge port +add bridge=Bridge-LAN interface=ether5 +add bridge=Bridge-LAN interface=ether2 +add bridge=Bridge-LAN interface=ether4 trusted=yes +add bridge=Bridge-LAN interface=ether3 +add bridge=Bridge-LAN interface=wlan2 +add bridge=Bridge-LAN interface=wlan1 +/interface bridge settings +set use-ip-firewall=yes +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN lldp-med=no lldp-poe-power=no +/ip settings +set accept-redirects=yes ipv4-multipath-hash-policy=l4 max-neighbor-entries=\ + 8192 +/ipv6 settings +set disable-ipv6=yes disable-link-local-address=yes forward=no \ + max-neighbor-entries=8192 multipath-hash-policy=l4 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=Internet \ + lan-interface-list=LAN request-interval=1m wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add interface=ether4 list=WAN +add interface="ether1 - Unet" list=Internet +add disabled=yes interface=WG list=WAN +add interface=Bridge-LAN list=LAN +/interface wireguard peers +add allowed-address=0.0.0.0/0 client-allowed-address=::/0 endpoint-address=\ + 109.107.177.79 endpoint-port=29185 interface=WG name=VDSina \ + persistent-keepalive=10s public-key=\ + "zuRsO+dL/j6awaBWZ/NgnHR+bCNUjRWbaHFpdzkNnw4=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-addresses=10.30.30.10 \ + caps-man-certificate-common-names=CAPsMAN-51B25E507D07 certificate=\ + CAP-488F5A8E1ABC discovery-interfaces=Bridge-LAN enabled=yes interfaces=\ + wlan2,wlan1 lock-to-caps-man=yes +/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 cloud +set update-time=no +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main:2 dhcp-options=clientid_duid,clientid \ + interface="ether1 - Unet" name=client1 use-peer-dns=no use-peer-ntp=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=iVados mac-address=DE:4D:72:F3:1A:9F server=masterDHCP +add address=10.30.30.10 allow-dual-stack-queue=yes client-id=\ + ff:0:0:0:df:0:3:0:1:f0:75:5d:1e:5f:85 dhcp-option=HostName \ + dhcp-option-set=MikroNUC mac-address=F0:75:5D:1E:5F:85 server=masterDHCP \ + use-src-mac=yes +/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.33,109.107.177.79 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=109.107.177.79,10.30.30.33,8.8.4.4 \ + verify-doh-cert=yes +/ip dns static +add address=109.107.177.79 comment="VDSina Server DNS" name=ns1.vados.ru \ + type=A +add address=109.107.177.79 name=vds.vados.ru type=A +add comment="Local DNS server for vados.ru" disabled=yes ns=10.30.30.81 \ + regexp=*.vados.ru type=NS +add comment="*.vados.ru Regexp" disabled=yes forward-to=10.30.30.81 regexp=\ + "\".*\\\\.vados\\\\.ru\"" type=FWD +add comment="*.30.30.10.in-addr.arpa Regexp" disabled=yes forward-to=\ + 10.30.30.81 regexp="\".*\\\\.30\\\\.30\\\\.10\\\\.in-addr\\\\.arpa" type=\ + FWD +add address=10.30.30.81 comment=NS.vados.ru.local disabled=yes name=\ + ns.vados.ru.local type=A +add comment="DNS ns.vados.ru.local" disabled=yes match-subdomain=yes name=\ + vados.ru ns=ns.vados.ru.local type=NS +add address=10.30.30.33 comment=reg.vados.ru name=reg.vados.ru type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" match-subdomain=yes name=\ + dns.google type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=ros.vados.ru type=A +add address=10.30.30.95 name=vados-nuc type=A +add address=10.30.30.33 name=amster-nuc type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 disabled=yes 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 disabled=yes match-subdomain=yes name=\ + mikrots.vados.ru 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" disabled=yes name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" disabled=yes name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" disabled=yes name=\ + dns.quad9.net type=A +add address=195.133.25.16 comment="DNS Comss" disabled=yes name=dns.comss.one \ + type=A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.10 name=MikroNUC type=A +add address=10.30.30.86 disabled=yes name=MikroYellow type=A +add address=10.30.30.85 disabled=yes name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.20 disabled=yes 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=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-IP +add address=wg.vados.ru comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" disabled=yes 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-IP +add address=geoip.co list=NoVdsina +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=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=amster disabled=yes list=NoWG +add address=10.30.30.10 comment=MikroNUC disabled=yes list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! disabled=yes list=NoWG +add address=wg.vados.ru comment=VDSina-vpn list=VDSina +add address=80.85.244.9 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=89.110.101.17 comment="!!!VDSina Server!!!" list=NoVdsina +add address=dns.quad9.net comment=Quad9-dns disabled=yes list=Trusted-DNS +add address=dns.google comment=Google-dns list=Trusted-DNS +add address=security.cloudflare-dns.com comment=CloudFlare-dns list=\ + Trusted-DNS +add address=time.google.com comment=Google-time list=Trusted-NTP +add address=0.ru.pool.ntp.org comment=ru.pool.ntp.org disabled=yes list=\ + Trusted-NTP +add address=1.ru.pool.ntp.org disabled=yes list=Trusted-NTP +add address=2.ru.pool.ntp.org comment=2.ru.pool.ntp.org disabled=yes list=\ + Trusted-NTP +add address=3.ru.pool.ntp.org comment=3.ru.pool.ntp.org disabled=yes list=\ + Trusted-NTP +add address=cp.vdsina.com comment=VDSina-vpn list=VDSina +add address=vdsina.ru comment=VDSina-vpn list=VDSina +add address=ns.vados.ru comment=VDSina-vpn list=VDSina +add address=vdsina.com comment=VDSina-vpn list=VDSina +add address=cp.vdsina.ru comment=VDSina-vpn list=VDSina +add address=ns1.vdsina.ru comment=VDSina-vpn list=VDSina +add address=10.30.30.0/24 comment="Local Network" list=Local-Net +add address=10.8.0.0/24 comment="WireGuard Network" list=Local-Net +add address=146.120.64.208/29 comment="External Net" list=Unet +add address=esia.gosuslugi.ru comment=esia.gosuslugi.ru list=NoVdsina +add address=lk.gosuslugi.ru comment=lk.gosuslugi.ru list=NoVdsina +add address=trudvsem.ru comment=trudvsem.ru list=NoVdsina +add address=10.30.30.30 comment=miller disabled=yes list=NoWG +add address=10.30.30.33 comment="Direct connet to DNS servers" list=\ + Direct-DNS +add address=109.107.177.79 list=VPN-Server +add address=10.30.30.10 list=AWG-Proxy +/ip firewall filter +add action=accept chain=input disabled=yes dst-port=18880 in-interface=\ + Bridge-LAN protocol=tcp src-address=10.30.30.0/24 +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 src-address-list=!Trusted-DNS +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp src-address-list=!Trusted-DNS +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=22,8291 \ + 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=4w2d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=accept chain=input disabled=yes dst-port=29185 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=input disabled=yes dst-port=29185 in-interface=\ + "ether1 - Unet" protocol=udp +add action=accept chain=input comment="tcp Accept input DNS queries from LAN" \ + dst-port=53 protocol=tcp src-address=10.30.30.0/24 +add action=accept chain=input comment="udp Accept input DNS queries" \ + dst-port=53 protocol=udp src-address=10.30.30.0/24 +add action=accept chain=output comment="accept WireGuard" disabled=yes \ + dst-address-list=VPN-Server out-interface="ether1 - Unet" protocol=udp \ + src-port=13231 +add action=accept chain=output disabled=yes dst-address-list=VPN-Server \ + dst-port=29185 out-interface="ether1 - Unet" protocol=udp +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + disabled=yes ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + disabled=yes ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid in-interface="ether1 - Unet" src-address=\ + !10.30.30.0/24 +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" src-address-list=\ + !VDSina +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +add action=accept chain=input in-interface="ether1 - Unet" protocol=icmp \ + src-address-list=VDSina +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +/ip firewall mangle +add action=mark-routing chain=prerouting comment="Mark Routing main for NoWG" \ + disabled=yes new-routing-mark=main src-address-list=NoWG +add action=mark-routing chain=prerouting comment=\ + "Mark Routing main for NoVdsina" dst-address-list=NoVdsina \ + new-routing-mark=main src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=\ + "Mark Routing main for VDSina" dst-address-list=VPN-Server \ + new-routing-mark=main src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=\ + "Mark Routing main for MikroNuc" disabled=yes dst-address-list=AWG-Proxy \ + new-routing-mark=main src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=\ + "!!!ERROR Mark Routing main for Unet!!!" disabled=yes dst-address-list=\ + Unet new-routing-mark=main passthrough=no +add action=mark-routing chain=prerouting comment="Test-IP sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test-IP new-routing-mark=\ + To-VPN src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=FuckRKN disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=RKN-dnsLookup \ + new-routing-mark=To-VPN passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment="AWG for All sites" \ + disabled=yes dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina \ + new-routing-mark=*401 routing-mark=!main 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 new-routing-mark=\ + To-VPN routing-mark=!main src-address=10.30.30.0/24 +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" new-connection-mark=\ + VPN_No_FastTrack routing-mark=*401 +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp routing-mark=main tcp-flags=syn tcp-mss=\ + 1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" disabled=yes \ + dst-address=10.8.0.0/24 new-routing-mark=*401 src-address=10.30.30.0/24 +/ip firewall nat +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps dst-port=443 \ + fragment=no in-interface="ether1 - Unet" protocol=tcp routing-mark=main \ + 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=redirect chain=dstnat comment="udp Redirect DNS in NAT" disabled=\ + yes dst-port=53 protocol=udp src-address=10.30.30.0/24 src-address-list=\ + !NoWG to-addresses=10.30.30.33 to-ports=53 +add action=redirect chain=dstnat comment="tcp Redirect DNS in NAT" disabled=\ + yes dst-port=53 protocol=tcp src-address=10.30.30.0/24 src-address-list=\ + !NoWG to-addresses=10.30.30.33 to-ports=53 +add action=dst-nat chain=dstnat comment=\ + "53/tcp dst-nat to amster.loc. From VDSina Server" dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp src-address-list=VPN-Server \ + to-addresses=10.30.30.33 to-ports=53 +add action=dst-nat chain=dstnat comment=\ + "53/udp dst-nat to amster.loc. From VDSina Server" dst-port=53 protocol=\ + udp src-address-list=VPN-Server to-addresses=10.30.30.33 to-ports=53 +add action=dst-nat chain=dstnat disabled=yes dst-port=44333 in-interface=\ + "ether1 - Unet" protocol=udp src-address=!10.30.30.0/24 to-addresses=\ + 10.30.30.33 to-ports=44333 +add action=masquerade chain=srcnat comment="Default NAT" out-interface=\ + "ether1 - Unet" routing-mark=!To-VPN src-address=10.30.30.0/24 +add action=dst-nat chain=dstnat comment="amster.vados.ru 3x-ui" disabled=yes \ + dst-port=2904 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=2904 +add action=dst-nat chain=dstnat comment=reg.vados.ru disabled=yes dst-port=\ + 5000 in-interface="ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 \ + to-ports=5000 +add action=dst-nat chain=dstnat comment="Docker swarm" disabled=yes dst-port=\ + 2377 in-interface="ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 \ + to-ports=2377 +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp routing-mark=To-VPN to-addresses=10.30.30.33 \ + to-ports=81 +add action=dst-nat chain=dstnat comment=SSH dst-port=22 in-interface=\ + "ether1 - Unet" protocol=tcp src-address-list=TRUSTED to-addresses=\ + 10.30.30.33 to-ports=22 +add action=dst-nat chain=dstnat comment="portainer agent" disabled=yes \ + dst-port=2377 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=2377 +add action=dst-nat chain=dstnat disabled=yes dst-port=22 in-interface=\ + "ether1 - Unet" protocol=tcp routing-mark=!To-VPN to-addresses=\ + 10.30.30.33 to-ports=22 +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + out-interface=WG routing-mark=To-VPN src-address-list=!NoWG +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=accept chain=prerouting comment="Trusted DNS" disabled=yes \ + in-interface-list=WAN src-address-list=Trusted-DNS +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=youtube.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + googleapis.com disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=ggpht.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=youtu.be \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=ytimg.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + googlevideo.com disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=gstatic.com \ + disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + googleusercontent.com disabled=yes +add action=add-dst-to-address-list address-list=FuckRKN address-list-timeout=\ + none-dynamic chain=prerouting comment="YouTube raw" content=\ + nhacmp3youtube.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment="me.com raw" \ + content=me.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + "icloud.com raw" content=icloud.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + "smtp.mail.me.com raw" content=smtp.mail.me.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + "smtp.mail.me.com.akadns.net raw" content=smtp.mail.me.com.akadns.net \ + disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + "api.db-ip.com raw" content=api.db-ip.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + esia.gosuslugi.ru content=esia.gosuslugi.ru disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gosuslugi.ru \ + content=gosuslugi.ru disabled=yes +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/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 check-gateway=none disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\ + WG routing-table=To-VPN scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set reverse-proxy disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 disabled=yes +set www-ssl certificate=Root-YE port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + 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 forced-ip=146.120.64.211 interface="ether1 - Unet" type=external +add forced-ip=109.107.177.79 interface=*E type=external +add interface=lo type=internal +add interface=wlan2 type=internal +add interface=wlan1 type=internal +/ipv6 dhcp-client +add add-default-route=yes disabled=yes interface=*F rapid-commit=no request=\ + info use-interface-duid=yes validate-server-duid=no +/ipv6 dhcp-server option sets +add name=domain-search-set options=domain-search-list +add name="=\"Client ID\"" options=HostName +/ipv6 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=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 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 disabled=yes interface=Bridge-LAN \ + managed-address-configuration=yes other-configuration=yes pref64=::/64 +/ipv6 nd prefix +add autonomous=no disabled=yes interface=Bridge-LAN on-link=no prefix=none +/ipv6 nd prefix default +set dhcp6-pd-preferred=yes +/ipv6 nd proxy +add disabled=yes interface=lo +/ipv6 nd settings +set router-advertisement-route-distance=100 +/routing settings +set single-process=no +/system clock +set time-zone-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 package update +set check-certificate=yes-without-crl ip-version=ipv4 +/system scheduler +add comment="Every Day Set Global Environment Variables" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +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 +add comment="Update RKN DNS Looup" disabled=yes interval=20m name=\ + AM-RKN-dnsLookup on-event="/system/script { run AM-RKN-dnsLookup; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/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 certificate=DigiCert-Global-Root-CA check-certificate=no comment="doh, doh\ + -url=https://security.cloudflare-dns.com/dns-query, notify, name=CloudFlar\ + e-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 http-codes="" \ + interval=10s name="CloudFlare-doh IPv4 1" port=443 test-script="" type=\ + https-get up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + name="CloudFlare-doh IPv4" port=443 test-script="" type=https-get \ + up-script="" +add comment="dns, notify, name=Google-DNS IPv4" disabled=yes dns-server=\ + 8.8.8.8 down-script="" host=dns.google http-codes="" name=\ + "Google-DNS IPv4" test-script="" type=dns up-script="" +add certificate=GTS-Root-R4 check-certificate=yes comment="doh-fallback, doh-u\ + rl=https://dns.google/dns-query, doh-cert=GTS Root R1, notify, name=Google\ + -DOH IPv4" disabled=yes dns-server=8.8.4.4 down-script="" host=dns.google \ + http-codes="" name="Google-DOH IPv4" port=443 record-type=NS src-address=\ + "" test-script="" type=dns up-script="" +add comment="dns-fallback, notify, name=Cuad9-DOH IPv4" disabled=yes \ + dns-server=9.9.9.9 down-script="" host=dns9.quad9.net http-codes="" \ + interval=10s name="Cuad9-DOH IPv4" src-address=146.120.64.211 \ + test-script="" timeout=800ms type=dns up-script="" +add certificate=DigiCert-Assured-ID-Root-CA comment="doh-fallback, doh-url=htt\ + ps://dns.quad9.net/dns-query, name=Cuad9-DOH IPv4" disabled=yes \ + down-script="" host=149.112.112.112 http-codes="" interval=10s name=\ + "Cuad9-DOH IPv4" port=443 test-script="" type=https-get up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" interval=10s name=\ + ns1.unet.ws test-script="" type=simple up-script="" +add check-certificate=yes comment=\ + "doh, doh-url=https://vds.vados.ru/vds-query, name=vds.vados.ru" \ + disabled=yes down-script="" host=109.107.177.79 http-codes="" name=\ + vds.vados.ru port=443 test-script="" type=https-get up-script="" +/user aaa +set accounting=no -- 2.52.0