From 61002d4aa2a9d2a8c4d9a01d9364897aaa3c3783 Mon Sep 17 00:00:00 2001 From: vados-dev Date: Sat, 12 Sep 2026 12:20:09 +0300 Subject: [PATCH] Backup for MikroMaster created successfully at Sep 12 12:20:09. --- .../20260912/20260912122002-Binary.backup | Bin 0 -> 243000 bytes .../20260912/20260912122002-Config.rsc | 4326 +++++++++++++++++ .../20260912/20260912122002-Diff-Config.rsc | 3184 ++++++++++++ 3 files changed, 7510 insertions(+) create mode 100644 MikroMaster/20260912/20260912122002-Binary.backup create mode 100644 MikroMaster/20260912/20260912122002-Config.rsc create mode 100644 MikroMaster/history/20260912/20260912122002-Diff-Config.rsc diff --git a/MikroMaster/20260912/20260912122002-Binary.backup b/MikroMaster/20260912/20260912122002-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..df700570119c4dcd3256c94dc51e8d7efd654f7b GIT binary patch literal 243000 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\"data\");\ + \n\ + \n#/usb1/mikro_bak_rsa.pub\ + \n\ + \n\ + \n#:local FetchFile AM-DOHCert.rsc\ + \n\ + \n\ + \n\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/tmp/\";\ + \n\ + \n:global MkDir;\ + \n\ + \n\ + \n:local FetchFile Manager@id_rsa.pub\ + \n:local localDir \"/\";\ + \n\ + \n\ + \n\ + \n\$MkDir \$localDir;\ + \n\ + \n\ + \n\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \$FetchFile) dst-path=(\ + \$localDir . \$FetchFile);\ + \n" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig-2026-09-1211:58:18.rsc 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 dont-require-permissions=no name=AM-Fetch-Generator owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \n:local srcFile \"AM-Awg-Generator.rsc\";\ + \n:local dstFile \$srcFile;\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \"/\$srcFile\") dst-pat\ + h=\"/\$dstFile\";\ + \n\ + \nexit 0\ + \n#\ + \n\ + \n#root.mnuc.backuper\ + \n\ + \n\ + \n\ + \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\";\ + \n\ + \n\ + \n#:local Script AM-GlobalConfig;\ + \n\ + \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\");\ + \n\ + \n#/usb1/mikro_bak_rsa.pub\ + \n\ + \n\ + \n#:local FetchFile AM-DOHCert.rsc\ + \n\ + \n\ + \n\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/tmp/\";\ + \n\ + \n:global MkDir;\ + \n\ + \n\ + \n:local FetchFile Manager@id_rsa.pub\ + \n:local localDir \"/\";\ + \n\ + \n\ + \n\ + \n\$MkDir \$localDir;\ + \n\ + \n\ + \n\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \$FetchFile) dst-path=(\ + \$localDir . \$FetchFile);\ + \n" +add comment=awg2vds dont-require-permissions=no name=awg2vds-uninstall owner=\ + vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \n :put \"Uninstallimg AmneziaWG...\"\ + \n :log info \"Uninstallimg AmneziaWG...\"\ + \n :local prevDNS \"\"\ + \n :do { :set prevDNS [/container/envs/get [find where list=\"awg2vds-env\ + \" key=\"AWG_PREV_DNS\"] value] } on-error={}\ + \n :local prevTmpdir \"\"\ + \n :do { :set prevTmpdir [/container/envs/get [find where list=\"awg2vds-\ + env\" key=\"AWG_PREV_TMPDIR\"] value] } on-error={}\ + \n /ip/route/remove [find where comment=awg2vds-tunnel]\ + \n /ip/route/remove [find where comment=awg2vds-dns]\ + \n /container/stop [find where interface=veth-awg2vds]\ + \n :delay 7s\ + \n /container/remove [find where interface=veth-awg2vds]\ + \n /container/envs/remove [find where list=\"awg2vds-env\"]\ + \n :if (\$prevDNS != \"\") do={\ + \n :do { /ip/dns/set servers=\"\$prevDNS\" } on-error={}\ + \n :put (\"DNS restored to: \$prevDNS\")\ + \n }\ + \n /container/config set tmpdir=\$prevTmpdir\ + \n :put (\"Container tmpdir restored to: \$prevTmpdir\")\ + \n /ip/firewall/nat/remove [find where out-interface=\"wg-awg2vds\"]\ + \n /ip/firewall/nat/remove [find where src-address=\"172.20.200.68/30\"]\ + \n /ip/address/remove [find where address=\"172.20.200.69/30\"]\ + \n /interface/veth/remove [find where name=\"veth-awg2vds\"]\ + \n /interface/wireguard/peers/remove [find where interface=\"wg-awg2vds\"\ + ]\ + \n /ip/address/remove [find where interface=\"wg-awg2vds\"]\ + \n /interface/wireguard/remove [find where name=\"wg-awg2vds\"]\ + \n :do { /file/remove [find where name~\"awg2vds.+tar\"] } on-error={}\ + \n :do { /file/remove [find where name=\"usb1/awg2vds\"] } on-error={}\ + \n :do { /file/remove [find where name=\"usb1/ru_ranges_timeout.rsc\"] } \ + on-error={}\ + \n :do { /file/remove [find where name~\"usb1/pull\"] } on-error={}\ + \n :put \"Uninstall AmneziaWG Proxy complete!\"\ + \n :log info \"Uninstall AmneziaWG Proxy complete!\"\ + \n /system/script/remove [find where name=awg2vds-uninstall]\ + \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/16716/73429726\";\r\ + \n:global CommitTAG \"unknown\";\r\ + \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ + r: root, in 12:00:05 12.09.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="awg3vds installer" dont-require-permissions=no name=\ + AM-awg3vdsInstall owner=AM-awg3vdsInstall policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-awg3vdsInstall\r\ + \n# Script comment: awg3vds installer\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n# ============================================================\r\ + \n# AWG Proxy -- MikroTik RouterOS (protocol: v3)\r\ + \n# 2026-09-12 08:41:48\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# Check storage device\r\ + \n{\r\ + \n :local targetDisk \"usb1\"\r\ + \n :local diskFree 0\r\ + \n :do { :set diskFree [/disk/get [find where mount-point=\$targetDisk] f\ + ree] } on-error={}\r\ + \n :if (\$diskFree = 0) do={\r\ + \n :local baseDisk \$targetDisk\r\ + \n :local dashPos [:find \$targetDisk \"-part\"]\r\ + \n :if ([:typeof \$dashPos] != \"nil\") do={ :set baseDisk [:pick \$tar\ + getDisk 0 \$dashPos] }\r\ + \n :if ([:len [/disk/find where slot=\$baseDisk]] > 0) do={\r\ + \n :put (\"Device \$baseDisk found but \$targetDisk is not available.\ + \")\r\ + \n :put \"Format \$baseDisk as ext4\? ALL DATA WILL BE ERASED!\"\r\ + \n :put \"Press 'y' to confirm, any other key to cancel:\"\r\ + \n :local key [/terminal/inkey timeout=30]\r\ + \n :if (\$key = 121 || \$key = 89) do={\r\ + \n :put \"Formatting \$baseDisk as ext4...\"\r\ + \n /disk/format-drive \$baseDisk file-system=ext4 label=\$baseDisk\ + \r\ + \n :delay 3s\r\ + \n :do { :set diskFree [/disk/get [find where mount-point=\$targetD\ + isk] free] } on-error={}\r\ + \n :if (\$diskFree = 0) do={\r\ + \n :put (\"ERROR: \$targetDisk not found after formatting.\")\r\ + \n :put \"Check mount point: /disk/print\"\r\ + \n :error (\"Mount point \$targetDisk not found after formatting\ + \")\r\ + \n }\r\ + \n :put (\"Formatted OK. Free: \" . (\$diskFree / 1048576) . \" MB\ + \")\r\ + \n } else={\r\ + \n :error \"Formatting cancelled\"\r\ + \n }\r\ + \n } else={\r\ + \n :put (\"ERROR: Storage device \$targetDisk not found.\")\r\ + \n :put \"Check available disks: /disk/print\"\r\ + \n :error (\"Storage not found: \" . \$targetDisk)\r\ + \n }\r\ + \n } else={\r\ + \n :put (\"Storage OK: \$targetDisk (\" . (\$diskFree / 1048576) . \" M\ + B free)\")\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# 1. Uninstall and update scripts\r\ + \n/system/script/add name=awg3vds-uninstall comment=awg3vds 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=\"awg3vds-env\ + \" key=\"AWG_PREV_DNS\"] value] } on-error={}\r\ + \n :local prevTmpdir \"\"\r\ + \n :do { :set prevTmpdir [/container/envs/get [find where list=\"awg3vds-\ + env\" key=\"AWG_PREV_TMPDIR\"] value] } on-error={}\r\ + \n /ip/route/remove [find where comment=awg3vds-tunnel]\r\ + \n /ip/route/remove [find where comment=awg3vds-dns]\r\ + \n :do { /system/scheduler/remove [find where comment~\"awg3vds\"] } on-e\ + rror={}\r\ + \n :do { /system/script/remove [find where comment~\"awg3vds\" and name!=\ + \"awg3vds-uninstall\"] } on-error={}\r\ + \n /container/stop [find where interface=veth-awg3vds]\r\ + \n :delay 7s\r\ + \n /container/remove [find where interface=veth-awg3vds]\r\ + \n /container/envs/remove [find where list=\"awg3vds-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 /container/config set tmpdir=\$prevTmpdir\r\ + \n :put (\"Container tmpdir restored to: \$prevTmpdir\")\r\ + \n /ip/firewall/nat/remove [find where out-interface=\"wg-awg3vds\"]\r\ + \n /ip/firewall/nat/remove [find where src-address=\"172.19.14.100/30\"]\ + \r\ + \n /ip/address/remove [find where address=\"172.19.14.101/30\"]\r\ + \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-v6-nat] } \ + on-error={}\r\ + \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-dstnat6] }\ + \_on-error={}\r\ + \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-v6-out]\ + \_} on-error={}\r\ + \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-awg-in6\ + ] } on-error={}\r\ + \n :do { /ipv6/nd/remove [find where interface=veth-awg3vds] } on-error={\ + }\r\ + \n :do { /ipv6/nd/prefix/remove [find where interface=veth-awg3vds] } on-\ + error={}\r\ + \n :do { /ipv6/address/remove [find where comment=awg3vds-v6] } on-error=\ + {}\r\ + \n /interface/veth/remove [find where name=\"veth-awg3vds\"]\r\ + \n /interface/wireguard/peers/remove [find where interface=\"wg-awg3vds\"\ + ]\r\ + \n /ip/address/remove [find where interface=\"wg-awg3vds\"]\r\ + \n /interface/wireguard/remove [find where name=\"wg-awg3vds\"]\r\ + \n :do { /file/remove [find where name~\"awg3vds.+tar\"] } on-error={}\r\ + \n :do { /file/remove [find where name=\"usb1/awg3vds\"] } on-error={}\r\ + \n :do { /file/remove [find where name=\"usb1/ru_ranges_timeout.rsc\"] } \ + on-error={}\r\ + \n :do { /file/remove [find where name=\"usb1/ru_ranges.rsc\"] } on-error\ + ={}\r\ + \n :do { /file/remove [find where name~\"usb1/pull\"] } 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=awg3vds-uninstall]\r\ + \n}\r\ + \n/system/script/add name=awg3vds-update comment=awg3vds source={\r\ + \n :local cids [/container/find where interface=veth-awg3vds and !stopped\ + ]\r\ + \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ + e=veth-awg3vds and start-on-boot=yes] }\r\ + \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ + e=veth-awg3vds] }\r\ + \n :if ([:len \$cids] = 0) do={\r\ + \n :put \"Container awg3vds not found\"\r\ + \n :log warning \"awg3vds-update: container not found\"\r\ + \n } else={\r\ + \n :local cid [:pick \$cids ([:len \$cids] - 1)]\r\ + \n :local img [/container/get \$cid remote-image]\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 wantRunning true\r\ + \n :do { :if ([/container/get \$cid start-on-boot] != true) do={ :set w\ + antRunning false } } on-error={}\r\ + \n :local healthy true\r\ + \n :if ([:len [/container/get \$cid image-id]] = 0) do={ :set healthy f\ + alse }\r\ + \n :if (\$wantRunning) do={\r\ + \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ + y false } } on-error={}\r\ + \n }\r\ + \n :if (!\$healthy && \$wantRunning && [:len [/container/get \$cid imag\ + e-id]] > 0) do={\r\ + \n :put \"Container is down - trying to start it\"\r\ + \n :do { /container/start \$cid } on-error={}\r\ + \n :delay 8s\r\ + \n :set healthy true\r\ + \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ + y false } } on-error={}\r\ + \n :if (\$healthy) do={\r\ + \n :put \"Container is back up\"\r\ + \n :log info \"awg3vds: container restarted by the update script\"\ + \r\ + \n }\r\ + \n }\r\ + \n :if (\$img = \"\" && \$minor >= 22 && !\$healthy) do={\r\ + \n :local imgTag \"latest\"\r\ + \n :local rbModel \"\"\r\ + \n :do { :set rbModel [[:parse \":return [/system/routerboard/get mod\ + el]\"]] } on-error={}\r\ + \n :local bName [/system/resource/get board-name]\r\ + \n :if (\$rbModel~\"E50UG\" || \$rbModel~\"E60iUGS\" || \$bName~\"E50\ + UG\" || \$bName~\"E60iUGS\" || \$bName~\"^hEX\") do={\r\ + \n :set imgTag \"latest-armv5\"\r\ + \n }\r\ + \n :set img (\"ghcr.io/timbrs/awg-proxy:\" . \$imgTag)\r\ + \n :put (\"Container is down and was installed from a file - pointing\ + \_it at \" . \$img)\r\ + \n :log warning \"awg3vds-update: broken file install, switching to t\ + he registry\"\r\ + \n :do { /container/set \$cid remote-image=\$img } on-error={}\r\ + \n }\r\ + \n :if (\$img = \"\") do={\r\ + \n :put \"Installed from a local image file - /container/repull only \ + updates registry installs.\"\r\ + \n :put \"Reinstall with the configurator on RouterOS 7.22+ to switch\ + \_to one-command updates.\"\r\ + \n } else={\r\ + \n :if (\$minor < 22) do={\r\ + \n :put (\"/container/repull needs RouterOS 7.22+, this router runs\ + \_\" . \$ver)\r\ + \n :if (!\$healthy) do={ :log error (\"awg3vds-update: container is\ + \_down, and \" . \$ver . \" has no /container/repull\") }\r\ + \n } else={\r\ + \n :local rootDir [/container/get \$cid root-dir]\r\ + \n :if ([:pick \$rootDir 0 1] = \"/\") do={ :set rootDir [:pick \$r\ + ootDir 1 [:len \$rootDir]] }\r\ + \n :local rootDirOrig \$rootDir\r\ + \n :local slashPos [:find \$rootDir \"/\"]\r\ + \n :local disk \$rootDir\r\ + \n :if ([:typeof \$slashPos] != \"nil\") do={ :set disk [:pick \$ro\ + otDir 0 \$slashPos] }\r\ + \n :local verPath \"awg-update-check.json\"\r\ + \n :if (\$disk != \"disk1\") do={\r\ + \n :do { /file/make-directory (\$disk . \"/pull\") } on-error={}\ + \r\ + \n /container/config set tmpdir=(\$disk . \"/pull\")\r\ + \n :set verPath (\$disk . \"/pull/awg-update-check.json\")\r\ + \n }\r\ + \n :local newVer \"\"\r\ + \n :do {\r\ + \n /tool/fetch url=\"https://api.github.com/repos/timbrs/amneziaw\ + g-mikrotik-c/releases/latest\" dst-path=\$verPath http-max-redirect-count=\ + 10\r\ + \n :local relJson [/file/get [find where name=\$verPath] contents\ + ]\r\ + \n :local tagPos [:find \$relJson \"\\\"tag_name\\\":\\\"\"]\r\ + \n :if ([:typeof \$tagPos] != \"nil\") do={\r\ + \n :local tagRest [:pick \$relJson (\$tagPos + 12) [:len \$relJ\ + son]]\r\ + \n :set newVer [:pick \$tagRest 0 [:find \$tagRest \"\\\"\"]]\r\ + \n }\r\ + \n :do { /file/remove [find where name=\$verPath] } on-error={}\r\ + \n } on-error={ :put \"Could not read the published version\" }\r\ + \n :local curVer \"\"\r\ + \n :do { :set curVer [/container/envs/get [find where list=\"awg3vd\ + s-env\" key=\"AWG_IMAGE_VER\"] value] } on-error={}\r\ + \n :local doPull true\r\ + \n :if (\$healthy) do={\r\ + \n :if (\$newVer = \"\") do={\r\ + \n :set doPull false\r\ + \n :put \"Published version unknown - leaving the healthy conta\ + iner alone\"\r\ + \n }\r\ + \n :if (\$newVer != \"\" && \$newVer = \$curVer) do={\r\ + \n :set doPull false\r\ + \n :put (\"Already on \" . \$curVer . \" - nothing to pull, tun\ + nel untouched\")\r\ + \n }\r\ + \n }\r\ + \n :if (\$doPull) do={\r\ + \n :if (!\$healthy) do={\r\ + \n :put \"Container is not healthy - pulling the image again\"\ + \r\ + \n :log warning \"awg3vds-update: container unhealthy, forcing \ + a pull\"\r\ + \n }\r\ + \n :put (\"Updating \" . \$img . \" ...\")\r\ + \n :log info \"awg3vds: repull started\"\r\ + \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ + p\")] } on-error={}\r\ + \n :do { [:parse \"/container/set \$cid ignore-remote-image-chang\ + e=yes\"] } on-error={}\r\ + \n /container/repull \$cid\r\ + \n :local waited 0\r\ + \n :while ([:len [/container/get \$cid image-id]] = 0 && \$waited\ + \_< 180) do={\r\ + \n :delay 3s\r\ + \n :set waited (\$waited + 3)\r\ + \n }\r\ + \n :if ([:len [/container/get \$cid image-id]] = 0) do={\r\ + \n :put \"Pull failed - retrying once in 15s\"\r\ + \n :delay 15s\r\ + \n /container/repull \$cid\r\ + \n :set waited 0\r\ + \n :while ([:len [/container/get \$cid image-id]] = 0 && \$wait\ + ed < 180) do={\r\ + \n :delay 3s\r\ + \n :set waited (\$waited + 3)\r\ + \n }\r\ + \n }\r\ + \n :local backUp false\r\ + \n :if ([:len [/container/get \$cid image-id]] > 0) do={\r\ + \n :set backUp true\r\ + \n :if (\$wantRunning) do={\r\ + \n :delay 3s\r\ + \n :do { /container/start \$cid } on-error={}\r\ + \n :delay 8s\r\ + \n :set backUp false\r\ + \n :do { :if ([/container/get \$cid stopped] != true) do={ :s\ + et backUp true } } on-error={}\r\ + \n }\r\ + \n }\r\ + \n :if (!\$backUp) do={\r\ + \n :put \"Container did not come back up - rebuilding it from t\ + he registry\"\r\ + \n :log warning \"awg3vds-update: container did not come back, \ + rebuilding\"\r\ + \n :do { /container/stop \$cid } on-error={}\r\ + \n :delay 5s\r\ + \n :do { /container/remove \$cid } on-error={}\r\ + \n :delay 3s\r\ + \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.bac\ + kup\")] } on-error={}\r\ + \n :do { /container/add remote-image=\$img interface=veth-awg3v\ + ds envlist=awg3vds-env hostname=awg3vds root-dir=\$rootDirOrig logging=no \ + start-on-boot=yes comment=awg3vds } on-error={}\r\ + \n :set waited 0\r\ + \n :local newCids [/container/find where interface=veth-awg3vds\ + \_and start-on-boot=yes]\r\ + \n :if ([:len \$newCids] = 0) do={ :set newCids [/container/fin\ + d where interface=veth-awg3vds] }\r\ + \n :while ([:len \$newCids] > 0 && [:len [/container/get [:pick\ + \_\$newCids ([:len \$newCids] - 1)] image-id]] = 0 && \$waited < 180) do={\ + \r\ + \n :delay 3s\r\ + \n :set waited (\$waited + 3)\r\ + \n }\r\ + \n :if ([:len \$newCids] > 0 && [:len [/container/get [:pick \$\ + newCids ([:len \$newCids] - 1)] image-id]] > 0) do={\r\ + \n :do { /container/set [:pick \$newCids ([:len \$newCids] - \ + 1)] shm-size=4M } on-error={}\r\ + \n :do { [:parse \"/container/set [find where interface=veth-\ + awg3vds] ignore-remote-image-change=yes\"] } on-error={}\r\ + \n :do { [:parse \"/container/set [find where interface=veth-\ + awg3vds] restart-policy=on-failure restart-interval=30s restart-max-count=\ + 10\"] } on-error={}\r\ + \n :do { /container/start [:pick \$newCids ([:len \$newCids] \ + - 1)] } on-error={}\r\ + \n :delay 8s\r\ + \n :do { :if ([/container/get [:pick \$newCids ([:len \$newCi\ + ds] - 1)] stopped] != true) do={ :set backUp true } } on-error={}\r\ + \n }\r\ + \n :if (\$backUp) do={\r\ + \n :put \"Container rebuilt\"\r\ + \n :log info \"awg3vds: container rebuilt after update\"\r\ + \n } else={\r\ + \n :put \"Rebuild failed - the tunnel is down. Netwatch keeps\ + \_the router online meanwhile.\"\r\ + \n :put \"This script runs again on the next schedule and wil\ + l retry.\"\r\ + \n :log error \"awg3vds-update: rebuild failed, tunnel is dow\ + n\"\r\ + \n }\r\ + \n }\r\ + \n :if (\$backUp && \$newVer != \"\") do={\r\ + \n :do { /container/envs/remove [find where list=\"awg3vds-env\ + \" key=\"AWG_IMAGE_VER\"] } on-error={}\r\ + \n :do { /container/envs/add list=awg3vds-env key=AWG_IMAGE_VER\ + \_value=\$newVer } on-error={}\r\ + \n }\r\ + \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ + p\")] } on-error={}\r\ + \n :if (\$backUp) do={\r\ + \n :put (\"Update done: \" . \$img)\r\ + \n :log info \"awg3vds: update done\"\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n# Daily update check. Skipped if scheduler is not allowed by device-mode\ + \r\ + \n{\r\ + \n :local schedOk true\r\ + \n :do { :set schedOk [/system/device-mode/get scheduler] } on-error={}\r\ + \n :if (\$schedOk) do={\r\ + \n /system/scheduler/add name=awg3vds-update on-event=\"/system/script/\ + run awg3vds-update\" start-time=04:30:00 interval=1d comment=awg3vds\r\ + \n } else={\r\ + \n :put \"WARNING: scheduler not allowed by device-mode, no daily updat\ + e check.\"\r\ + \n :put \"Update by hand: /system/script/run awg3vds-update\"\r\ + \n :put \"To allow it: /system/device-mode/update scheduler=yes\"\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# 2. Network infrastructure\r\ + \n/interface/veth/add name=veth-awg3vds address=172.19.14.102/30 gateway=1\ + 72.19.14.101\r\ + \n/ip/address/add address=172.19.14.101/30 interface=veth-awg3vds\r\ + \n/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.19.1\ + 4.100/30\r\ + \n\r\ + \n# 3. WireGuard interface (MikroTik derives the public key automatically)\ + \r\ + \n/interface/wireguard/add name=wg-awg3vds private-key=\"AEU+diR7SCIEOtwOW\ + SWR3pEpkw6v0Qro2LRF0SnPpnw=\" listen-port=41430 mtu=1320 disabled=yes\r\ + \n/interface/wireguard/peers/add interface=wg-awg3vds public-key=\"MMWjD/T\ + PNpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=\" preshared-key=\"r9B13bB7gUTqde6zgB\ + DfffFIUN6puP2gOWdK5zVS3nw=\" endpoint-address=172.19.14.102 endpoint-port=\ + 51820 allowed-address=10.31.31.0/24,0.0.0.0/0 persistent-keepalive=14\r\ + \n/ip/address/add address=10.31.31.2/24 interface=wg-awg3vds\r\ + \n\r\ + \n# 4. Container environment variables\r\ + \n/container/envs/add list=awg3vds-env key=AWG_LISTEN value=\":51820\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_REMOTE value=\"89.110.101.1\ + 7:31031\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_JC value=\"5\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_JMIN value=\"510\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_JMAX value=\"952\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_S1 value=\"138\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_S2 value=\"105\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_H1 value=\"457615290-457646\ + 150\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_H2 value=\"1307355386-13073\ + 63580\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_H3 value=\"2441734303-24417\ + 81787\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_H4 value=\"3719180788-37191\ + 95844\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_SERVER_PUB value=\"MMWjD/TP\ + NpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_CLIENT_PUB value=[/interfac\ + e/wireguard/get [find name=wg-awg3vds] public-key]\r\ + \n/container/envs/add list=awg3vds-env key=AWG_S3 value=\"51\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_S4 value=\"22\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_I1 value=\"\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_I2 value=\"\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_I3 value=\"\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_I4 value=\"\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_I5 value=\"\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_HEADER_PROTECTION_KEY value\ + =\"FkGxbrW6ds3YPWNl48OWFEccrLC4tF94z9MnoKUZUsM=\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_CONTENT_PADDING value=\"54-\ + 119\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_REKEY_AFTER value=\"102-130\ + \"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_REKEY_TIMEOUT value=\"6-8\"\ + \r\ + \n/container/envs/add list=awg3vds-env key=AWG_REJECT_AFTER value=\"174-19\ + 5\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_KEEPALIVE_TIMEOUT value=\"1\ + 4-21\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_MAX_HANDSHAKE_ATTEMPTS valu\ + e=\"12-14\"\r\ + \n/container/envs/add list=awg3vds-env key=AWG_NO_DF value=\"1\"\r\ + \n# Perf: give each forwarding thread its own core (4+ core routers)\r\ + \n{ :if ([/system/resource/get cpu-count] >= 4) do={ /container/envs/add l\ + ist=awg3vds-env key=AWG_CPU_C2S value=\"1\"; /container/envs/add list=awg3\ + vds-env key=AWG_CPU_S2C value=\"2\" } }\r\ + \n# NOTE on MTU: the value above assumes this tunnel is the last hop.\r\ + \n# If the server forwards your traffic into another tunnel, subtract\r\ + \n# that tunnel's overhead too, or every packet leaves in two fragments.\ + \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\ + g3vds-env key=AWG_PREV_DNS value=\"\$prevDNS\" }\r\ + \n# NOTE: replaces existing DNS configuration\r\ + \n/ip/dns/set servers=89.110.101.17,8.8.4.4\r\ + \n# DNS 89.110.101.17 \D0\B8\D0\B4\D1\91\D1\82 \D0\BE\D0\B1\D1\89\D0\B8\D0\ + \BC \D0\BC\D0\B0\D1\80\D1\88\D1\80\D1\83\D1\82\D0\BE\D0\BC (\D0\B2 \D0\B0\ + \D0\BA\D1\82\D0\B8\D0\B2\D0\BD\D1\8B\D0\B9 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\ + \D0\BB\D1\8C / default),\r\ + \n# \D0\B1\D0\B5\D0\B7 \D0\BF\D1\80\D0\B8\D0\B2\D1\8F\D0\B7\D0\BA\D0\B8 \ + \D0\BA wg-awg3vds: \D0\B8\D0\BD\D0\B0\D1\87\D0\B5 \D0\BF\D0\B0\D0\B4\D0\B5\ + \D0\BD\D0\B8\D0\B5 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\D0\BB\D1\8F \D1\83\D0\BD\ + \D0\BE\D1\81\D0\B8\D1\82 \D1\81 \D1\81\D0\BE\D0\B1\D0\BE\D0\B9 \D1\80\D0\ + \B5\D0\B7\D0\BE\D0\BB\D0\B2.\r\ + \n# DNS 8.8.4.4 \D0\B8\D0\B4\D1\91\D1\82 \D0\BE\D0\B1\D1\89\D0\B8\D0\BC \ + \D0\BC\D0\B0\D1\80\D1\88\D1\80\D1\83\D1\82\D0\BE\D0\BC (\D0\B2 \D0\B0\D0\ + \BA\D1\82\D0\B8\D0\B2\D0\BD\D1\8B\D0\B9 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\D0\ + \BB\D1\8C / default),\r\ + \n# \D0\B1\D0\B5\D0\B7 \D0\BF\D1\80\D0\B8\D0\B2\D1\8F\D0\B7\D0\BA\D0\B8 \ + \D0\BA wg-awg3vds: \D0\B8\D0\BD\D0\B0\D1\87\D0\B5 \D0\BF\D0\B0\D0\B4\D0\B5\ + \D0\BD\D0\B8\D0\B5 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\D0\BB\D1\8F \D1\83\D0\BD\ + \D0\BE\D1\81\D0\B8\D1\82 \D1\81 \D1\81\D0\BE\D0\B1\D0\BE\D0\B9 \D1\80\D0\ + \B5\D0\B7\D0\BE\D0\BB\D0\B2.\r\ + \n\r\ + \n# 6. Download, create and start container\r\ + \n:local prevTmpdir [/container/config/get tmpdir]\r\ + \n/container/envs/add list=awg3vds-env key=AWG_PREV_TMPDIR value=\$prevTmp\ + dir\r\ + \n/container/config set tmpdir=usb1/pull memory-high=200M\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 :local imgTag \"latest\"\r\ + \n :if (\$arch = \"arm64\") do={ :set file (\"awg-proxy-arm64\" . \$suffi\ + x . \".tar.gz\") }\r\ + \n :if (\$arch = \"arm\") do={\r\ + \n :set file (\"awg-proxy-arm\" . \$suffix . \".tar.gz\")\r\ + \n :local rbModel \"\"\r\ + \n :do { :set rbModel [[:parse \":return [/system/routerboard/get model\ + ]\"]] } on-error={}\r\ + \n :local bName [/system/resource/get board-name]\r\ + \n :if (\$rbModel~\"E50UG\" || \$rbModel~\"E60iUGS\" || \$bName~\"E50UG\ + \" || \$bName~\"E60iUGS\" || \$bName~\"^hEX\") do={\r\ + \n :set file (\"awg-proxy-armv5\" . \$suffix . \".tar.gz\")\r\ + \n :set imgTag \"latest-armv5\"\r\ + \n }\r\ + \n }\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 (\"usb1/pull/\" . \$file)\r\ + \n :local altPath (\"usb1/\" . \$file)\r\ + \n :local rootDir \"usb1/awg3vds\"\r\ + \n :do { /file/make-directory usb1/pull } on-error={}\r\ + \n :if ([:len [/file/find where name=\$filePath]] = 0 && [:len [/file/fin\ + d where name=\$altPath]] > 0) do={\r\ + \n :set filePath \$altPath\r\ + \n }\r\ + \n :local added false\r\ + \n :local fetched false\r\ + \n :if ([:len [/file/find where name=\$filePath]] > 0) do={\r\ + \n :put (\"Using image already on the router: \" . \$filePath)\r\ + \n /container/add file=\$filePath interface=veth-awg3vds envlist=awg3vd\ + s-env hostname=awg3vds root-dir=\$rootDir logging=no start-on-boot=yes com\ + ment=awg3vds\r\ + \n :set added true\r\ + \n }\r\ + \n :if (!\$added && \$minor >= 22) do={\r\ + \n :local img (\"ghcr.io/timbrs/awg-proxy:\" . \$imgTag)\r\ + \n :put (\"Pulling \" . \$img)\r\ + \n /container/add remote-image=\$img interface=veth-awg3vds envlist=awg\ + 3vds-env hostname=awg3vds root-dir=\$rootDir logging=no start-on-boot=yes \ + comment=awg3vds\r\ + \n :local cids [/container/find where interface=veth-awg3vds]\r\ + \n :local waited 0\r\ + \n :while ([:len \$cids] > 0 && [:len [/container/get [:pick \$cids 0] \ + image-id]] = 0 && \$waited < 120) do={\r\ + \n :delay 2s\r\ + \n :set waited (\$waited + 2)\r\ + \n }\r\ + \n :if ([:len \$cids] > 0 && [:len [/container/get [:pick \$cids 0] ima\ + ge-id]] > 0) do={\r\ + \n :set added true\r\ + \n :put (\"Pulled from registry in \" . \$waited . \"s\")\r\ + \n :do {\r\ + \n :local verPath (\$filePath . \".rel\")\r\ + \n /tool/fetch url=\"https://api.github.com/repos/timbrs/amneziawg-\ + mikrotik-c/releases/latest\" dst-path=\$verPath http-max-redirect-count=10\ + \r\ + \n :local relJson [/file/get [find where name=\$verPath] contents]\ + \r\ + \n :local tagPos [:find \$relJson \"\\\"tag_name\\\":\\\"\"]\r\ + \n :local tagRest [:pick \$relJson (\$tagPos + 12) [:len \$relJson]\ + ]\r\ + \n /container/envs/add list=awg3vds-env key=AWG_IMAGE_VER value=[:p\ + ick \$tagRest 0 [:find \$tagRest \"\\\"\"]]\r\ + \n /file/remove [find where name=\$verPath]\r\ + \n } on-error={}\r\ + \n } else={\r\ + \n :put \"Registry unavailable, falling back to the release archive\"\ + \r\ + \n :do { /container/remove \$cids } on-error={}\r\ + \n :delay 2s\r\ + \n }\r\ + \n }\r\ + \n :if (!\$added) do={\r\ + \n :local freeStorage 0\r\ + \n :do { :set freeStorage [/disk/get [find where mount-point=\"usb1\"] \ + free] } on-error={}\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 /container/add file=\$filePath interface=veth-awg3vds envlist=awg3vd\ + s-env hostname=awg3vds root-dir=\$rootDir logging=no start-on-boot=yes com\ + ment=awg3vds\r\ + \n :set fetched true\r\ + \n }\r\ + \n :if (\$minor > 20) do={ [:parse \"/container/set [find where interface\ + =veth-awg3vds] shm-size=4M\"] }\r\ + \n :do { [:parse \"/container/set [find where interface=veth-awg3vds] ign\ + ore-remote-image-change=yes\"] } on-error={}\r\ + \n :do { [:parse \"/container/set [find where interface=veth-awg3vds] res\ + tart-policy=on-failure restart-interval=30s restart-max-count=10\"] } on-e\ + rror={}\r\ + \n :if (\$fetched) do={ /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-awg3vds]\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-awg3vds\r\ + \n :put \"WireGuard interface enabled\"\r\ + \n :put \"Installation complete!\"\r\ + \n :put \"Ping test: 89.110.101.17 via AmneziaWG tunnel. repeat 10 times\ + \"\r\ + \n /ping 89.110.101.17 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-awg3vds com\ + ment=awg3vds-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-awg3vds co\ + mment=awg3vds-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Remove a route:\"\r\ + \n :put \" /ip/route/remove [find where comment=awg3vds-tunnel dst-add\ + ress=8.8.8.8/32]\"\r\ + \n :put \"\"\r\ + \n :put \" Show all tunnel routes:\"\r\ + \n :put \" /ip/route/print where comment=awg3vds-tunnel\"\r\ + \n :put \"\"\r\ + \n :put \" Update the container:\"\r\ + \n :put \" /system/script/run awg3vds-update\"\r\ + \n :put \"\"\r\ + \n :put \" Uninstall:\"\r\ + \n :put \" /system/script/run awg3vds-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=awg3vds dont-require-permissions=no name=awg3vds-uninstall owner=\ + vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon 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=\"awg3vds-env\ + \" key=\"AWG_PREV_DNS\"] value] } on-error={}\r\ + \n :local prevTmpdir \"\"\r\ + \n :do { :set prevTmpdir [/container/envs/get [find where list=\"awg3vds-\ + env\" key=\"AWG_PREV_TMPDIR\"] value] } on-error={}\r\ + \n /ip/route/remove [find where comment=awg3vds-tunnel]\r\ + \n /ip/route/remove [find where comment=awg3vds-dns]\r\ + \n :do { /system/scheduler/remove [find where comment~\"awg3vds\"] } on-e\ + rror={}\r\ + \n :do { /system/script/remove [find where comment~\"awg3vds\" and name!=\ + \"awg3vds-uninstall\"] } on-error={}\r\ + \n /container/stop [find where interface=veth-awg3vds]\r\ + \n :delay 7s\r\ + \n /container/remove [find where interface=veth-awg3vds]\r\ + \n /container/envs/remove [find where list=\"awg3vds-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 /container/config set tmpdir=\$prevTmpdir\r\ + \n :put (\"Container tmpdir restored to: \$prevTmpdir\")\r\ + \n /ip/firewall/nat/remove [find where out-interface=\"wg-awg3vds\"]\r\ + \n /ip/firewall/nat/remove [find where src-address=\"172.19.14.100/30\"]\ + \r\ + \n /ip/address/remove [find where address=\"172.19.14.101/30\"]\r\ + \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-v6-nat] } \ + on-error={}\r\ + \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-dstnat6] }\ + \_on-error={}\r\ + \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-v6-out]\ + \_} on-error={}\r\ + \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-awg-in6\ + ] } on-error={}\r\ + \n :do { /ipv6/nd/remove [find where interface=veth-awg3vds] } on-error={\ + }\r\ + \n :do { /ipv6/nd/prefix/remove [find where interface=veth-awg3vds] } on-\ + error={}\r\ + \n :do { /ipv6/address/remove [find where comment=awg3vds-v6] } on-error=\ + {}\r\ + \n /interface/veth/remove [find where name=\"veth-awg3vds\"]\r\ + \n /interface/wireguard/peers/remove [find where interface=\"wg-awg3vds\"\ + ]\r\ + \n /ip/address/remove [find where interface=\"wg-awg3vds\"]\r\ + \n /interface/wireguard/remove [find where name=\"wg-awg3vds\"]\r\ + \n :do { /file/remove [find where name~\"awg3vds.+tar\"] } on-error={}\r\ + \n :do { /file/remove [find where name=\"usb1/awg3vds\"] } on-error={}\r\ + \n :do { /file/remove [find where name=\"usb1/ru_ranges_timeout.rsc\"] } \ + on-error={}\r\ + \n :do { /file/remove [find where name=\"usb1/ru_ranges.rsc\"] } on-error\ + ={}\r\ + \n :do { /file/remove [find where name~\"usb1/pull\"] } 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=awg3vds-uninstall]\r\ + \n" +add comment=awg3vds dont-require-permissions=no name=awg3vds-update owner=\ + vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n :local cids [/container/find where interface=veth-awg3vds and !stopped\ + ]\r\ + \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ + e=veth-awg3vds and start-on-boot=yes] }\r\ + \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ + e=veth-awg3vds] }\r\ + \n :if ([:len \$cids] = 0) do={\r\ + \n :put \"Container awg3vds not found\"\r\ + \n :log warning \"awg3vds-update: container not found\"\r\ + \n } else={\r\ + \n :local cid [:pick \$cids ([:len \$cids] - 1)]\r\ + \n :local img [/container/get \$cid remote-image]\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 wantRunning true\r\ + \n :do { :if ([/container/get \$cid start-on-boot] != true) do={ :set w\ + antRunning false } } on-error={}\r\ + \n :local healthy true\r\ + \n :if ([:len [/container/get \$cid image-id]] = 0) do={ :set healthy f\ + alse }\r\ + \n :if (\$wantRunning) do={\r\ + \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ + y false } } on-error={}\r\ + \n }\r\ + \n :if (!\$healthy && \$wantRunning && [:len [/container/get \$cid imag\ + e-id]] > 0) do={\r\ + \n :put \"Container is down - trying to start it\"\r\ + \n :do { /container/start \$cid } on-error={}\r\ + \n :delay 8s\r\ + \n :set healthy true\r\ + \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ + y false } } on-error={}\r\ + \n :if (\$healthy) do={\r\ + \n :put \"Container is back up\"\r\ + \n :log info \"awg3vds: container restarted by the update script\"\ + \r\ + \n }\r\ + \n }\r\ + \n :if (\$img = \"\" && \$minor >= 22 && !\$healthy) do={\r\ + \n :local imgTag \"latest\"\r\ + \n :local rbModel \"\"\r\ + \n :do { :set rbModel [[:parse \":return [/system/routerboard/get mod\ + el]\"]] } on-error={}\r\ + \n :local bName [/system/resource/get board-name]\r\ + \n :if (\$rbModel~\"E50UG\" || \$rbModel~\"E60iUGS\" || \$bName~\"E50\ + UG\" || \$bName~\"E60iUGS\" || \$bName~\"^hEX\") do={\r\ + \n :set imgTag \"latest-armv5\"\r\ + \n }\r\ + \n :set img (\"ghcr.io/timbrs/awg-proxy:\" . \$imgTag)\r\ + \n :put (\"Container is down and was installed from a file - pointing\ + \_it at \" . \$img)\r\ + \n :log warning \"awg3vds-update: broken file install, switching to t\ + he registry\"\r\ + \n :do { /container/set \$cid remote-image=\$img } on-error={}\r\ + \n }\r\ + \n :if (\$img = \"\") do={\r\ + \n :put \"Installed from a local image file - /container/repull only \ + updates registry installs.\"\r\ + \n :put \"Reinstall with the configurator on RouterOS 7.22+ to switch\ + \_to one-command updates.\"\r\ + \n } else={\r\ + \n :if (\$minor < 22) do={\r\ + \n :put (\"/container/repull needs RouterOS 7.22+, this router runs\ + \_\" . \$ver)\r\ + \n :if (!\$healthy) do={ :log error (\"awg3vds-update: container is\ + \_down, and \" . \$ver . \" has no /container/repull\") }\r\ + \n } else={\r\ + \n :local rootDir [/container/get \$cid root-dir]\r\ + \n :if ([:pick \$rootDir 0 1] = \"/\") do={ :set rootDir [:pick \$r\ + ootDir 1 [:len \$rootDir]] }\r\ + \n :local rootDirOrig \$rootDir\r\ + \n :local slashPos [:find \$rootDir \"/\"]\r\ + \n :local disk \$rootDir\r\ + \n :if ([:typeof \$slashPos] != \"nil\") do={ :set disk [:pick \$ro\ + otDir 0 \$slashPos] }\r\ + \n :local verPath \"awg-update-check.json\"\r\ + \n :if (\$disk != \"disk1\") do={\r\ + \n :do { /file/make-directory (\$disk . \"/pull\") } on-error={}\ + \r\ + \n /container/config set tmpdir=(\$disk . \"/pull\")\r\ + \n :set verPath (\$disk . \"/pull/awg-update-check.json\")\r\ + \n }\r\ + \n :local newVer \"\"\r\ + \n :do {\r\ + \n /tool/fetch url=\"https://api.github.com/repos/timbrs/amneziaw\ + g-mikrotik-c/releases/latest\" dst-path=\$verPath http-max-redirect-count=\ + 10\r\ + \n :local relJson [/file/get [find where name=\$verPath] contents\ + ]\r\ + \n :local tagPos [:find \$relJson \"\\\"tag_name\\\":\\\"\"]\r\ + \n :if ([:typeof \$tagPos] != \"nil\") do={\r\ + \n :local tagRest [:pick \$relJson (\$tagPos + 12) [:len \$relJ\ + son]]\r\ + \n :set newVer [:pick \$tagRest 0 [:find \$tagRest \"\\\"\"]]\r\ + \n }\r\ + \n :do { /file/remove [find where name=\$verPath] } on-error={}\r\ + \n } on-error={ :put \"Could not read the published version\" }\r\ + \n :local curVer \"\"\r\ + \n :do { :set curVer [/container/envs/get [find where list=\"awg3vd\ + s-env\" key=\"AWG_IMAGE_VER\"] value] } on-error={}\r\ + \n :local doPull true\r\ + \n :if (\$healthy) do={\r\ + \n :if (\$newVer = \"\") do={\r\ + \n :set doPull false\r\ + \n :put \"Published version unknown - leaving the healthy conta\ + iner alone\"\r\ + \n }\r\ + \n :if (\$newVer != \"\" && \$newVer = \$curVer) do={\r\ + \n :set doPull false\r\ + \n :put (\"Already on \" . \$curVer . \" - nothing to pull, tun\ + nel untouched\")\r\ + \n }\r\ + \n }\r\ + \n :if (\$doPull) do={\r\ + \n :if (!\$healthy) do={\r\ + \n :put \"Container is not healthy - pulling the image again\"\ + \r\ + \n :log warning \"awg3vds-update: container unhealthy, forcing \ + a pull\"\r\ + \n }\r\ + \n :put (\"Updating \" . \$img . \" ...\")\r\ + \n :log info \"awg3vds: repull started\"\r\ + \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ + p\")] } on-error={}\r\ + \n :do { [:parse \"/container/set \$cid ignore-remote-image-chang\ + e=yes\"] } on-error={}\r\ + \n /container/repull \$cid\r\ + \n :local waited 0\r\ + \n :while ([:len [/container/get \$cid image-id]] = 0 && \$waited\ + \_< 180) do={\r\ + \n :delay 3s\r\ + \n :set waited (\$waited + 3)\r\ + \n }\r\ + \n :if ([:len [/container/get \$cid image-id]] = 0) do={\r\ + \n :put \"Pull failed - retrying once in 15s\"\r\ + \n :delay 15s\r\ + \n /container/repull \$cid\r\ + \n :set waited 0\r\ + \n :while ([:len [/container/get \$cid image-id]] = 0 && \$wait\ + ed < 180) do={\r\ + \n :delay 3s\r\ + \n :set waited (\$waited + 3)\r\ + \n }\r\ + \n }\r\ + \n :local backUp false\r\ + \n :if ([:len [/container/get \$cid image-id]] > 0) do={\r\ + \n :set backUp true\r\ + \n :if (\$wantRunning) do={\r\ + \n :delay 3s\r\ + \n :do { /container/start \$cid } on-error={}\r\ + \n :delay 8s\r\ + \n :set backUp false\r\ + \n :do { :if ([/container/get \$cid stopped] != true) do={ :s\ + et backUp true } } on-error={}\r\ + \n }\r\ + \n }\r\ + \n :if (!\$backUp) do={\r\ + \n :put \"Container did not come back up - rebuilding it from t\ + he registry\"\r\ + \n :log warning \"awg3vds-update: container did not come back, \ + rebuilding\"\r\ + \n :do { /container/stop \$cid } on-error={}\r\ + \n :delay 5s\r\ + \n :do { /container/remove \$cid } on-error={}\r\ + \n :delay 3s\r\ + \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.bac\ + kup\")] } on-error={}\r\ + \n :do { /container/add remote-image=\$img interface=veth-awg3v\ + ds envlist=awg3vds-env hostname=awg3vds root-dir=\$rootDirOrig logging=no \ + start-on-boot=yes comment=awg3vds } on-error={}\r\ + \n :set waited 0\r\ + \n :local newCids [/container/find where interface=veth-awg3vds\ + \_and start-on-boot=yes]\r\ + \n :if ([:len \$newCids] = 0) do={ :set newCids [/container/fin\ + d where interface=veth-awg3vds] }\r\ + \n :while ([:len \$newCids] > 0 && [:len [/container/get [:pick\ + \_\$newCids ([:len \$newCids] - 1)] image-id]] = 0 && \$waited < 180) do={\ + \r\ + \n :delay 3s\r\ + \n :set waited (\$waited + 3)\r\ + \n }\r\ + \n :if ([:len \$newCids] > 0 && [:len [/container/get [:pick \$\ + newCids ([:len \$newCids] - 1)] image-id]] > 0) do={\r\ + \n :do { /container/set [:pick \$newCids ([:len \$newCids] - \ + 1)] shm-size=4M } on-error={}\r\ + \n :do { [:parse \"/container/set [find where interface=veth-\ + awg3vds] ignore-remote-image-change=yes\"] } on-error={}\r\ + \n :do { [:parse \"/container/set [find where interface=veth-\ + awg3vds] restart-policy=on-failure restart-interval=30s restart-max-count=\ + 10\"] } on-error={}\r\ + \n :do { /container/start [:pick \$newCids ([:len \$newCids] \ + - 1)] } on-error={}\r\ + \n :delay 8s\r\ + \n :do { :if ([/container/get [:pick \$newCids ([:len \$newCi\ + ds] - 1)] stopped] != true) do={ :set backUp true } } on-error={}\r\ + \n }\r\ + \n :if (\$backUp) do={\r\ + \n :put \"Container rebuilt\"\r\ + \n :log info \"awg3vds: container rebuilt after update\"\r\ + \n } else={\r\ + \n :put \"Rebuild failed - the tunnel is down. Netwatch keeps\ + \_the router online meanwhile.\"\r\ + \n :put \"This script runs again on the next schedule and wil\ + l retry.\"\r\ + \n :log error \"awg3vds-update: rebuild failed, tunnel is dow\ + n\"\r\ + \n }\r\ + \n }\r\ + \n :if (\$backUp && \$newVer != \"\") do={\r\ + \n :do { /container/envs/remove [find where list=\"awg3vds-env\ + \" key=\"AWG_IMAGE_VER\"] } on-error={}\r\ + \n :do { /container/envs/add list=awg3vds-env key=AWG_IMAGE_VER\ + \_value=\$newVer } on-error={}\r\ + \n }\r\ + \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ + p\")] } on-error={}\r\ + \n :if (\$backUp) do={\r\ + \n :put (\"Update done: \" . \$img)\r\ + \n :log info \"awg3vds: update done\"\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n }\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" +add name=manager policy="local,ssh,ftp,read,write,policy,api,rest-api,!telnet,\ + !reboot,!test,!winbox,!password,!web,!sniff,!sensitive,!romon" +/certificate settings +set builtin-trust-store=\ + capsman,fetch,email,netwatch,container,dns,www,api,reverse-proxy,logging +/container +add comment=awg3vds envlists=awg3vds-env file=usb1/pull/awg-proxy-arm.tar.gz \ + hostname=awg3vds ignore-remote-image-change=yes interface=veth-awg3vds \ + layer-dir="" name=awg-proxy-arm restart-interval=30s restart-max-count=10 \ + restart-policy=on-failure root-dir=/usb1/awg3vds shm-size=4096.0KiB \ + start-on-boot=yes +/container config +set memory-high=200.0MiB tmpdir=/usb1/pull +/container envs +add key=AWG_CLIENT_PUB list=awg3vds-env value=\ + "LnLYVichmfWj/lDZqn2tk7pj2XII/1tnyZaOjf40Tl8=" +add key=AWG_CONTENT_PADDING list=awg3vds-env value=54-119 +add key=AWG_CPU_C2S list=awg3vds-env value=1 +add key=AWG_CPU_S2C list=awg3vds-env value=2 +add key=AWG_H1 list=awg3vds-env value=457615290-457646150 +add key=AWG_H2 list=awg3vds-env value=1307355386-1307363580 +add key=AWG_H3 list=awg3vds-env value=2441734303-2441781787 +add key=AWG_H4 list=awg3vds-env value=3719180788-3719195844 +add key=AWG_HEADER_PROTECTION_KEY list=awg3vds-env value=\ + "FkGxbrW6ds3YPWNl48OWFEccrLC4tF94z9MnoKUZUsM=" +add key=AWG_I1 list=awg3vds-env value=\ + "" +add key=AWG_I2 list=awg3vds-env value=\ + "" +add key=AWG_I3 list=awg3vds-env value="" +add key=AWG_I4 list=awg3vds-env value="" +add key=AWG_I5 list=awg3vds-env value=\ + "" +add key=AWG_JC list=awg3vds-env value=5 +add key=AWG_JMAX list=awg3vds-env value=952 +add key=AWG_JMIN list=awg3vds-env value=510 +add key=AWG_KEEPALIVE_TIMEOUT list=awg3vds-env value=14-21 +add key=AWG_LISTEN list=awg3vds-env value=:51820 +add key=AWG_MAX_HANDSHAKE_ATTEMPTS list=awg3vds-env value=12-14 +add key=AWG_NO_DF list=awg3vds-env value=1 +add key=AWG_PREV_DNS list=awg3vds-env value=10.30.30.33,8.8.4.4 +add key=AWG_PREV_TMPDIR list=awg3vds-env value=/usb1/pull +add key=AWG_REJECT_AFTER list=awg3vds-env value=174-195 +add key=AWG_REKEY_AFTER list=awg3vds-env value=102-130 +add key=AWG_REKEY_TIMEOUT list=awg3vds-env value=6-8 +add key=AWG_REMOTE list=awg3vds-env value=89.110.101.17:31031 +add key=AWG_S1 list=awg3vds-env value=138 +add key=AWG_S2 list=awg3vds-env value=105 +add key=AWG_S3 list=awg3vds-env value=51 +add key=AWG_S4 list=awg3vds-env value=22 +add key=AWG_SERVER_PUB list=awg3vds-env value=\ + "MMWjD/TPNpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=" +/disk settings +set auto-media-interface=Bridge-Lan +/ip smb +set domain=WORKGROUP enabled=no interfaces=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=wlan1 +add bridge=Bridge-Lan interface=wlan2 +/interface bridge settings +set allow-fast-path=no use-ip-firewall=yes +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set accept-redirects=yes allow-fast-path=no +/ipv6 settings +set accept-router-advertisements-on=none allow-fast-path=no disable-ipv6=yes \ + disable-link-local-address=yes +/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="ether1 - Unet" list=Internet +add interface=Bridge-Lan list=LAN +add interface=wg-awg3vds list=WAN +/interface wireguard peers +add allowed-address=10.31.31.0/24,0.0.0.0/0 endpoint-address=172.19.14.102 \ + endpoint-port=51820 interface=wg-awg3vds name=peer1 persistent-keepalive=\ + 14s public-key="MMWjD/TPNpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=" +/interface wireless cap +# +set bridge=Bridge-Lan caps-man-addresses=10.30.30.10 \ + caps-man-certificate-common-names=CAPsMAN-2C900E832E04 certificate=\ + CAP-18FD746E5814 discovery-interfaces=Bridge-Lan enabled=yes interfaces=\ + wlan1,wlan2 lock-to-caps-man=yes +/ip address +add address=10.30.30.81/24 interface=Bridge-Lan network=10.30.30.0 +add address=172.19.14.101/30 interface=veth-awg3vds network=172.19.14.100 +add address=10.31.31.2/24 interface=wg-awg3vds network=10.31.31.0 +/ip cloud +set ddns-enabled=yes +/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.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.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 +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81 domain=WORKGROUP gateway=10.30.30.81 netmask=24 ntp-server=\ + 10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes servers=89.110.101.17,8.8.4.4 +/ip dns static +add address=10.30.30.81 comment=defconf name=router.lan type=A +add address=10.30.30.81 comment=defconf name=master type=A +add address=10.30.30.33 comment=amster name=amster.vados.ru type=A +add address=8.8.8.8 name=dns.google type=A +add address=8.8.4.4 name=dns.google 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=149.112.112.112 comment="Cuad9-dns IPv4 2" disabled=yes name=\ + dns.quad9.net type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +/ip firewall address-list +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=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.4 disabled=yes list=to_vpn +add address=10.30.30.98 comment=vados-len list=Local2Vpn +add address=89.110.101.17 list=VDS +add address=109.107.177.79 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=2ip.ru list=Test +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com comment=vdsina.com list=NoVdsina +add address=vdsina.ru comment=vdsina.ru list=NoVdsina +add address=youla.ru comment=youla.ru list=NoVdsina +add address=kupiprodai.ru comment=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co comment=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru comment=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC disabled=yes list=NoWG +add address=10.30.30.10 comment=MikroNUC disabled=yes list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! disabled=yes list=NoWG +add address=wg.vados.ru comment=VDSina-vpn list=Trusted-VPN +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=vdsina.vados.ru 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=Trusted-VPN +add address=vdsina.ru comment=VDSina-vpn list=Trusted-VPN +add address=ns.vados.ru comment=VDSina-vpn list=Trusted-VPN +add address=vdsina.com comment=VDSina-vpn list=Trusted-VPN +add address=cp.vdsina.ru comment=VDSina-vpn list=Trusted-VPN +add address=ns1.vdsina.ru comment=VDSina-vpn list=Trusted-VPN +add address=ghcr.io comment=GitHub list=Trusted-VPN +add address=github.com comment=GitHub list=Trusted-VPN +add address=149.154.164.13 comment=telegra.ph list=FuckRKN +add address=194.85.61.76 comment=grani.ru list=FuckRKN +add address=109.70.26.37 comment=grani.ru list=FuckRKN +add address=104.16.4.81 comment=xhamster.com list=FuckRKN +add address=104.16.3.81 comment=xhamster.com list=FuckRKN +add address=188.114.96.1 comment=lostfilm.tv list=FuckRKN +add address=188.114.97.1 comment=lostfilm.tv list=FuckRKN +add address=172.67.182.196 comment=rutracker.org list=FuckRKN +add address=104.21.32.39 comment=rutracker.org list=FuckRKN +add address=104.247.81.99 comment=lurkmore.to list=FuckRKN +add address=8.47.69.6 comment=dou.ua list=FuckRKN +add address=8.6.112.6 comment=dou.ua list=FuckRKN +add address=66.254.114.79 comment=youporn.com list=FuckRKN +add address=185.110.92.40 comment=pornolab.net list=FuckRKN +add address=185.110.92.41 comment=pornolab.net list=FuckRKN +add address=104.21.71.238 comment=crimerussia.com list=FuckRKN +add address=172.67.172.95 comment=crimerussia.com list=FuckRKN +add address=149.154.167.99 comment=telegram.org list=FuckRKN +add address=149.154.166.110 comment=api.telegram.org list=FuckRKN +add address=myip.ru comment="!!! Check IP (MYIP.RU) !!!" disabled=yes list=\ + NoVdsina +add address=ipinfo.io comment="!!! Check IP (IPINFO.IO) !!!" list=NoVdsina +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS UDP" \ + connection-state=new dst-port=53 in-interface="ether1 - Unet" protocol=\ + udp src-address-list=!VDS +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot DNS TCP" \ + connection-state=new dst-port=53 in-interface="ether1 - Unet" protocol=\ + tcp src-address-list=!VDS +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=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 ssh rdp winbox" connection-state=new dst-port=22,8291 \ + in-interface-list=WAN protocol=tcp src-address-list=!TRUSTED +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 in-interface=lo src-address=127.0.0.1 +add action=drop chain=input comment="defconf: drop all not coming from LAN" \ + in-interface-list=!LAN +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 +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + in-interface-list=WAN +/ip firewall mangle +add action=accept chain=prerouting dst-address-list=RFC1918 \ + in-interface-list=!WAN +add action=mark-connection chain=prerouting comment="NO VPN" \ + dst-address-list=NoVdsina in-interface-list=!WAN new-connection-mark=\ + To-ISP +add action=mark-routing chain=prerouting comment=All2vpn connection-mark=\ + !To-ISP dst-address=!89.110.101.17 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" connection-mark=\ + !To-ISP in-interface-list=!WAN new-mss=1380 protocol=tcp tcp-flags=syn \ + tcp-mss=1381-65535 +add action=mark-routing chain=prerouting connection-mark=to-vpn-conn \ + disabled=yes new-routing-mark=To-VPN routing-mark=To-VPN src-address=\ + 10.30.30.0/24 +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=\ + veth-awg3vds log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=accept chain=prerouting comment="SSH To ME" disabled=yes \ + dst-address=10.30.30.81 dst-port=2222 in-interface-list=!WAN protocol=tcp \ + src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment="VPN Network" disabled=yes \ + dst-address=10.8.0.0/24 log-prefix=VPN-Net new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 +/ip firewall nat +add action=masquerade chain=srcnat comment="Default NAT" ipsec-policy=\ + out,none out-interface="ether1 - Unet" src-address=10.30.30.0/24 +add action=masquerade chain=srcnat comment="NAT for VPN" routing-mark=To-VPN +add action=dst-nat chain=dstnat comment="dst-nat for acme" 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="dst-nat for amster HTTPS" dst-port=\ + 443 in-interface="ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 \ + to-ports=443 +add action=dst-nat chain=dstnat comment="dst-nat for amster ssh" disabled=yes \ + dst-port=22 protocol=tcp src-address-list=VDS to-addresses=10.30.30.33 \ + to-ports=22 +add action=dst-nat chain=dstnat comment="dst-nat for amster DNS (TCP)" \ + dst-port=53 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + VDS to-addresses=10.30.30.33 to-ports=53 +add action=dst-nat chain=dstnat comment="dst-nat for amster DNS (UDP)" \ + dst-port=53 in-interface="ether1 - Unet" protocol=udp src-address-list=\ + VDS to-addresses=10.30.30.33 to-ports=53 +add action=masquerade chain=srcnat disabled=yes src-address=172.20.200.68/30 +add action=masquerade chain=srcnat src-address=172.19.14.100/30 +/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 user profile +set [ find default=yes ] address-pool=dhcp +/ip route +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=wg-awg3vds@main \ + routing-table=To-VPN scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set www disabled=yes port=188 +set reverse-proxy disabled=yes +set ssh port=2222 +set www-ssl port=4433 +set api disabled=yes +set api-ssl disabled=yes +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface="ether1 - Unet" type=external +add interface=Bridge-Lan type=internal +/ipv6 firewall filter +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked disabled=yes +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid disabled=yes +add action=accept chain=input comment="defconf: accept ICMPv6" disabled=yes \ + protocol=icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + disabled=yes dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." disabled=yes dst-port=\ + 546 protocol=udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" disabled=yes \ + dst-port=500,4500 protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" disabled=yes \ + protocol=ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" disabled=\ + yes protocol=ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" disabled=yes \ + ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" disabled=yes \ + in-interface-list=!LAN +add action=fasttrack-connection chain=forward comment="defconf: fasttrack6" \ + connection-state=established,related +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 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system identity +set name=MikroMaster +/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=time.google.com +/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=awg3vds interval=1d name=awg3vds-update on-event=\ + "/system/script/run awg3vds-update" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-09-12 start-time=04:30:00 +/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="doh-fallback, doh-url=https://security.cloudflare-dns.com/dns-que\ + ry, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare-doh IPv4 1" \ + disabled=yes host=1.1.1.1 type=simple +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, doh-c\ + ert=DigiCert Global Root CA, notify, name=CloudFlare-doh IPv4 2" \ + disabled=yes host=1.0.0.1 type=simple +add comment="doh-fallback, dns-fallback, doh-url=https://dns.google/dns-query,\ + \_doh-cert=DigiCert Global Root G2, notify, name=Google-doh IPv4 1" \ + disabled=yes host=8.8.8.8 type=simple +add comment="doh-fallback, dns-fallback, doh-url=https://dns.google/dns-query,\ + \_doh-cert=DigiCert Global Root G2, notify, name=Google-doh IPv4 2" \ + disabled=yes host=8.8.4.4 type=simple +add comment="doh-fallback, dns-fallback, doh-url=https://dns.quad9.net/dns-que\ + ry, doh-cert=DigiCert Global Root G3, notify, name=Cuad9-doh IPv4 1" \ + disabled=yes host=9.9.9.9 type=simple +add comment="doh-fallback, dns-fallback, doh-url=https://dns.quad9.net/dns-que\ + ry, doh-cert=DigiCert Global Root G3, notify, name=Cuad9-doh IPv4 2" \ + disabled=yes host=149.112.112.112 type=simple +add comment="dns, notify, name=ns1.unet.ws" disabled=yes host=91.192.189.2 \ + type=simple +/user aaa +set accounting=no diff --git a/MikroMaster/history/20260912/20260912122002-Diff-Config.rsc b/MikroMaster/history/20260912/20260912122002-Diff-Config.rsc new file mode 100644 index 0000000..067f441 --- /dev/null +++ b/MikroMaster/history/20260912/20260912122002-Diff-Config.rsc @@ -0,0 +1,3184 @@ +19,22d18 +< /interface veth +< add address=172.19.14.102/30 container-mac-address=30:C8:D7:A4:6C:D6 dhcp=no \ +< gateway=172.19.14.101 gateway6="" mac-address=30:C8:D7:A4:6C:D5 name=\ +< veth-awg3vds +24d19 +< add listen-port=41430 mtu=1320 name=wg-awg3vds +70c65 +< add disabled=no fib name=To-VPN +--- +> add disabled=yes fib name=To-VPN +120c115 +< AM-GlobalConfig-2026-09-1211:58:18.rsc owner=AM-GlobalConfig policy=\ +--- +> AM-GlobalConfig owner=AM-GlobalConfig policy=\ +394,3453d388 +< 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/16716/73429726\";\r\ +< \n:global CommitTAG \"unknown\";\r\ +< \n:global CommitInfo \"Autocommit in repo: ros.vados.ru, generated by owne\ +< r: root, in 12:00:05 12.09.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="awg3vds installer" dont-require-permissions=no name=\ +< AM-awg3vdsInstall owner=AM-awg3vdsInstall policy=\ +< ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ +< !rsc by Vados\r\ +< \n# RouterOS script: AM-awg3vdsInstall\r\ +< \n# Script comment: awg3vds installer\r\ +< \n#\r\ +< \n#\r\ +< \n# requires RouterOS, version=7.19\r\ +< \n# requires device-mode, fetch, scheduler\r\ +< \n# ============================================================\r\ +< \n# AWG Proxy -- MikroTik RouterOS (protocol: v3)\r\ +< \n# 2026-09-12 08:41:48\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# Check storage device\r\ +< \n{\r\ +< \n :local targetDisk \"usb1\"\r\ +< \n :local diskFree 0\r\ +< \n :do { :set diskFree [/disk/get [find where mount-point=\$targetDisk] f\ +< ree] } on-error={}\r\ +< \n :if (\$diskFree = 0) do={\r\ +< \n :local baseDisk \$targetDisk\r\ +< \n :local dashPos [:find \$targetDisk \"-part\"]\r\ +< \n :if ([:typeof \$dashPos] != \"nil\") do={ :set baseDisk [:pick \$tar\ +< getDisk 0 \$dashPos] }\r\ +< \n :if ([:len [/disk/find where slot=\$baseDisk]] > 0) do={\r\ +< \n :put (\"Device \$baseDisk found but \$targetDisk is not available.\ +< \")\r\ +< \n :put \"Format \$baseDisk as ext4\? ALL DATA WILL BE ERASED!\"\r\ +< \n :put \"Press 'y' to confirm, any other key to cancel:\"\r\ +< \n :local key [/terminal/inkey timeout=30]\r\ +< \n :if (\$key = 121 || \$key = 89) do={\r\ +< \n :put \"Formatting \$baseDisk as ext4...\"\r\ +< \n /disk/format-drive \$baseDisk file-system=ext4 label=\$baseDisk\ +< \r\ +< \n :delay 3s\r\ +< \n :do { :set diskFree [/disk/get [find where mount-point=\$targetD\ +< isk] free] } on-error={}\r\ +< \n :if (\$diskFree = 0) do={\r\ +< \n :put (\"ERROR: \$targetDisk not found after formatting.\")\r\ +< \n :put \"Check mount point: /disk/print\"\r\ +< \n :error (\"Mount point \$targetDisk not found after formatting\ +< \")\r\ +< \n }\r\ +< \n :put (\"Formatted OK. Free: \" . (\$diskFree / 1048576) . \" MB\ +< \")\r\ +< \n } else={\r\ +< \n :error \"Formatting cancelled\"\r\ +< \n }\r\ +< \n } else={\r\ +< \n :put (\"ERROR: Storage device \$targetDisk not found.\")\r\ +< \n :put \"Check available disks: /disk/print\"\r\ +< \n :error (\"Storage not found: \" . \$targetDisk)\r\ +< \n }\r\ +< \n } else={\r\ +< \n :put (\"Storage OK: \$targetDisk (\" . (\$diskFree / 1048576) . \" M\ +< B free)\")\r\ +< \n }\r\ +< \n}\r\ +< \n\r\ +< \n# 1. Uninstall and update scripts\r\ +< \n/system/script/add name=awg3vds-uninstall comment=awg3vds 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=\"awg3vds-env\ +< \" key=\"AWG_PREV_DNS\"] value] } on-error={}\r\ +< \n :local prevTmpdir \"\"\r\ +< \n :do { :set prevTmpdir [/container/envs/get [find where list=\"awg3vds-\ +< env\" key=\"AWG_PREV_TMPDIR\"] value] } on-error={}\r\ +< \n /ip/route/remove [find where comment=awg3vds-tunnel]\r\ +< \n /ip/route/remove [find where comment=awg3vds-dns]\r\ +< \n :do { /system/scheduler/remove [find where comment~\"awg3vds\"] } on-e\ +< rror={}\r\ +< \n :do { /system/script/remove [find where comment~\"awg3vds\" and name!=\ +< \"awg3vds-uninstall\"] } on-error={}\r\ +< \n /container/stop [find where interface=veth-awg3vds]\r\ +< \n :delay 7s\r\ +< \n /container/remove [find where interface=veth-awg3vds]\r\ +< \n /container/envs/remove [find where list=\"awg3vds-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 /container/config set tmpdir=\$prevTmpdir\r\ +< \n :put (\"Container tmpdir restored to: \$prevTmpdir\")\r\ +< \n /ip/firewall/nat/remove [find where out-interface=\"wg-awg3vds\"]\r\ +< \n /ip/firewall/nat/remove [find where src-address=\"172.19.14.100/30\"]\ +< \r\ +< \n /ip/address/remove [find where address=\"172.19.14.101/30\"]\r\ +< \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-v6-nat] } \ +< on-error={}\r\ +< \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-dstnat6] }\ +< \_on-error={}\r\ +< \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-v6-out]\ +< \_} on-error={}\r\ +< \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-awg-in6\ +< ] } on-error={}\r\ +< \n :do { /ipv6/nd/remove [find where interface=veth-awg3vds] } on-error={\ +< }\r\ +< \n :do { /ipv6/nd/prefix/remove [find where interface=veth-awg3vds] } on-\ +< error={}\r\ +< \n :do { /ipv6/address/remove [find where comment=awg3vds-v6] } on-error=\ +< {}\r\ +< \n /interface/veth/remove [find where name=\"veth-awg3vds\"]\r\ +< \n /interface/wireguard/peers/remove [find where interface=\"wg-awg3vds\"\ +< ]\r\ +< \n /ip/address/remove [find where interface=\"wg-awg3vds\"]\r\ +< \n /interface/wireguard/remove [find where name=\"wg-awg3vds\"]\r\ +< \n :do { /file/remove [find where name~\"awg3vds.+tar\"] } on-error={}\r\ +< \n :do { /file/remove [find where name=\"usb1/awg3vds\"] } on-error={}\r\ +< \n :do { /file/remove [find where name=\"usb1/ru_ranges_timeout.rsc\"] } \ +< on-error={}\r\ +< \n :do { /file/remove [find where name=\"usb1/ru_ranges.rsc\"] } on-error\ +< ={}\r\ +< \n :do { /file/remove [find where name~\"usb1/pull\"] } 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=awg3vds-uninstall]\r\ +< \n}\r\ +< \n/system/script/add name=awg3vds-update comment=awg3vds source={\r\ +< \n :local cids [/container/find where interface=veth-awg3vds and !stopped\ +< ]\r\ +< \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ +< e=veth-awg3vds and start-on-boot=yes] }\r\ +< \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ +< e=veth-awg3vds] }\r\ +< \n :if ([:len \$cids] = 0) do={\r\ +< \n :put \"Container awg3vds not found\"\r\ +< \n :log warning \"awg3vds-update: container not found\"\r\ +< \n } else={\r\ +< \n :local cid [:pick \$cids ([:len \$cids] - 1)]\r\ +< \n :local img [/container/get \$cid remote-image]\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 wantRunning true\r\ +< \n :do { :if ([/container/get \$cid start-on-boot] != true) do={ :set w\ +< antRunning false } } on-error={}\r\ +< \n :local healthy true\r\ +< \n :if ([:len [/container/get \$cid image-id]] = 0) do={ :set healthy f\ +< alse }\r\ +< \n :if (\$wantRunning) do={\r\ +< \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ +< y false } } on-error={}\r\ +< \n }\r\ +< \n :if (!\$healthy && \$wantRunning && [:len [/container/get \$cid imag\ +< e-id]] > 0) do={\r\ +< \n :put \"Container is down - trying to start it\"\r\ +< \n :do { /container/start \$cid } on-error={}\r\ +< \n :delay 8s\r\ +< \n :set healthy true\r\ +< \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ +< y false } } on-error={}\r\ +< \n :if (\$healthy) do={\r\ +< \n :put \"Container is back up\"\r\ +< \n :log info \"awg3vds: container restarted by the update script\"\ +< \r\ +< \n }\r\ +< \n }\r\ +< \n :if (\$img = \"\" && \$minor >= 22 && !\$healthy) do={\r\ +< \n :local imgTag \"latest\"\r\ +< \n :local rbModel \"\"\r\ +< \n :do { :set rbModel [[:parse \":return [/system/routerboard/get mod\ +< el]\"]] } on-error={}\r\ +< \n :local bName [/system/resource/get board-name]\r\ +< \n :if (\$rbModel~\"E50UG\" || \$rbModel~\"E60iUGS\" || \$bName~\"E50\ +< UG\" || \$bName~\"E60iUGS\" || \$bName~\"^hEX\") do={\r\ +< \n :set imgTag \"latest-armv5\"\r\ +< \n }\r\ +< \n :set img (\"ghcr.io/timbrs/awg-proxy:\" . \$imgTag)\r\ +< \n :put (\"Container is down and was installed from a file - pointing\ +< \_it at \" . \$img)\r\ +< \n :log warning \"awg3vds-update: broken file install, switching to t\ +< he registry\"\r\ +< \n :do { /container/set \$cid remote-image=\$img } on-error={}\r\ +< \n }\r\ +< \n :if (\$img = \"\") do={\r\ +< \n :put \"Installed from a local image file - /container/repull only \ +< updates registry installs.\"\r\ +< \n :put \"Reinstall with the configurator on RouterOS 7.22+ to switch\ +< \_to one-command updates.\"\r\ +< \n } else={\r\ +< \n :if (\$minor < 22) do={\r\ +< \n :put (\"/container/repull needs RouterOS 7.22+, this router runs\ +< \_\" . \$ver)\r\ +< \n :if (!\$healthy) do={ :log error (\"awg3vds-update: container is\ +< \_down, and \" . \$ver . \" has no /container/repull\") }\r\ +< \n } else={\r\ +< \n :local rootDir [/container/get \$cid root-dir]\r\ +< \n :if ([:pick \$rootDir 0 1] = \"/\") do={ :set rootDir [:pick \$r\ +< ootDir 1 [:len \$rootDir]] }\r\ +< \n :local rootDirOrig \$rootDir\r\ +< \n :local slashPos [:find \$rootDir \"/\"]\r\ +< \n :local disk \$rootDir\r\ +< \n :if ([:typeof \$slashPos] != \"nil\") do={ :set disk [:pick \$ro\ +< otDir 0 \$slashPos] }\r\ +< \n :local verPath \"awg-update-check.json\"\r\ +< \n :if (\$disk != \"disk1\") do={\r\ +< \n :do { /file/make-directory (\$disk . \"/pull\") } on-error={}\ +< \r\ +< \n /container/config set tmpdir=(\$disk . \"/pull\")\r\ +< \n :set verPath (\$disk . \"/pull/awg-update-check.json\")\r\ +< \n }\r\ +< \n :local newVer \"\"\r\ +< \n :do {\r\ +< \n /tool/fetch url=\"https://api.github.com/repos/timbrs/amneziaw\ +< g-mikrotik-c/releases/latest\" dst-path=\$verPath http-max-redirect-count=\ +< 10\r\ +< \n :local relJson [/file/get [find where name=\$verPath] contents\ +< ]\r\ +< \n :local tagPos [:find \$relJson \"\\\"tag_name\\\":\\\"\"]\r\ +< \n :if ([:typeof \$tagPos] != \"nil\") do={\r\ +< \n :local tagRest [:pick \$relJson (\$tagPos + 12) [:len \$relJ\ +< son]]\r\ +< \n :set newVer [:pick \$tagRest 0 [:find \$tagRest \"\\\"\"]]\r\ +< \n }\r\ +< \n :do { /file/remove [find where name=\$verPath] } on-error={}\r\ +< \n } on-error={ :put \"Could not read the published version\" }\r\ +< \n :local curVer \"\"\r\ +< \n :do { :set curVer [/container/envs/get [find where list=\"awg3vd\ +< s-env\" key=\"AWG_IMAGE_VER\"] value] } on-error={}\r\ +< \n :local doPull true\r\ +< \n :if (\$healthy) do={\r\ +< \n :if (\$newVer = \"\") do={\r\ +< \n :set doPull false\r\ +< \n :put \"Published version unknown - leaving the healthy conta\ +< iner alone\"\r\ +< \n }\r\ +< \n :if (\$newVer != \"\" && \$newVer = \$curVer) do={\r\ +< \n :set doPull false\r\ +< \n :put (\"Already on \" . \$curVer . \" - nothing to pull, tun\ +< nel untouched\")\r\ +< \n }\r\ +< \n }\r\ +< \n :if (\$doPull) do={\r\ +< \n :if (!\$healthy) do={\r\ +< \n :put \"Container is not healthy - pulling the image again\"\ +< \r\ +< \n :log warning \"awg3vds-update: container unhealthy, forcing \ +< a pull\"\r\ +< \n }\r\ +< \n :put (\"Updating \" . \$img . \" ...\")\r\ +< \n :log info \"awg3vds: repull started\"\r\ +< \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ +< p\")] } on-error={}\r\ +< \n :do { [:parse \"/container/set \$cid ignore-remote-image-chang\ +< e=yes\"] } on-error={}\r\ +< \n /container/repull \$cid\r\ +< \n :local waited 0\r\ +< \n :while ([:len [/container/get \$cid image-id]] = 0 && \$waited\ +< \_< 180) do={\r\ +< \n :delay 3s\r\ +< \n :set waited (\$waited + 3)\r\ +< \n }\r\ +< \n :if ([:len [/container/get \$cid image-id]] = 0) do={\r\ +< \n :put \"Pull failed - retrying once in 15s\"\r\ +< \n :delay 15s\r\ +< \n /container/repull \$cid\r\ +< \n :set waited 0\r\ +< \n :while ([:len [/container/get \$cid image-id]] = 0 && \$wait\ +< ed < 180) do={\r\ +< \n :delay 3s\r\ +< \n :set waited (\$waited + 3)\r\ +< \n }\r\ +< \n }\r\ +< \n :local backUp false\r\ +< \n :if ([:len [/container/get \$cid image-id]] > 0) do={\r\ +< \n :set backUp true\r\ +< \n :if (\$wantRunning) do={\r\ +< \n :delay 3s\r\ +< \n :do { /container/start \$cid } on-error={}\r\ +< \n :delay 8s\r\ +< \n :set backUp false\r\ +< \n :do { :if ([/container/get \$cid stopped] != true) do={ :s\ +< et backUp true } } on-error={}\r\ +< \n }\r\ +< \n }\r\ +< \n :if (!\$backUp) do={\r\ +< \n :put \"Container did not come back up - rebuilding it from t\ +< he registry\"\r\ +< \n :log warning \"awg3vds-update: container did not come back, \ +< rebuilding\"\r\ +< \n :do { /container/stop \$cid } on-error={}\r\ +< \n :delay 5s\r\ +< \n :do { /container/remove \$cid } on-error={}\r\ +< \n :delay 3s\r\ +< \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.bac\ +< kup\")] } on-error={}\r\ +< \n :do { /container/add remote-image=\$img interface=veth-awg3v\ +< ds envlist=awg3vds-env hostname=awg3vds root-dir=\$rootDirOrig logging=no \ +< start-on-boot=yes comment=awg3vds } on-error={}\r\ +< \n :set waited 0\r\ +< \n :local newCids [/container/find where interface=veth-awg3vds\ +< \_and start-on-boot=yes]\r\ +< \n :if ([:len \$newCids] = 0) do={ :set newCids [/container/fin\ +< d where interface=veth-awg3vds] }\r\ +< \n :while ([:len \$newCids] > 0 && [:len [/container/get [:pick\ +< \_\$newCids ([:len \$newCids] - 1)] image-id]] = 0 && \$waited < 180) do={\ +< \r\ +< \n :delay 3s\r\ +< \n :set waited (\$waited + 3)\r\ +< \n }\r\ +< \n :if ([:len \$newCids] > 0 && [:len [/container/get [:pick \$\ +< newCids ([:len \$newCids] - 1)] image-id]] > 0) do={\r\ +< \n :do { /container/set [:pick \$newCids ([:len \$newCids] - \ +< 1)] shm-size=4M } on-error={}\r\ +< \n :do { [:parse \"/container/set [find where interface=veth-\ +< awg3vds] ignore-remote-image-change=yes\"] } on-error={}\r\ +< \n :do { [:parse \"/container/set [find where interface=veth-\ +< awg3vds] restart-policy=on-failure restart-interval=30s restart-max-count=\ +< 10\"] } on-error={}\r\ +< \n :do { /container/start [:pick \$newCids ([:len \$newCids] \ +< - 1)] } on-error={}\r\ +< \n :delay 8s\r\ +< \n :do { :if ([/container/get [:pick \$newCids ([:len \$newCi\ +< ds] - 1)] stopped] != true) do={ :set backUp true } } on-error={}\r\ +< \n }\r\ +< \n :if (\$backUp) do={\r\ +< \n :put \"Container rebuilt\"\r\ +< \n :log info \"awg3vds: container rebuilt after update\"\r\ +< \n } else={\r\ +< \n :put \"Rebuild failed - the tunnel is down. Netwatch keeps\ +< \_the router online meanwhile.\"\r\ +< \n :put \"This script runs again on the next schedule and wil\ +< l retry.\"\r\ +< \n :log error \"awg3vds-update: rebuild failed, tunnel is dow\ +< n\"\r\ +< \n }\r\ +< \n }\r\ +< \n :if (\$backUp && \$newVer != \"\") do={\r\ +< \n :do { /container/envs/remove [find where list=\"awg3vds-env\ +< \" key=\"AWG_IMAGE_VER\"] } on-error={}\r\ +< \n :do { /container/envs/add list=awg3vds-env key=AWG_IMAGE_VER\ +< \_value=\$newVer } on-error={}\r\ +< \n }\r\ +< \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ +< p\")] } on-error={}\r\ +< \n :if (\$backUp) do={\r\ +< \n :put (\"Update done: \" . \$img)\r\ +< \n :log info \"awg3vds: update done\"\r\ +< \n }\r\ +< \n }\r\ +< \n }\r\ +< \n }\r\ +< \n }\r\ +< \n}\r\ +< \n# Daily update check. Skipped if scheduler is not allowed by device-mode\ +< \r\ +< \n{\r\ +< \n :local schedOk true\r\ +< \n :do { :set schedOk [/system/device-mode/get scheduler] } on-error={}\r\ +< \n :if (\$schedOk) do={\r\ +< \n /system/scheduler/add name=awg3vds-update on-event=\"/system/script/\ +< run awg3vds-update\" start-time=04:30:00 interval=1d comment=awg3vds\r\ +< \n } else={\r\ +< \n :put \"WARNING: scheduler not allowed by device-mode, no daily updat\ +< e check.\"\r\ +< \n :put \"Update by hand: /system/script/run awg3vds-update\"\r\ +< \n :put \"To allow it: /system/device-mode/update scheduler=yes\"\r\ +< \n }\r\ +< \n}\r\ +< \n\r\ +< \n# 2. Network infrastructure\r\ +< \n/interface/veth/add name=veth-awg3vds address=172.19.14.102/30 gateway=1\ +< 72.19.14.101\r\ +< \n/ip/address/add address=172.19.14.101/30 interface=veth-awg3vds\r\ +< \n/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.19.1\ +< 4.100/30\r\ +< \n\r\ +< \n# 3. WireGuard interface (MikroTik derives the public key automatically)\ +< \r\ +< \n/interface/wireguard/add name=wg-awg3vds private-key=\"AEU+diR7SCIEOtwOW\ +< SWR3pEpkw6v0Qro2LRF0SnPpnw=\" listen-port=41430 mtu=1320 disabled=yes\r\ +< \n/interface/wireguard/peers/add interface=wg-awg3vds public-key=\"MMWjD/T\ +< PNpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=\" preshared-key=\"r9B13bB7gUTqde6zgB\ +< DfffFIUN6puP2gOWdK5zVS3nw=\" endpoint-address=172.19.14.102 endpoint-port=\ +< 51820 allowed-address=10.31.31.0/24,0.0.0.0/0 persistent-keepalive=14\r\ +< \n/ip/address/add address=10.31.31.2/24 interface=wg-awg3vds\r\ +< \n\r\ +< \n# 4. Container environment variables\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_LISTEN value=\":51820\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_REMOTE value=\"89.110.101.1\ +< 7:31031\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_JC value=\"5\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_JMIN value=\"510\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_JMAX value=\"952\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_S1 value=\"138\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_S2 value=\"105\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_H1 value=\"457615290-457646\ +< 150\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_H2 value=\"1307355386-13073\ +< 63580\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_H3 value=\"2441734303-24417\ +< 81787\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_H4 value=\"3719180788-37191\ +< 95844\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_SERVER_PUB value=\"MMWjD/TP\ +< NpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_CLIENT_PUB value=[/interfac\ +< e/wireguard/get [find name=wg-awg3vds] public-key]\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_S3 value=\"51\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_S4 value=\"22\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_I1 value=\"\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_I2 value=\"\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_I3 value=\"\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_I4 value=\"\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_I5 value=\"\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_HEADER_PROTECTION_KEY value\ +< =\"FkGxbrW6ds3YPWNl48OWFEccrLC4tF94z9MnoKUZUsM=\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_CONTENT_PADDING value=\"54-\ +< 119\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_REKEY_AFTER value=\"102-130\ +< \"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_REKEY_TIMEOUT value=\"6-8\"\ +< \r\ +< \n/container/envs/add list=awg3vds-env key=AWG_REJECT_AFTER value=\"174-19\ +< 5\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_KEEPALIVE_TIMEOUT value=\"1\ +< 4-21\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_MAX_HANDSHAKE_ATTEMPTS valu\ +< e=\"12-14\"\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_NO_DF value=\"1\"\r\ +< \n# Perf: give each forwarding thread its own core (4+ core routers)\r\ +< \n{ :if ([/system/resource/get cpu-count] >= 4) do={ /container/envs/add l\ +< ist=awg3vds-env key=AWG_CPU_C2S value=\"1\"; /container/envs/add list=awg3\ +< vds-env key=AWG_CPU_S2C value=\"2\" } }\r\ +< \n# NOTE on MTU: the value above assumes this tunnel is the last hop.\r\ +< \n# If the server forwards your traffic into another tunnel, subtract\r\ +< \n# that tunnel's overhead too, or every packet leaves in two fragments.\ +< \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\ +< g3vds-env key=AWG_PREV_DNS value=\"\$prevDNS\" }\r\ +< \n# NOTE: replaces existing DNS configuration\r\ +< \n/ip/dns/set servers=89.110.101.17,8.8.4.4\r\ +< \n# DNS 89.110.101.17 \D0\B8\D0\B4\D1\91\D1\82 \D0\BE\D0\B1\D1\89\D0\B8\D0\ +< \BC \D0\BC\D0\B0\D1\80\D1\88\D1\80\D1\83\D1\82\D0\BE\D0\BC (\D0\B2 \D0\B0\ +< \D0\BA\D1\82\D0\B8\D0\B2\D0\BD\D1\8B\D0\B9 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\ +< \D0\BB\D1\8C / default),\r\ +< \n# \D0\B1\D0\B5\D0\B7 \D0\BF\D1\80\D0\B8\D0\B2\D1\8F\D0\B7\D0\BA\D0\B8 \ +< \D0\BA wg-awg3vds: \D0\B8\D0\BD\D0\B0\D1\87\D0\B5 \D0\BF\D0\B0\D0\B4\D0\B5\ +< \D0\BD\D0\B8\D0\B5 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\D0\BB\D1\8F \D1\83\D0\BD\ +< \D0\BE\D1\81\D0\B8\D1\82 \D1\81 \D1\81\D0\BE\D0\B1\D0\BE\D0\B9 \D1\80\D0\ +< \B5\D0\B7\D0\BE\D0\BB\D0\B2.\r\ +< \n# DNS 8.8.4.4 \D0\B8\D0\B4\D1\91\D1\82 \D0\BE\D0\B1\D1\89\D0\B8\D0\BC \ +< \D0\BC\D0\B0\D1\80\D1\88\D1\80\D1\83\D1\82\D0\BE\D0\BC (\D0\B2 \D0\B0\D0\ +< \BA\D1\82\D0\B8\D0\B2\D0\BD\D1\8B\D0\B9 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\D0\ +< \BB\D1\8C / default),\r\ +< \n# \D0\B1\D0\B5\D0\B7 \D0\BF\D1\80\D0\B8\D0\B2\D1\8F\D0\B7\D0\BA\D0\B8 \ +< \D0\BA wg-awg3vds: \D0\B8\D0\BD\D0\B0\D1\87\D0\B5 \D0\BF\D0\B0\D0\B4\D0\B5\ +< \D0\BD\D0\B8\D0\B5 \D1\82\D1\83\D0\BD\D0\BD\D0\B5\D0\BB\D1\8F \D1\83\D0\BD\ +< \D0\BE\D1\81\D0\B8\D1\82 \D1\81 \D1\81\D0\BE\D0\B1\D0\BE\D0\B9 \D1\80\D0\ +< \B5\D0\B7\D0\BE\D0\BB\D0\B2.\r\ +< \n\r\ +< \n# 6. Download, create and start container\r\ +< \n:local prevTmpdir [/container/config/get tmpdir]\r\ +< \n/container/envs/add list=awg3vds-env key=AWG_PREV_TMPDIR value=\$prevTmp\ +< dir\r\ +< \n/container/config set tmpdir=usb1/pull memory-high=200M\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 :local imgTag \"latest\"\r\ +< \n :if (\$arch = \"arm64\") do={ :set file (\"awg-proxy-arm64\" . \$suffi\ +< x . \".tar.gz\") }\r\ +< \n :if (\$arch = \"arm\") do={\r\ +< \n :set file (\"awg-proxy-arm\" . \$suffix . \".tar.gz\")\r\ +< \n :local rbModel \"\"\r\ +< \n :do { :set rbModel [[:parse \":return [/system/routerboard/get model\ +< ]\"]] } on-error={}\r\ +< \n :local bName [/system/resource/get board-name]\r\ +< \n :if (\$rbModel~\"E50UG\" || \$rbModel~\"E60iUGS\" || \$bName~\"E50UG\ +< \" || \$bName~\"E60iUGS\" || \$bName~\"^hEX\") do={\r\ +< \n :set file (\"awg-proxy-armv5\" . \$suffix . \".tar.gz\")\r\ +< \n :set imgTag \"latest-armv5\"\r\ +< \n }\r\ +< \n }\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 (\"usb1/pull/\" . \$file)\r\ +< \n :local altPath (\"usb1/\" . \$file)\r\ +< \n :local rootDir \"usb1/awg3vds\"\r\ +< \n :do { /file/make-directory usb1/pull } on-error={}\r\ +< \n :if ([:len [/file/find where name=\$filePath]] = 0 && [:len [/file/fin\ +< d where name=\$altPath]] > 0) do={\r\ +< \n :set filePath \$altPath\r\ +< \n }\r\ +< \n :local added false\r\ +< \n :local fetched false\r\ +< \n :if ([:len [/file/find where name=\$filePath]] > 0) do={\r\ +< \n :put (\"Using image already on the router: \" . \$filePath)\r\ +< \n /container/add file=\$filePath interface=veth-awg3vds envlist=awg3vd\ +< s-env hostname=awg3vds root-dir=\$rootDir logging=no start-on-boot=yes com\ +< ment=awg3vds\r\ +< \n :set added true\r\ +< \n }\r\ +< \n :if (!\$added && \$minor >= 22) do={\r\ +< \n :local img (\"ghcr.io/timbrs/awg-proxy:\" . \$imgTag)\r\ +< \n :put (\"Pulling \" . \$img)\r\ +< \n /container/add remote-image=\$img interface=veth-awg3vds envlist=awg\ +< 3vds-env hostname=awg3vds root-dir=\$rootDir logging=no start-on-boot=yes \ +< comment=awg3vds\r\ +< \n :local cids [/container/find where interface=veth-awg3vds]\r\ +< \n :local waited 0\r\ +< \n :while ([:len \$cids] > 0 && [:len [/container/get [:pick \$cids 0] \ +< image-id]] = 0 && \$waited < 120) do={\r\ +< \n :delay 2s\r\ +< \n :set waited (\$waited + 2)\r\ +< \n }\r\ +< \n :if ([:len \$cids] > 0 && [:len [/container/get [:pick \$cids 0] ima\ +< ge-id]] > 0) do={\r\ +< \n :set added true\r\ +< \n :put (\"Pulled from registry in \" . \$waited . \"s\")\r\ +< \n :do {\r\ +< \n :local verPath (\$filePath . \".rel\")\r\ +< \n /tool/fetch url=\"https://api.github.com/repos/timbrs/amneziawg-\ +< mikrotik-c/releases/latest\" dst-path=\$verPath http-max-redirect-count=10\ +< \r\ +< \n :local relJson [/file/get [find where name=\$verPath] contents]\ +< \r\ +< \n :local tagPos [:find \$relJson \"\\\"tag_name\\\":\\\"\"]\r\ +< \n :local tagRest [:pick \$relJson (\$tagPos + 12) [:len \$relJson]\ +< ]\r\ +< \n /container/envs/add list=awg3vds-env key=AWG_IMAGE_VER value=[:p\ +< ick \$tagRest 0 [:find \$tagRest \"\\\"\"]]\r\ +< \n /file/remove [find where name=\$verPath]\r\ +< \n } on-error={}\r\ +< \n } else={\r\ +< \n :put \"Registry unavailable, falling back to the release archive\"\ +< \r\ +< \n :do { /container/remove \$cids } on-error={}\r\ +< \n :delay 2s\r\ +< \n }\r\ +< \n }\r\ +< \n :if (!\$added) do={\r\ +< \n :local freeStorage 0\r\ +< \n :do { :set freeStorage [/disk/get [find where mount-point=\"usb1\"] \ +< free] } on-error={}\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 /container/add file=\$filePath interface=veth-awg3vds envlist=awg3vd\ +< s-env hostname=awg3vds root-dir=\$rootDir logging=no start-on-boot=yes com\ +< ment=awg3vds\r\ +< \n :set fetched true\r\ +< \n }\r\ +< \n :if (\$minor > 20) do={ [:parse \"/container/set [find where interface\ +< =veth-awg3vds] shm-size=4M\"] }\r\ +< \n :do { [:parse \"/container/set [find where interface=veth-awg3vds] ign\ +< ore-remote-image-change=yes\"] } on-error={}\r\ +< \n :do { [:parse \"/container/set [find where interface=veth-awg3vds] res\ +< tart-policy=on-failure restart-interval=30s restart-max-count=10\"] } on-e\ +< rror={}\r\ +< \n :if (\$fetched) do={ /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-awg3vds]\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-awg3vds\r\ +< \n :put \"WireGuard interface enabled\"\r\ +< \n :put \"Installation complete!\"\r\ +< \n :put \"Ping test: 89.110.101.17 via AmneziaWG tunnel. repeat 10 times\ +< \"\r\ +< \n /ping 89.110.101.17 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-awg3vds com\ +< ment=awg3vds-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-awg3vds co\ +< mment=awg3vds-tunnel\"\r\ +< \n :put \"\"\r\ +< \n :put \" Remove a route:\"\r\ +< \n :put \" /ip/route/remove [find where comment=awg3vds-tunnel dst-add\ +< ress=8.8.8.8/32]\"\r\ +< \n :put \"\"\r\ +< \n :put \" Show all tunnel routes:\"\r\ +< \n :put \" /ip/route/print where comment=awg3vds-tunnel\"\r\ +< \n :put \"\"\r\ +< \n :put \" Update the container:\"\r\ +< \n :put \" /system/script/run awg3vds-update\"\r\ +< \n :put \"\"\r\ +< \n :put \" Uninstall:\"\r\ +< \n :put \" /system/script/run awg3vds-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=awg3vds dont-require-permissions=no name=awg3vds-uninstall owner=\ +< vados policy=\ +< ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon 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=\"awg3vds-env\ +< \" key=\"AWG_PREV_DNS\"] value] } on-error={}\r\ +< \n :local prevTmpdir \"\"\r\ +< \n :do { :set prevTmpdir [/container/envs/get [find where list=\"awg3vds-\ +< env\" key=\"AWG_PREV_TMPDIR\"] value] } on-error={}\r\ +< \n /ip/route/remove [find where comment=awg3vds-tunnel]\r\ +< \n /ip/route/remove [find where comment=awg3vds-dns]\r\ +< \n :do { /system/scheduler/remove [find where comment~\"awg3vds\"] } on-e\ +< rror={}\r\ +< \n :do { /system/script/remove [find where comment~\"awg3vds\" and name!=\ +< \"awg3vds-uninstall\"] } on-error={}\r\ +< \n /container/stop [find where interface=veth-awg3vds]\r\ +< \n :delay 7s\r\ +< \n /container/remove [find where interface=veth-awg3vds]\r\ +< \n /container/envs/remove [find where list=\"awg3vds-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 /container/config set tmpdir=\$prevTmpdir\r\ +< \n :put (\"Container tmpdir restored to: \$prevTmpdir\")\r\ +< \n /ip/firewall/nat/remove [find where out-interface=\"wg-awg3vds\"]\r\ +< \n /ip/firewall/nat/remove [find where src-address=\"172.19.14.100/30\"]\ +< \r\ +< \n /ip/address/remove [find where address=\"172.19.14.101/30\"]\r\ +< \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-v6-nat] } \ +< on-error={}\r\ +< \n :do { /ipv6/firewall/nat/remove [find where comment=awg3vds-dstnat6] }\ +< \_on-error={}\r\ +< \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-v6-out]\ +< \_} on-error={}\r\ +< \n :do { /ipv6/firewall/filter/remove [find where comment=awg3vds-awg-in6\ +< ] } on-error={}\r\ +< \n :do { /ipv6/nd/remove [find where interface=veth-awg3vds] } on-error={\ +< }\r\ +< \n :do { /ipv6/nd/prefix/remove [find where interface=veth-awg3vds] } on-\ +< error={}\r\ +< \n :do { /ipv6/address/remove [find where comment=awg3vds-v6] } on-error=\ +< {}\r\ +< \n /interface/veth/remove [find where name=\"veth-awg3vds\"]\r\ +< \n /interface/wireguard/peers/remove [find where interface=\"wg-awg3vds\"\ +< ]\r\ +< \n /ip/address/remove [find where interface=\"wg-awg3vds\"]\r\ +< \n /interface/wireguard/remove [find where name=\"wg-awg3vds\"]\r\ +< \n :do { /file/remove [find where name~\"awg3vds.+tar\"] } on-error={}\r\ +< \n :do { /file/remove [find where name=\"usb1/awg3vds\"] } on-error={}\r\ +< \n :do { /file/remove [find where name=\"usb1/ru_ranges_timeout.rsc\"] } \ +< on-error={}\r\ +< \n :do { /file/remove [find where name=\"usb1/ru_ranges.rsc\"] } on-error\ +< ={}\r\ +< \n :do { /file/remove [find where name~\"usb1/pull\"] } 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=awg3vds-uninstall]\r\ +< \n" +< add comment=awg3vds dont-require-permissions=no name=awg3vds-update owner=\ +< vados policy=\ +< ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ +< \r\ +< \n :local cids [/container/find where interface=veth-awg3vds and !stopped\ +< ]\r\ +< \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ +< e=veth-awg3vds and start-on-boot=yes] }\r\ +< \n :if ([:len \$cids] = 0) do={ :set cids [/container/find where interfac\ +< e=veth-awg3vds] }\r\ +< \n :if ([:len \$cids] = 0) do={\r\ +< \n :put \"Container awg3vds not found\"\r\ +< \n :log warning \"awg3vds-update: container not found\"\r\ +< \n } else={\r\ +< \n :local cid [:pick \$cids ([:len \$cids] - 1)]\r\ +< \n :local img [/container/get \$cid remote-image]\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 wantRunning true\r\ +< \n :do { :if ([/container/get \$cid start-on-boot] != true) do={ :set w\ +< antRunning false } } on-error={}\r\ +< \n :local healthy true\r\ +< \n :if ([:len [/container/get \$cid image-id]] = 0) do={ :set healthy f\ +< alse }\r\ +< \n :if (\$wantRunning) do={\r\ +< \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ +< y false } } on-error={}\r\ +< \n }\r\ +< \n :if (!\$healthy && \$wantRunning && [:len [/container/get \$cid imag\ +< e-id]] > 0) do={\r\ +< \n :put \"Container is down - trying to start it\"\r\ +< \n :do { /container/start \$cid } on-error={}\r\ +< \n :delay 8s\r\ +< \n :set healthy true\r\ +< \n :do { :if ([/container/get \$cid stopped] = true) do={ :set health\ +< y false } } on-error={}\r\ +< \n :if (\$healthy) do={\r\ +< \n :put \"Container is back up\"\r\ +< \n :log info \"awg3vds: container restarted by the update script\"\ +< \r\ +< \n }\r\ +< \n }\r\ +< \n :if (\$img = \"\" && \$minor >= 22 && !\$healthy) do={\r\ +< \n :local imgTag \"latest\"\r\ +< \n :local rbModel \"\"\r\ +< \n :do { :set rbModel [[:parse \":return [/system/routerboard/get mod\ +< el]\"]] } on-error={}\r\ +< \n :local bName [/system/resource/get board-name]\r\ +< \n :if (\$rbModel~\"E50UG\" || \$rbModel~\"E60iUGS\" || \$bName~\"E50\ +< UG\" || \$bName~\"E60iUGS\" || \$bName~\"^hEX\") do={\r\ +< \n :set imgTag \"latest-armv5\"\r\ +< \n }\r\ +< \n :set img (\"ghcr.io/timbrs/awg-proxy:\" . \$imgTag)\r\ +< \n :put (\"Container is down and was installed from a file - pointing\ +< \_it at \" . \$img)\r\ +< \n :log warning \"awg3vds-update: broken file install, switching to t\ +< he registry\"\r\ +< \n :do { /container/set \$cid remote-image=\$img } on-error={}\r\ +< \n }\r\ +< \n :if (\$img = \"\") do={\r\ +< \n :put \"Installed from a local image file - /container/repull only \ +< updates registry installs.\"\r\ +< \n :put \"Reinstall with the configurator on RouterOS 7.22+ to switch\ +< \_to one-command updates.\"\r\ +< \n } else={\r\ +< \n :if (\$minor < 22) do={\r\ +< \n :put (\"/container/repull needs RouterOS 7.22+, this router runs\ +< \_\" . \$ver)\r\ +< \n :if (!\$healthy) do={ :log error (\"awg3vds-update: container is\ +< \_down, and \" . \$ver . \" has no /container/repull\") }\r\ +< \n } else={\r\ +< \n :local rootDir [/container/get \$cid root-dir]\r\ +< \n :if ([:pick \$rootDir 0 1] = \"/\") do={ :set rootDir [:pick \$r\ +< ootDir 1 [:len \$rootDir]] }\r\ +< \n :local rootDirOrig \$rootDir\r\ +< \n :local slashPos [:find \$rootDir \"/\"]\r\ +< \n :local disk \$rootDir\r\ +< \n :if ([:typeof \$slashPos] != \"nil\") do={ :set disk [:pick \$ro\ +< otDir 0 \$slashPos] }\r\ +< \n :local verPath \"awg-update-check.json\"\r\ +< \n :if (\$disk != \"disk1\") do={\r\ +< \n :do { /file/make-directory (\$disk . \"/pull\") } on-error={}\ +< \r\ +< \n /container/config set tmpdir=(\$disk . \"/pull\")\r\ +< \n :set verPath (\$disk . \"/pull/awg-update-check.json\")\r\ +< \n }\r\ +< \n :local newVer \"\"\r\ +< \n :do {\r\ +< \n /tool/fetch url=\"https://api.github.com/repos/timbrs/amneziaw\ +< g-mikrotik-c/releases/latest\" dst-path=\$verPath http-max-redirect-count=\ +< 10\r\ +< \n :local relJson [/file/get [find where name=\$verPath] contents\ +< ]\r\ +< \n :local tagPos [:find \$relJson \"\\\"tag_name\\\":\\\"\"]\r\ +< \n :if ([:typeof \$tagPos] != \"nil\") do={\r\ +< \n :local tagRest [:pick \$relJson (\$tagPos + 12) [:len \$relJ\ +< son]]\r\ +< \n :set newVer [:pick \$tagRest 0 [:find \$tagRest \"\\\"\"]]\r\ +< \n }\r\ +< \n :do { /file/remove [find where name=\$verPath] } on-error={}\r\ +< \n } on-error={ :put \"Could not read the published version\" }\r\ +< \n :local curVer \"\"\r\ +< \n :do { :set curVer [/container/envs/get [find where list=\"awg3vd\ +< s-env\" key=\"AWG_IMAGE_VER\"] value] } on-error={}\r\ +< \n :local doPull true\r\ +< \n :if (\$healthy) do={\r\ +< \n :if (\$newVer = \"\") do={\r\ +< \n :set doPull false\r\ +< \n :put \"Published version unknown - leaving the healthy conta\ +< iner alone\"\r\ +< \n }\r\ +< \n :if (\$newVer != \"\" && \$newVer = \$curVer) do={\r\ +< \n :set doPull false\r\ +< \n :put (\"Already on \" . \$curVer . \" - nothing to pull, tun\ +< nel untouched\")\r\ +< \n }\r\ +< \n }\r\ +< \n :if (\$doPull) do={\r\ +< \n :if (!\$healthy) do={\r\ +< \n :put \"Container is not healthy - pulling the image again\"\ +< \r\ +< \n :log warning \"awg3vds-update: container unhealthy, forcing \ +< a pull\"\r\ +< \n }\r\ +< \n :put (\"Updating \" . \$img . \" ...\")\r\ +< \n :log info \"awg3vds: repull started\"\r\ +< \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ +< p\")] } on-error={}\r\ +< \n :do { [:parse \"/container/set \$cid ignore-remote-image-chang\ +< e=yes\"] } on-error={}\r\ +< \n /container/repull \$cid\r\ +< \n :local waited 0\r\ +< \n :while ([:len [/container/get \$cid image-id]] = 0 && \$waited\ +< \_< 180) do={\r\ +< \n :delay 3s\r\ +< \n :set waited (\$waited + 3)\r\ +< \n }\r\ +< \n :if ([:len [/container/get \$cid image-id]] = 0) do={\r\ +< \n :put \"Pull failed - retrying once in 15s\"\r\ +< \n :delay 15s\r\ +< \n /container/repull \$cid\r\ +< \n :set waited 0\r\ +< \n :while ([:len [/container/get \$cid image-id]] = 0 && \$wait\ +< ed < 180) do={\r\ +< \n :delay 3s\r\ +< \n :set waited (\$waited + 3)\r\ +< \n }\r\ +< \n }\r\ +< \n :local backUp false\r\ +< \n :if ([:len [/container/get \$cid image-id]] > 0) do={\r\ +< \n :set backUp true\r\ +< \n :if (\$wantRunning) do={\r\ +< \n :delay 3s\r\ +< \n :do { /container/start \$cid } on-error={}\r\ +< \n :delay 8s\r\ +< \n :set backUp false\r\ +< \n :do { :if ([/container/get \$cid stopped] != true) do={ :s\ +< et backUp true } } on-error={}\r\ +< \n }\r\ +< \n }\r\ +< \n :if (!\$backUp) do={\r\ +< \n :put \"Container did not come back up - rebuilding it from t\ +< he registry\"\r\ +< \n :log warning \"awg3vds-update: container did not come back, \ +< rebuilding\"\r\ +< \n :do { /container/stop \$cid } on-error={}\r\ +< \n :delay 5s\r\ +< \n :do { /container/remove \$cid } on-error={}\r\ +< \n :delay 3s\r\ +< \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.bac\ +< kup\")] } on-error={}\r\ +< \n :do { /container/add remote-image=\$img interface=veth-awg3v\ +< ds envlist=awg3vds-env hostname=awg3vds root-dir=\$rootDirOrig logging=no \ +< start-on-boot=yes comment=awg3vds } on-error={}\r\ +< \n :set waited 0\r\ +< \n :local newCids [/container/find where interface=veth-awg3vds\ +< \_and start-on-boot=yes]\r\ +< \n :if ([:len \$newCids] = 0) do={ :set newCids [/container/fin\ +< d where interface=veth-awg3vds] }\r\ +< \n :while ([:len \$newCids] > 0 && [:len [/container/get [:pick\ +< \_\$newCids ([:len \$newCids] - 1)] image-id]] = 0 && \$waited < 180) do={\ +< \r\ +< \n :delay 3s\r\ +< \n :set waited (\$waited + 3)\r\ +< \n }\r\ +< \n :if ([:len \$newCids] > 0 && [:len [/container/get [:pick \$\ +< newCids ([:len \$newCids] - 1)] image-id]] > 0) do={\r\ +< \n :do { /container/set [:pick \$newCids ([:len \$newCids] - \ +< 1)] shm-size=4M } on-error={}\r\ +< \n :do { [:parse \"/container/set [find where interface=veth-\ +< awg3vds] ignore-remote-image-change=yes\"] } on-error={}\r\ +< \n :do { [:parse \"/container/set [find where interface=veth-\ +< awg3vds] restart-policy=on-failure restart-interval=30s restart-max-count=\ +< 10\"] } on-error={}\r\ +< \n :do { /container/start [:pick \$newCids ([:len \$newCids] \ +< - 1)] } on-error={}\r\ +< \n :delay 8s\r\ +< \n :do { :if ([/container/get [:pick \$newCids ([:len \$newCi\ +< ds] - 1)] stopped] != true) do={ :set backUp true } } on-error={}\r\ +< \n }\r\ +< \n :if (\$backUp) do={\r\ +< \n :put \"Container rebuilt\"\r\ +< \n :log info \"awg3vds: container rebuilt after update\"\r\ +< \n } else={\r\ +< \n :put \"Rebuild failed - the tunnel is down. Netwatch keeps\ +< \_the router online meanwhile.\"\r\ +< \n :put \"This script runs again on the next schedule and wil\ +< l retry.\"\r\ +< \n :log error \"awg3vds-update: rebuild failed, tunnel is dow\ +< n\"\r\ +< \n }\r\ +< \n }\r\ +< \n :if (\$backUp && \$newVer != \"\") do={\r\ +< \n :do { /container/envs/remove [find where list=\"awg3vds-env\ +< \" key=\"AWG_IMAGE_VER\"] } on-error={}\r\ +< \n :do { /container/envs/add list=awg3vds-env key=AWG_IMAGE_VER\ +< \_value=\$newVer } on-error={}\r\ +< \n }\r\ +< \n :do { /file/remove [find where name~(\$disk . \"/awg3vds.backu\ +< p\")] } on-error={}\r\ +< \n :if (\$backUp) do={\r\ +< \n :put (\"Update done: \" . \$img)\r\ +< \n :log info \"awg3vds: update done\"\r\ +< \n }\r\ +< \n }\r\ +< \n }\r\ +< \n }\r\ +< \n }\r\ +< \n" +3460,3467c395 +< set builtin-trust-store=\ +< capsman,fetch,email,netwatch,container,dns,www,api,reverse-proxy,logging +< /container +< add comment=awg3vds envlists=awg3vds-env file=usb1/pull/awg-proxy-arm.tar.gz \ +< hostname=awg3vds ignore-remote-image-change=yes interface=veth-awg3vds \ +< layer-dir="" name=awg-proxy-arm restart-interval=30s restart-max-count=10 \ +< restart-policy=on-failure root-dir=/usb1/awg3vds shm-size=4096.0KiB \ +< start-on-boot=yes +--- +> set builtin-trust-store=all crl-use=yes +3470,3508d397 +< /container envs +< add key=AWG_CLIENT_PUB list=awg3vds-env value=\ +< "LnLYVichmfWj/lDZqn2tk7pj2XII/1tnyZaOjf40Tl8=" +< add key=AWG_CONTENT_PADDING list=awg3vds-env value=54-119 +< add key=AWG_CPU_C2S list=awg3vds-env value=1 +< add key=AWG_CPU_S2C list=awg3vds-env value=2 +< add key=AWG_H1 list=awg3vds-env value=457615290-457646150 +< add key=AWG_H2 list=awg3vds-env value=1307355386-1307363580 +< add key=AWG_H3 list=awg3vds-env value=2441734303-2441781787 +< add key=AWG_H4 list=awg3vds-env value=3719180788-3719195844 +< add key=AWG_HEADER_PROTECTION_KEY list=awg3vds-env value=\ +< "FkGxbrW6ds3YPWNl48OWFEccrLC4tF94z9MnoKUZUsM=" +< add key=AWG_I1 list=awg3vds-env value=\ +< "" +< add key=AWG_I2 list=awg3vds-env value=\ +< "" +< add key=AWG_I3 list=awg3vds-env value="" +< add key=AWG_I4 list=awg3vds-env value="" +< add key=AWG_I5 list=awg3vds-env value=\ +< "" +< add key=AWG_JC list=awg3vds-env value=5 +< add key=AWG_JMAX list=awg3vds-env value=952 +< add key=AWG_JMIN list=awg3vds-env value=510 +< add key=AWG_KEEPALIVE_TIMEOUT list=awg3vds-env value=14-21 +< add key=AWG_LISTEN list=awg3vds-env value=:51820 +< add key=AWG_MAX_HANDSHAKE_ATTEMPTS list=awg3vds-env value=12-14 +< add key=AWG_NO_DF list=awg3vds-env value=1 +< add key=AWG_PREV_DNS list=awg3vds-env value=10.30.30.33,8.8.4.4 +< add key=AWG_PREV_TMPDIR list=awg3vds-env value=/usb1/pull +< add key=AWG_REJECT_AFTER list=awg3vds-env value=174-195 +< add key=AWG_REKEY_AFTER list=awg3vds-env value=102-130 +< add key=AWG_REKEY_TIMEOUT list=awg3vds-env value=6-8 +< add key=AWG_REMOTE list=awg3vds-env value=89.110.101.17:31031 +< add key=AWG_S1 list=awg3vds-env value=138 +< add key=AWG_S2 list=awg3vds-env value=105 +< add key=AWG_S3 list=awg3vds-env value=51 +< add key=AWG_S4 list=awg3vds-env value=22 +< add key=AWG_SERVER_PUB list=awg3vds-env value=\ +< "MMWjD/TPNpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=" +3530c419 +< set detect-interface-list=WAN internet-interface-list=Internet \ +--- +> set detect-interface-list=static internet-interface-list=WAN \ +3535,3539d423 +< add interface=wg-awg3vds list=WAN +< /interface wireguard peers +< add allowed-address=10.31.31.0/24,0.0.0.0/0 endpoint-address=172.19.14.102 \ +< endpoint-port=51820 interface=wg-awg3vds name=peer1 persistent-keepalive=\ +< 14s public-key="MMWjD/TPNpupCvhXLCAw0xHXV4N6jgtQkg9Pl6pcQhU=" +3548,3549d431 +< add address=172.19.14.101/30 interface=veth-awg3vds network=172.19.14.100 +< add address=10.31.31.2/24 interface=wg-awg3vds network=10.31.31.0 +3601c483 +< set allow-remote-requests=yes servers=89.110.101.17,8.8.4.4 +--- +> set allow-remote-requests=yes servers=10.30.30.33,8.8.4.4 +4150c1032 +< add action=mark-connection chain=prerouting comment="NO VPN" \ +--- +> add action=mark-connection chain=prerouting comment="NO VPN" disabled=yes \ +4154,4155c1036,1038 +< !To-ISP dst-address=!89.110.101.17 dst-address-list=!NoVdsina \ +< new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +--- +> !To-ISP disabled=yes dst-address=!89.110.101.17 dst-address-list=\ +> !NoVdsina new-routing-mark=To-VPN src-address=10.30.30.0/24 \ +> src-address-list=!NoWG +4157,4158c1040,1041 +< !To-ISP in-interface-list=!WAN new-mss=1380 protocol=tcp tcp-flags=syn \ +< tcp-mss=1381-65535 +--- +> !To-ISP disabled=yes in-interface-list=!WAN new-mss=1380 protocol=tcp \ +> tcp-flags=syn tcp-mss=1381-65535 +4163,4164c1046,1048 +< "Mark VPN connections to exclude from FastTrack" in-interface=\ +< veth-awg3vds log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +--- +> "Mark VPN connections to exclude from FastTrack" disabled=yes \ +> in-interface=*B log-prefix=Mark-VPN-FT new-connection-mark=\ +> VPN_No_FastTrack +4174c1058,1059 +< add action=masquerade chain=srcnat comment="NAT for VPN" routing-mark=To-VPN +--- +> add action=masquerade chain=srcnat comment="NAT for VPN" disabled=yes \ +> routing-mark=To-VPN +4191d1075 +< add action=masquerade chain=srcnat src-address=172.19.14.100/30 +4201,4203d1084 +< /ip route +< add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=wg-awg3vds@main \ +< routing-table=To-VPN scope=30 target-scope=10 +4297,4300d1177 +< add comment=awg3vds interval=1d name=awg3vds-update on-event=\ +< "/system/script/run awg3vds-update" policy=\ +< ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ +< start-date=2026-09-12 start-time=04:30:00 -- 2.52.0