From 1ef39518a9fb9ace294d0a3a9c26527f110ce3bf Mon Sep 17 00:00:00 2001 From: vados-dev Date: Sun, 5 Jul 2026 08:23:15 +0300 Subject: [PATCH] Backup for MikroGig created successfully at Jul 05 08:23:15. --- .../20260705/20260705082311-Binary.backup | Bin 0 -> 194200 bytes MikroGig/20260705/20260705082311-Config.rsc | 3337 +++++++++++++++ .../20260705/20260705082311-Diff-Config.rsc | 14 + .../20260705/20260705080005-Config.rsc | 3741 +++++++++++++++++ MikroMaster/tmp/Diff-Config.rsc | 4 - 5 files changed, 7092 insertions(+), 4 deletions(-) create mode 100644 MikroGig/20260705/20260705082311-Binary.backup create mode 100644 MikroGig/20260705/20260705082311-Config.rsc create mode 100644 MikroGig/history/20260705/20260705082311-Diff-Config.rsc create mode 100644 MikroMaster/20260705/20260705080005-Config.rsc delete mode 100644 MikroMaster/tmp/Diff-Config.rsc diff --git a/MikroGig/20260705/20260705082311-Binary.backup b/MikroGig/20260705/20260705082311-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..0099c88dcfb5899970152f5532c8c1720015fbf8 GIT binary patch literal 194200 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 zⓈ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 literal 0 HcmV?d00001 diff --git a/MikroGig/20260705/20260705082311-Config.rsc b/MikroGig/20260705/20260705082311-Config.rsc new file mode 100644 index 0000000..acb52ed --- /dev/null +++ b/MikroGig/20260705/20260705082311-Config.rsc @@ -0,0 +1,3337 @@ +# 2026-07-05 08:23:12 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 +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] country=belarus disabled=no mode=ap-bridge \ + ssid=vados wps-mode=disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] country=belarus disabled=no mode=ap-bridge \ + ssid=vados5g wps-mode=disabled +/interface ethernet +set [ find default-name=ether1 ] mac-address=48:8F:5A:8E:1A:BC +/interface veth +add address=172.20.0.2/30 container-mac-address=00:00:00:00:00:00 dhcp=no \ + gateway=172.20.0.1 gateway6="" name=veth-awgVDSina +/interface wireguard +add disabled=yes listen-port=12430 mtu=1360 name=wg-awgVDSina +/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/728/bebacfc7\";\r\ + \n:global CommitTAG \"unknown\";\r\ + \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ + r: root, in 11:00:05 30.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" +add comment=Generator dont-require-permissions=no name=AWG-VDSina owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# ============================================================\r\ + \n# AWG Proxy -- MikroTik RouterOS (protocol: v2)\r\ + \n# 2026-06-30 22:08:12\r\ + \n# ============================================================\r\ + \n\r\ + \n# 0. Check prerequisites\r\ + \n:if ([:len [/system/package/find where name=\"container\" disabled=no]] \ + = 0) do={\r\ + \n :put \"Container package is not installed or disabled. Install it and \ + reboot.\"\r\ + \n :error \"Usage: /system/device-mode/update container=yes\"\r\ + \n}\r\ + \n\r\ + \n# Auto-detect storage\r\ + \n:global awgDisk \"disk1\"\r\ + \n{\r\ + \n :local usbFree 0\r\ + \n :do { :set usbFree [/disk/get [find where mount-point=\"usb1\"] free] \ + } on-error={}\r\ + \n :if (\$usbFree > 0) do={\r\ + \n :set awgDisk \"usb1\"\r\ + \n :put (\"Using USB: usb1 (\" . (\$usbFree / 1048576) . \" MB free)\")\ + \r\ + \n } else={\r\ + \n :if ([:len [/disk/find where slot=\"usb1\"]] > 0) do={\r\ + \n :put \"USB found but not mounted. Format as ext4\?\"\r\ + \n :put \"Press 'y' to confirm:\"\r\ + \n :local key [/terminal/inkey timeout=30]\r\ + \n :if (\$key = 121 || \$key = 89) do={\r\ + \n /disk/format-drive usb1 file-system=ext4 label=usb1\r\ + \n :delay 3s\r\ + \n :do { :set usbFree [/disk/get [find where mount-point=\"usb1\"] \ + free] } on-error={}\r\ + \n :if (\$usbFree > 0) do={\r\ + \n :set awgDisk \"usb1\"\r\ + \n } else={ :put \"Format failed, using disk1\" }\r\ + \n } else={ :put \"Using disk1\" }\r\ + \n } else={ :put \"No USB, using disk1\" }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# 1. Uninstall script\r\ + \n/system/script/add name=awg-VDSina-uninstall comment=awg-VDSina source={\ + \r\ + \n :put \"Uninstallimg AmneziaWG...\"\r\ + \n :log info \"Uninstallimg AmneziaWG...\"\r\ + \n :local prevDNS \"\"\r\ + \n :do { :set prevDNS [/container/envs/get [find where list=\"awg-VDSina-\ + env\" key=\"AWG_PREV_DNS\"] value] } on-error={}\r\ + \n :local storageDisk \"disk1\"\r\ + \n :do { :set storageDisk [/container/envs/get [find where list=\"awg-VDS\ + ina-env\" key=\"AWG_STORAGE\"] value] } on-error={}\r\ + \n :local prevTmpdir \"\"\r\ + \n :if (\$storageDisk != \"disk1\") do={\r\ + \n :do { :set prevTmpdir [/container/envs/get [find where list=\"awg-VD\ + Sina-env\" key=\"AWG_PREV_TMPDIR\"] value] } on-error={}\r\ + \n }\r\ + \n /ip/route/remove [find where comment=awg-VDSina-tunnel]\r\ + \n /ip/route/remove [find where comment=awg-VDSina-dns]\r\ + \n /container/stop [find where interface=veth-awg-VDSina]\r\ + \n :delay 7s\r\ + \n /container/remove [find where interface=veth-awg-VDSina]\r\ + \n /container/envs/remove [find where list=\"awg-VDSina-env\"]\r\ + \n :if (\$prevDNS != \"\") do={\r\ + \n :do { /ip/dns/set servers=\"\$prevDNS\" } on-error={}\r\ + \n :put (\"DNS restored to: \$prevDNS\")\r\ + \n }\r\ + \n :if (\$storageDisk != \"disk1\") do={\r\ + \n /container/config set tmpdir=\$prevTmpdir\r\ + \n :put (\"Container tmpdir restored to: \$prevTmpdir\")\r\ + \n }\r\ + \n /ip/firewall/nat/remove [find where out-interface=\"wg-awg-VDSina\"]\r\ + \n /ip/firewall/nat/remove [find where src-address=\"172.19.75.208/30\"]\ + \r\ + \n /ip/address/remove [find where address=\"172.19.75.209/30\"]\r\ + \n /interface/veth/remove [find where name=\"veth-awg-VDSina\"]\r\ + \n /interface/wireguard/peers/remove [find where interface=\"wg-awg-VDSin\ + a\"]\r\ + \n /ip/address/remove [find where interface=\"wg-awg-VDSina\"]\r\ + \n /interface/wireguard/remove [find where name=\"wg-awg-VDSina\"]\r\ + \n :do { /file/remove [find where name~\"awg-VDSina.+tar\"] } on-error={}\ + \r\ + \n :do { /file/remove [find where name=(\$storageDisk . \"/awg-VDSina\")]\ + \_} on-error={}\r\ + \n :do { /file/remove [find where name=(\$storageDisk . \"/ru_ranges_time\ + out.rsc\")] } on-error={}\r\ + \n :if (\$storageDisk != \"disk1\") do={\r\ + \n :do { /file/remove [find where name~(\$storageDisk . \"/pull\")] } o\ + n-error={}\r\ + \n }\r\ + \n :put \"Uninstall AmneziaWG Proxy complete!\"\r\ + \n :log info \"Uninstall AmneziaWG Proxy complete!\"\r\ + \n /system/script/remove [find where name=awg-VDSina-uninstall]\r\ + \n}\r\ + \n\r\ + \n# 2. Network infrastructure\r\ + \n/interface/veth/add name=veth-awg-VDSina address=172.19.75.210/30 gatewa\ + y=172.19.75.209\r\ + \n/ip/address/add address=172.19.75.209/30 interface=veth-awg-VDSina\r\ + \n/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.19.7\ + 5.208/30\r\ + \n\r\ + \n# 3. WireGuard interface (MikroTik derives the public key automatically)\ + \r\ + \n/interface/wireguard/add name=wg-awg-VDSina private-key=\"4CHyNhbOs923/E\ + yNDguMXJXdghL2I3UyzXPwrANVgHs=\" listen-port=14710 disabled=yes\r\ + \n/interface/wireguard/peers/add interface=wg-awg-VDSina public-key=\"o5Ig\ + Cl1/G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU=\" preshared-key=\"RNvF7T1cg5tyXcY\ + QnD9N5BEp6e20vVJQTv0GMjyvHU0=\" endpoint-address=172.19.75.210 endpoint-po\ + rt=51820 allowed-address=0.0.0.0/0 persistent-keepalive=10\r\ + \n/ip/address/add address=10.9.0.3/32 interface=wg-awg-VDSina\r\ + \n\r\ + \n# 4. Container environment variables\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_LISTEN value=\":44044\"\ + \r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_REMOTE value=\"109.107.1\ + 77.79:55055\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_JC value=\"9\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_JMIN value=\"105\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_JMAX value=\"920\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S1 value=\"90\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S2 value=\"136\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H1 value=\"472437748-472\ + 438637\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H2 value=\"707808381-707\ + 809250\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H3 value=\"1609078552-16\ + 09079495\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H4 value=\"1012329484-10\ + 12329741\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_SERVER_PUB value=\"o5IgC\ + l1/G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU=\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_CLIENT_PUB value=[/inter\ + face/wireguard/get [find name=wg-awg-VDSina] public-key]\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S3 value=\"45\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S4 value=\"27\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I1 value=\"\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I2 value=\"\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I3 value=\"\ + \"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I4 value=\"\"\ + \r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I5 value=\"\"\r\ + \n\r\ + \n# 5. DNS\r\ + \n{ :local rawDNS [/ip/dns/get servers]; :local prevDNS \"\"; :foreach s i\ + n=[:toarray \$rawDNS] do={ :if ([:len \$prevDNS] > 0) do={ :set prevDNS \"\ + \$prevDNS,\$s\" } else={ :set prevDNS \$s } }; /container/envs/add list=aw\ + g-VDSina-env key=AWG_PREV_DNS value=\"\$prevDNS\" }\r\ + \n# NOTE: replaces existing DNS configuration\r\ + \n/ip/dns/set servers=8.8.8.8\r\ + \n#/ip/route/add dst-address=109.107.177.79/32 gateway=wg-awg-VDSina dista\ + nce=1 comment=awg-VDSina-dns\r\ + \n\r\ + \n# 6. Download, create and start container\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_STORAGE value=\$awgDisk\ + \r\ + \n:if (\$awgDisk != \"disk1\") do={\r\ + \n :local tmpPath (\$awgDisk . \"/pull\")\r\ + \n /container/envs/add list=awg-VDSina-env key=AWG_PREV_TMPDIR value=[/co\ + ntainer/config/get tmpdir]\r\ + \n /container/config set tmpdir=\$tmpPath memory-high=200M\r\ + \n}\r\ + \n{\r\ + \n :local arch [/system/resource/get architecture-name]\r\ + \n :local ver [/system/resource/get version]\r\ + \n :local dotPos [:find \$ver \".\"]\r\ + \n :local rest [:pick \$ver (\$dotPos + 1) [:len \$ver]]\r\ + \n :local endPos [:find \$rest \".\"]\r\ + \n :if ([:typeof \$endPos] = \"nil\") do={ :set endPos [:find \$rest \" \ + \"] }\r\ + \n :local minor [:tonum [:pick \$rest 0 \$endPos]]\r\ + \n :local suffix \"\"\r\ + \n :if (\$minor <= 20) do={ :set suffix \"-7.20-Docker\" }\r\ + \n :local file \"\"\r\ + \n :if (\$arch = \"arm64\") do={ :set file (\"awg-proxy-arm64\" . \$suffi\ + x . \".tar.gz\") }\r\ + \n :if (\$arch = \"arm\") do={ :set file (\"awg-proxy-arm\" . \$suffix . \ + \".tar.gz\") }\r\ + \n :if (\$arch ~ \"x86\") do={ :set file (\"awg-proxy-amd64\" . \$suffix \ + . \".tar.gz\") }\r\ + \n :if (\$file = \"\") do={ :error \"Unsupported architecture: \$arch\" }\ + \r\ + \n :local url \"https://github.com/timbrs/amneziawg-mikrotik-c/releases/l\ + atest/download/\$file\"\r\ + \n :local filePath \$file\r\ + \n :if (\$awgDisk != \"disk1\") do={\r\ + \n :set filePath (\$awgDisk . \"/pull/\" . \$file)\r\ + \n :do { /file/make-directory (\$awgDisk . \"/pull\") } on-error={}\r\ + \n }\r\ + \n :if ([:len [/file/find where name=\$filePath]] = 0) do={\r\ + \n :local freeStorage 0\r\ + \n :if (\$awgDisk = \"disk1\") do={\r\ + \n :set freeStorage [/system/resource/get free-hdd-space]\r\ + \n } else={\r\ + \n :do { :set freeStorage [/disk/get [find where mount-point=\$awgDis\ + k] free] } on-error={}\r\ + \n }\r\ + \n :if (\$freeStorage < 262144) do={\r\ + \n :put (\"WARNING: Low disk space (\" . (\$freeStorage / 1024) . \"K\ + B free). Need at least 256KB.\")\r\ + \n :put \"See: https://github.com/timbrs/amneziawg-mikrotik-c#insuffi\ + cient-disk-space\"\r\ + \n :error \"Insufficient disk space\"\r\ + \n }\r\ + \n :put (\"Fetching: \$url -> \" . \$filePath)\r\ + \n /tool/fetch url=\$url dst-path=\$filePath http-max-redirect-count=10\ + \r\ + \n } else={\r\ + \n :put (\"File already exists: \" . \$filePath)\r\ + \n }\r\ + \n :local rootDir (\$awgDisk . \"/awg-VDSina\")\r\ + \n /container/add file=\$filePath interface=veth-awg-VDSina envlist=awg-V\ + DSina-env hostname=awg-VDSina root-dir=\$rootDir logging=no start-on-boot=\ + yes comment=awg-VDSina\r\ + \n :if (\$minor > 20) do={ [:parse \"/container/set [find where interface\ + =veth-awg-VDSina] shm-size=4M\"] }\r\ + \n /file/remove \$filePath\r\ + \n :local freeMem [/system/resource/get free-memory]\r\ + \n :if (\$freeMem < 16777216) do={\r\ + \n :put (\"WARNING: Low memory (\" . (\$freeMem / 1048576) . \"MB free)\ + . 16MB+ recommended.\")\r\ + \n }\r\ + \n /container/start [find where interface=veth-awg-VDSina]\r\ + \n :do { /file/remove [find where name=\"console-dump.txt\"] } on-error={\ + }\r\ + \n :put \"Waiting for container to start...\"\r\ + \n :delay 5s\r\ + \n /interface/wireguard/enable wg-awg-VDSina\r\ + \n :put \"WireGuard interface enabled\"\r\ + \n :put \"Installation complete!\"\r\ + \n :put \"Ping test: 109.107.177.79 via AmneziaWG tunnel. repeat 10 times\ + \"\r\ + \n /ping 109.107.177.79 count=10 interval=1\r\ + \n :put \"\"\r\ + \n :put \"======= NEXT STEPS =======\"\r\ + \n :put \"\"\r\ + \n :put \"Route specific traffic through the AmneziaWG tunnel:\"\r\ + \n :put \"\"\r\ + \n :put \" Route a single host:\"\r\ + \n :put \" /ip/route/add dst-address=8.8.8.8/32 gateway=wg-awg-VDSina \ + comment=awg-VDSina-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Route a subnet:\"\r\ + \n :put \" /ip/route/add dst-address=100.0.0.0/8 gateway=wg-awg-VDSina\ + \_comment=awg-VDSina-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Remove a route:\"\r\ + \n :put \" /ip/route/remove [find where comment=awg-VDSina-tunnel dst-\ + address=8.8.8.8/32]\"\r\ + \n :put \"\"\r\ + \n :put \" Show all tunnel routes:\"\r\ + \n :put \" /ip/route/print where comment=awg-VDSina-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Uninstall:\"\r\ + \n :put \" /system/script/run awg-VDSina-uninstall\"\r\ + \n :put \"=========================\"\r\ + \n}\r\ + \n\r\ + \n# 7. Verification\r\ + \n# /container/print\r\ + \n# /interface/wireguard/print\r\ + \n# /interface/wireguard/peers/print\r\ + \n" +add comment=awgVDSina dont-require-permissions=no name=awgVDSina-uninstall \ + owner=Manager policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n :put \"Uninstalling AmneziaWG...\"\r\ + \n :log info \"Uninstalling AmneziaWG...\"\r\ + \n /ip/route/remove [find where comment=awgVDSina-tunnel]\r\ + \n :do { /tool/netwatch/remove [find where comment=Monitor-AWGVDSINA] } o\ + n-error={}\r\ + \n :do { /ip/route/remove [find where comment=Monitor-AWGVDSINA] } on-err\ + or={}\r\ + \n /container/stop [find where interface=veth-awgVDSina]\r\ + \n :delay 7s\r\ + \n /interface/list/member/remove [find where interface=wg-awgVDSina]\r\ + \n /container/remove [find where interface=veth-awgVDSina]\r\ + \n /container/envs/remove [find where list=\"awgVDSina-env\"]\r\ + \n /ip/firewall/nat/remove [find where out-interface=\"wg-awgVDSina\"]\r\ + \n /ip/address/remove [find where address=\"172.20.0.1/30\"]\r\ + \n /interface/veth/remove [find where name=\"veth-awgVDSina\"]\r\ + \n /interface/wireguard/peers/remove [find where interface=\"wg-awgVDSina\ + \"]\r\ + \n /ip/address/remove [find where interface=\"wg-awgVDSina\"]\r\ + \n /interface/wireguard/remove [find where name=\"wg-awgVDSina\"]\r\ + \n :do { /file/remove [find where name~\"awgVDSina.+tar\"] } on-error={}\ + \r\ + \n :do { /file/remove [find where name=\"disk1/awgVDSina\"] } on-error={}\ + \r\ + \n :put \"Uninstall AmneziaWG Proxy complete!\"\r\ + \n :log info \"Uninstall AmneziaWG Proxy complete!\"\r\ + \n /system/script/remove [find where name=awgVDSina-uninstall]\r\ + \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 config +set layer-dir=/usb1/docker memory-high=200.0MiB memory-max=2048.0KiB \ + registry-url=https://registry-1.docker.io tmpdir=/usb1/pull username=\ + amsternl +/disk settings +set auto-media-interface=lo +/interface bridge port +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=Bridge-LAN interface=ether1 +/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=WAN 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 wireguard peers +add allowed-address=0.0.0.0/0,::/0 disabled=yes endpoint-address=172.20.0.2 \ + endpoint-port=51820 interface=wg-awgVDSina name=awgVDSina \ + persistent-keepalive=27s public-key=\ + "o5IgCl1/G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU=" +/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=Bridge-LAN network=10.30.30.0 +add address=172.20.0.1/30 interface=veth-awgVDSina network=172.20.0.0 +add address=10.9.0.2 interface=wg-awgVDSina network=10.9.0.2 +/ip dns +set allow-remote-requests=yes servers=8.8.8.8 +/ip firewall nat +add action=masquerade chain=srcnat src-address=10.9.9.0/24 +add action=dst-nat chain=dstnat disabled=yes dst-port=443 in-interface=ether1 \ + protocol=udp to-addresses=10.9.9.2 to-ports=55055 +add action=dst-nat chain=dstnat disabled=yes 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=\ + 10.30.30.81 routing-table=main scope=30 target-scope=10 +add comment=Monitor-AWGVDSINA distance=1 dst-address=9.9.9.9/32 gateway=\ + wg-awgVDSina +/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=veth-awgVDSina 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/Moscow +/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 +add comment=Generator name=awg-VDSina on-event="# ============================\ + ================================\r\ + \n# AWG Proxy -- MikroTik RouterOS (protocol: v2)\r\ + \n# 2026-07-01 00:03:43\r\ + \n# ============================================================\r\ + \n\r\ + \n# 0. Check prerequisites\r\ + \n:if ([:len [/system/package/find where name=\"container\" disabled=no]] \ + = 0) do={\r\ + \n :put \"Container package is not installed or disabled. Install it and \ + reboot.\"\r\ + \n :error \"Usage: /system/device-mode/update container=yes\"\r\ + \n}\r\ + \n\r\ + \n# Auto-detect storage\r\ + \n:global awgDisk \"disk1\"\r\ + \n{\r\ + \n :local usbFree 0\r\ + \n :do { :set usbFree [/disk/get [find where mount-point=\"usb1\"] free] \ + } on-error={}\r\ + \n :if (\$usbFree > 0) do={\r\ + \n :set awgDisk \"usb1\"\r\ + \n :put (\"Using USB: usb1 (\" . (\$usbFree / 1048576) . \" MB free)\")\ + \r\ + \n } else={\r\ + \n :if ([:len [/disk/find where slot=\"usb1\"]] > 0) do={\r\ + \n :put \"USB found but not mounted. Format as ext4\?\"\r\ + \n :put \"Press 'y' to confirm:\"\r\ + \n :local key [/terminal/inkey timeout=30]\r\ + \n :if (\$key = 121 || \$key = 89) do={\r\ + \n /disk/format-drive usb1 file-system=ext4 label=usb1\r\ + \n :delay 3s\r\ + \n :do { :set usbFree [/disk/get [find where mount-point=\"usb1\"] \ + free] } on-error={}\r\ + \n :if (\$usbFree > 0) do={\r\ + \n :set awgDisk \"usb1\"\r\ + \n } else={ :put \"Format failed, using disk1\" }\r\ + \n } else={ :put \"Using disk1\" }\r\ + \n } else={ :put \"No USB, using disk1\" }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# 1. Uninstall script\r\ + \n/system/script/add name=awg-VDSina-uninstall comment=awg-VDSina source={\ + \r\ + \n :put \"Uninstallimg AmneziaWG...\"\r\ + \n :log info \"Uninstallimg AmneziaWG...\"\r\ + \n :local prevDNS \"\"\r\ + \n :do { :set prevDNS [/container/envs/get [find where list=\"awg-VDSina-\ + env\" key=\"AWG_PREV_DNS\"] value] } on-error={}\r\ + \n :local storageDisk \"disk1\"\r\ + \n :do { :set storageDisk [/container/envs/get [find where list=\"awg-VDS\ + ina-env\" key=\"AWG_STORAGE\"] value] } on-error={}\r\ + \n :local prevTmpdir \"\"\r\ + \n :if (\$storageDisk != \"disk1\") do={\r\ + \n :do { :set prevTmpdir [/container/envs/get [find where list=\"awg-VD\ + Sina-env\" key=\"AWG_PREV_TMPDIR\"] value] } on-error={}\r\ + \n }\r\ + \n /ip/route/remove [find where comment=awg-VDSina-tunnel]\r\ + \n /ip/route/remove [find where comment=awg-VDSina-dns]\r\ + \n /container/stop [find where interface=veth-awg-VDSina]\r\ + \n :delay 7s\r\ + \n /container/remove [find where interface=veth-awg-VDSina]\r\ + \n /container/envs/remove [find where list=\"awg-VDSina-env\"]\r\ + \n :if (\$prevDNS != \"\") do={\r\ + \n :do { /ip/dns/set servers=\"\$prevDNS\" } on-error={}\r\ + \n :put (\"DNS restored to: \$prevDNS\")\r\ + \n }\r\ + \n :if (\$storageDisk != \"disk1\") do={\r\ + \n /container/config set tmpdir=\$prevTmpdir\r\ + \n :put (\"Container tmpdir restored to: \$prevTmpdir\")\r\ + \n }\r\ + \n /ip/firewall/nat/remove [find where out-interface=\"wg-awg-VDSina\"]\r\ + \n /ip/firewall/nat/remove [find where src-address=\"172.19.75.208/30\"]\ + \r\ + \n /ip/address/remove [find where address=\"172.19.75.209/30\"]\r\ + \n /interface/veth/remove [find where name=\"veth-awg-VDSina\"]\r\ + \n /interface/wireguard/peers/remove [find where interface=\"wg-awg-VDSin\ + a\"]\r\ + \n /ip/address/remove [find where interface=\"wg-awg-VDSina\"]\r\ + \n /interface/wireguard/remove [find where name=\"wg-awg-VDSina\"]\r\ + \n :do { /file/remove [find where name~\"awg-VDSina.+tar\"] } on-error={}\ + \r\ + \n :do { /file/remove [find where name=(\$storageDisk . \"/awg-VDSina\")]\ + \_} on-error={}\r\ + \n :do { /file/remove [find where name=(\$storageDisk . \"/ru_ranges_time\ + out.rsc\")] } on-error={}\r\ + \n :if (\$storageDisk != \"disk1\") do={\r\ + \n :do { /file/remove [find where name~(\$storageDisk . \"/pull\")] } o\ + n-error={}\r\ + \n }\r\ + \n :put \"Uninstall AmneziaWG Proxy complete!\"\r\ + \n :log info \"Uninstall AmneziaWG Proxy complete!\"\r\ + \n /system/script/remove [find where name=awg-VDSina-uninstall]\r\ + \n}\r\ + \n\r\ + \n# 2. Network infrastructure\r\ + \n/interface/veth/add name=veth-awg-VDSina address=172.19.75.210/30 gatewa\ + y=172.19.75.209\r\ + \n/ip/address/add address=172.19.75.209/30 interface=veth-awg-VDSina\r\ + \n/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.19.7\ + 5.208/30\r\ + \n\r\ + \n# 3. WireGuard interface (MikroTik derives the public key automatically)\ + \r\ + \n/interface/wireguard/add name=wg-awg-VDSina private-key=\"QCMsDU98Gm+nhn\ + kYRcAN/dyczDYHOLsX3PfBRFjWBF4=\" listen-port=14710 disabled=yes\r\ + \n/interface/wireguard/peers/add interface=wg-awg-VDSina public-key=\"o5Ig\ + Cl1/G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU=\" preshared-key=\"b39T9K2/LR8vNtY\ + AZw+sLRze6yGlS3EaZhAa7wiFB20=\" endpoint-address=172.19.75.210 endpoint-po\ + rt=51820 allowed-address=0.0.0.0/0 persistent-keepalive=10\r\ + \n/ip/address/add address=10.9.0.2/32 interface=wg-awg-VDSina\r\ + \n\r\ + \n# 4. Container environment variables\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_LISTEN value=\":51820\"\ + \r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_REMOTE value=\"109.107.1\ + 77.79:55055\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_JC value=\"9\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_JMIN value=\"105\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_JMAX value=\"920\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S1 value=\"90\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S2 value=\"136\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H1 value=\"472437748-472\ + 438637\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H2 value=\"707808381-707\ + 809250\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H3 value=\"1609078552-16\ + 09079495\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_H4 value=\"1012329484-10\ + 12329741\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_SERVER_PUB value=\"o5IgC\ + l1/G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU=\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_CLIENT_PUB value=[/inter\ + face/wireguard/get [find name=wg-awg-VDSina] public-key]\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S3 value=\"45\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_S4 value=\"27\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I1 value=\"\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I2 value=\"\"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I3 value=\"\ + \"\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I4 value=\"\"\ + \r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_I5 value=\"\"\r\ + \n\r\ + \n# 5. DNS\r\ + \n{ :local rawDNS [/ip/dns/get servers]; :local prevDNS \"\"; :foreach s i\ + n=[:toarray \$rawDNS] do={ :if ([:len \$prevDNS] > 0) do={ :set prevDNS \"\ + \$prevDNS,\$s\" } else={ :set prevDNS \$s } }; /container/envs/add list=aw\ + g-VDSina-env key=AWG_PREV_DNS value=\"\$prevDNS\" }\r\ + \n# NOTE: replaces existing DNS configuration\r\ + \n/ip/dns/set servers=109.107.177.79\r\ + \n/ip/route/add dst-address=109.107.177.79/32 gateway=wg-awg-VDSina distan\ + ce=1 comment=awg-VDSina-dns\r\ + \n\r\ + \n# 6. Download, create and start container\r\ + \n/container/envs/add list=awg-VDSina-env key=AWG_STORAGE value=\$awgDisk\ + \r\ + \n:if (\$awgDisk != \"disk1\") do={\r\ + \n :local tmpPath (\$awgDisk . \"/pull\")\r\ + \n /container/envs/add list=awg-VDSina-env key=AWG_PREV_TMPDIR value=[/co\ + ntainer/config/get tmpdir]\r\ + \n /container/config set tmpdir=\$tmpPath memory-high=200M\r\ + \n}\r\ + \n{\r\ + \n :local arch [/system/resource/get architecture-name]\r\ + \n :local ver [/system/resource/get version]\r\ + \n :local dotPos [:find \$ver \".\"]\r\ + \n :local rest [:pick \$ver (\$dotPos + 1) [:len \$ver]]\r\ + \n :local endPos [:find \$rest \".\"]\r\ + \n :if ([:typeof \$endPos] = \"nil\") do={ :set endPos [:find \$rest \" \ + \"] }\r\ + \n :local minor [:tonum [:pick \$rest 0 \$endPos]]\r\ + \n :local suffix \"\"\r\ + \n :if (\$minor <= 20) do={ :set suffix \"-7.20-Docker\" }\r\ + \n :local file \"\"\r\ + \n :if (\$arch = \"arm64\") do={ :set file (\"awg-proxy-arm64\" . \$suffi\ + x . \".tar.gz\") }\r\ + \n :if (\$arch = \"arm\") do={ :set file (\"awg-proxy-arm\" . \$suffix . \ + \".tar.gz\") }\r\ + \n :if (\$arch ~ \"x86\") do={ :set file (\"awg-proxy-amd64\" . \$suffix \ + . \".tar.gz\") }\r\ + \n :if (\$file = \"\") do={ :error \"Unsupported architecture: \$arch\" }\ + \r\ + \n :local url \"https://github.com/timbrs/amneziawg-mikrotik-c/releases/l\ + atest/download/\$file\"\r\ + \n :local filePath \$file\r\ + \n :if (\$awgDisk != \"disk1\") do={\r\ + \n :set filePath (\$awgDisk . \"/pull/\" . \$file)\r\ + \n :do { /file/make-directory (\$awgDisk . \"/pull\") } on-error={}\r\ + \n }\r\ + \n :if ([:len [/file/find where name=\$filePath]] = 0) do={\r\ + \n :local freeStorage 0\r\ + \n :if (\$awgDisk = \"disk1\") do={\r\ + \n :set freeStorage [/system/resource/get free-hdd-space]\r\ + \n } else={\r\ + \n :do { :set freeStorage [/disk/get [find where mount-point=\$awgDis\ + k] free] } on-error={}\r\ + \n }\r\ + \n :if (\$freeStorage < 262144) do={\r\ + \n :put (\"WARNING: Low disk space (\" . (\$freeStorage / 1024) . \"K\ + B free). Need at least 256KB.\")\r\ + \n :put \"See: https://github.com/timbrs/amneziawg-mikrotik-c#insuffi\ + cient-disk-space\"\r\ + \n :error \"Insufficient disk space\"\r\ + \n }\r\ + \n :put (\"Fetching: \$url -> \" . \$filePath)\r\ + \n /tool/fetch url=\$url dst-path=\$filePath http-max-redirect-count=10\ + \r\ + \n } else={\r\ + \n :put (\"File already exists: \" . \$filePath)\r\ + \n }\r\ + \n :local rootDir (\$awgDisk . \"/awg-VDSina\")\r\ + \n /container/add file=\$filePath interface=veth-awg-VDSina envlist=awg-V\ + DSina-env hostname=awg-VDSina root-dir=\$rootDir logging=no start-on-boot=\ + yes comment=awg-VDSina\r\ + \n :if (\$minor > 20) do={ [:parse \"/container/set [find where interface\ + =veth-awg-VDSina] shm-size=4M\"] }\r\ + \n /file/remove \$filePath\r\ + \n :local freeMem [/system/resource/get free-memory]\r\ + \n :if (\$freeMem < 16777216) do={\r\ + \n :put (\"WARNING: Low memory (\" . (\$freeMem / 1048576) . \"MB free)\ + . 16MB+ recommended.\")\r\ + \n }\r\ + \n /container/start [find where interface=veth-awg-VDSina]\r\ + \n :do { /file/remove [find where name=\"console-dump.txt\"] } on-error={\ + }\r\ + \n :put \"Waiting for container to start...\"\r\ + \n :delay 5s\r\ + \n /interface/wireguard/enable wg-awg-VDSina\r\ + \n :put \"WireGuard interface enabled\"\r\ + \n :put \"Installation complete!\"\r\ + \n :put \"Ping test: 109.107.177.79 via AmneziaWG tunnel. repeat 10 times\ + \"\r\ + \n /ping 109.107.177.79 count=10 interval=1\r\ + \n :put \"\"\r\ + \n :put \"======= NEXT STEPS =======\"\r\ + \n :put \"\"\r\ + \n :put \"Route specific traffic through the AmneziaWG tunnel:\"\r\ + \n :put \"\"\r\ + \n :put \" Route a single host:\"\r\ + \n :put \" /ip/route/add dst-address=8.8.8.8/32 gateway=wg-awg-VDSina \ + comment=awg-VDSina-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Route a subnet:\"\r\ + \n :put \" /ip/route/add dst-address=100.0.0.0/8 gateway=wg-awg-VDSina\ + \_comment=awg-VDSina-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Remove a route:\"\r\ + \n :put \" /ip/route/remove [find where comment=awg-VDSina-tunnel dst-\ + address=8.8.8.8/32]\"\r\ + \n :put \"\"\r\ + \n :put \" Show all tunnel routes:\"\r\ + \n :put \" /ip/route/print where comment=awg-VDSina-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Uninstall:\"\r\ + \n :put \" /system/script/run awg-VDSina-uninstall\"\r\ + \n :put \"=========================\"\r\ + \n}\r\ + \n\r\ + \n# 7. Verification\r\ + \n# /container/print\r\ + \n# /interface/wireguard/print\r\ + \n# /interface/wireguard/peers/print\r\ + \n" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-07-01 start-time=02:03:59 +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool netwatch +add comment=Monitor-AWGVDSINA down-script=\ + "/ip route disable [find comment=\"Route-AWGVDSINA\"]" host=9.9.9.9 \ + interval=10s packet-count=5 thr-avg=0ms thr-loss-count=4 timeout=5s type=\ + icmp up-script="/ip route enable [find comment=\"Route-AWGVDSINA\"]" diff --git a/MikroGig/history/20260705/20260705082311-Diff-Config.rsc b/MikroGig/history/20260705/20260705082311-Diff-Config.rsc new file mode 100644 index 0000000..cbb2e22 --- /dev/null +++ b/MikroGig/history/20260705/20260705082311-Diff-Config.rsc @@ -0,0 +1,14 @@ +11,13c11,12 +< # channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +< set [ find default-name=wlan1 ] country=belarus disabled=no mode=ap-bridge \ +< ssid=vados wps-mode=disabled +--- +> set [ find default-name=wlan1 ] country=belarus mode=ap-bridge ssid=vados \ +> wps-mode=disabled +15,17c14,15 +< # channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +< set [ find default-name=wlan2 ] country=belarus disabled=no mode=ap-bridge \ +< ssid=vados5g wps-mode=disabled +--- +> set [ find default-name=wlan2 ] country=belarus mode=ap-bridge ssid=vados5g \ +> wps-mode=disabled diff --git a/MikroMaster/20260705/20260705080005-Config.rsc b/MikroMaster/20260705/20260705080005-Config.rsc new file mode 100644 index 0000000..08d0150 --- /dev/null +++ b/MikroMaster/20260705/20260705080005-Config.rsc @@ -0,0 +1,3741 @@ +# 2026-07-05 08:00:10 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 +# channel: 2422/20-Ce/gn(18dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] country=belarus disabled=no mode=ap-bridge \ + ssid=vados wireless-protocol=802.11 +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(21dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] country=belarus disabled=no mode=ap-bridge \ + ssid=vados5g wireless-protocol=802.11 +/interface wireguard +add comment=WG disabled=yes listen-port=13231 mtu=1320 name=WG +add comment="WG interface for Amnezia route" listen-port=33033 mtu=1360 name=\ + wg-nuc +/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 disabled=yes dns-servers=1.0.0.1,1.1.1.1 name=blsp.at verify-doh-cert=no +add comment=Kra disabled=yes dns-servers=1.0.0.1,1.1.1.1 name=slon2.to \ + verify-doh-cert=no +add disabled=yes dns-servers=1.1.1.1,1.0.0.1 name=slon3.at verify-doh-cert=no +add disabled=yes dns-servers=1.0.0.1,1.1.1.1 name=slon3.cc verify-doh-cert=no +add disabled=yes dns-servers=1.1.1.1,1.0.0.1 name=bs2web.at verify-doh-cert=\ + no +add disabled=yes dns-servers=1.1.1.1,1.0.0.1 name=bs2best.at verify-doh-cert=\ + no +add disabled=yes 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 +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 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/729/f42d43ae\";\r\ + \n:global CommitTAG \"unknown\";\r\ + \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ + r: root, in 00:05:03 01.07.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}" +add comment=Generator dont-require-permissions=no name=proxySet owner=vados \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="# 2. WireGuard interface\r\ + \n/interface/wireguard/add name=wg-VDSina private-key=\"4CHyNhbOs923/EyNDg\ + uMXJXdghL2I3UyzXPwrANVgHs=\" listen-port=21641\r\ + \n/interface/wireguard/peers/add interface=wg-VDSina public-key=\"o5IgCl1/\ + G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU=\" preshared-key=\"RNvF7T1cg5tyXcYQnD9\ + N5BEp6e20vVJQTv0GMjyvHU0=\" endpoint-address=10.30.30.33 endpoint-port=518\ + 20 allowed-address=0.0.0.0/0 persistent-keepalive=11\r\ + \n/ip/address/add address=10.9.0.3/32 interface=wg-VDSina\r\ + \n\r\ + \n# 3. DNS\r\ + \n{ :local rawDNS [/ip/dns/get servers]; :local prevDNS \"\"; :foreach s i\ + n=[:toarray \$rawDNS] do={ :if ([:len \$prevDNS] > 0) do={ :set prevDNS \"\ + \$prevDNS,\$s\" } else={ :set prevDNS \$s } }; /system/script/add name=VDS\ + ina-prev-dns comment=\"\$prevDNS\" source=\"\" }\r\ + \n/ip/dns/set servers=8.8.4.4\r\ + \n/ip/route/add dst-address=8.8.4.4/32 gateway=wg-VDSina distance=1 commen\ + t=VDSina-dns\r\ + \n\r\ + \n# 4. Enable WireGuard\r\ + \n/interface/wireguard/enable wg-VDSina\r\ + \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="ether1 - Unet" list=Internet +add interface=WG list=WAN +add interface=Bridge-LAN list=LAN +add interface="ether1 - Unet" list=WAN +add interface=wg-nuc list=WAN +/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=" +add allowed-address=0.0.0.0/0 client-allowed-address=::/0 endpoint-address=\ + 10.30.30.33 endpoint-port=55055 interface=wg-nuc name=NUC \ + persistent-keepalive=11s public-key=\ + "+OvzAjLC45Td52hjkQPmpGvC3RGhZ+Q2CDMJ1U/D4Rw=" +/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 +add address=192.168.33.2/24 interface=wg-nuc network=192.168.33.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,clientid_duid \ + 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=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 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.0.0.0/8 list=RFC1918 +add address=172.16.0.0/12 list=RFC1918 +add address=192.168.0.0/16 list=RFC1918 +add address=8.8.4.4 disabled=yes list=to_vpn +add address=myip.ru disabled=yes list=to_vpn +add address=10.30.30.98 disabled=yes list=to_vpn +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new dst-port=53 in-interface="ether1 - Unet" protocol=\ + udp 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 dst-port=29185 in-interface="ether1 - Unet" \ + protocol=tcp +add action=accept chain=input dst-port=29185 in-interface="ether1 - Unet" \ + protocol=udp +add action=accept chain=input comment="tcp Accept input DNS queries from LAN" \ + 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=accept chain=input in-interface="ether1 - Unet" protocol=icmp \ + src-address-list=VDSina +add action=accept chain=input connection-state=established +add action=accept chain=input connection-state=related +/ip firewall mangle +add action=accept chain=prerouting comment=RFC1918 dst-address-list=RFC1918 \ + in-interface-list=!WAN +add action=mark-routing chain=prerouting comment="Mark Routing main for NoWG" \ + 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-connection chain=prerouting comment=\ + "Transit for address-list \"to_vpn\"" connection-mark=no-mark \ + dst-address-list=to_vpn in-interface-list=!WAN new-connection-mark=\ + to-vpn-conn routing-mark=!main +add action=mark-routing chain=prerouting comment=\ + "Find routing over table r_to_vpn" connection-mark=to-vpn-conn \ + in-interface-list=!WAN new-routing-mark=r_to_vpn +add action=mark-routing chain=prerouting comment=\ + "Mark Routing main for VDSina" disabled=yes 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="WG for all" \ + dst-address-list=!NoVdsina new-routing-mark=To-VPN src-address=\ + 10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp routing-mark=To-VPN tcp-flags=syn tcp-mss=\ + 1381-65535 +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" disabled=yes \ + new-connection-mark=VPN_No_FastTrack routing-mark=To-VPN +add action=mark-routing chain=prerouting comment="VPN Network" disabled=yes \ + dst-address=10.8.0.0/24 new-routing-mark=To-VPN src-address=10.30.30.0/24 +add action=mark-connection chain=output comment="For this router" \ + connection-mark=no-mark dst-address-list=to_vpn new-connection-mark=\ + to-vpn-conn-local +add action=mark-routing chain=output comment="For this router" \ + connection-mark=to-vpn-conn-local new-routing-mark=r_to_vpn +/ip firewall nat +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=masquerade chain=srcnat comment=\ + "Nat Addresses for routing mark r_to_vpn" routing-mark=r_to_vpn +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 dst-port=44044 in-interface="ether1 - Unet" \ + protocol=udp src-address=109.107.177.79 to-addresses=10.30.30.33 \ + to-ports=44044 +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=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 disabled=yes 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=yes distance=1 dst-address=0.0.0.0/0 gateway=\ + wg-nuc routing-table=r_to_vpn scope=30 target-scope=10 +add blackhole check-gateway=none disabled=no distance=2 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 +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-secure=no scep-plain=no webfig-plain=no \ + webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required +/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 diff --git a/MikroMaster/tmp/Diff-Config.rsc b/MikroMaster/tmp/Diff-Config.rsc deleted file mode 100644 index d9804fd..0000000 --- a/MikroMaster/tmp/Diff-Config.rsc +++ /dev/null @@ -1,4 +0,0 @@ -3553c3553 -< add check-gateway=none disabled=yes distance=1 dst-address=0.0.0.0/0 gateway=\ ---- -> add check-gateway=none disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\ -- 2.52.0