Compare commits

..

No commits in common. "main" and "routeros-7.18beta2-2" have entirely different histories.

25 changed files with 167 additions and 430 deletions

View file

@ -1,63 +0,0 @@
Debug output and logs
=====================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.15-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](README.md)
Sometimes scripts do not behave as expected. In these cases debug output
or logs can help.
## Debug output
Run this command in a terminal:
:set PrintDebug true;
You will then see debug output when running the script from terminal.
To revert to default output run:
:set PrintDebug false;
### Debug output for specific script
Even having debug output for a specific script or function only (or a
set of) is possible. To enable debug output for `telegram-chat` run:
:set ($PrintDebugOverride->"telegram-chat") true;
## Debug logs
The debug info can go to system log. To make it show up in `memory` run:
/system/logging/add topics=script,debug action=memory;
Other actions (`disk`, `email`, `remote` or `support`) can be used as
well. I do not recommend using `echo` - use [debug output](#debug-output)
instead.
Disable or remote that setting to restore regular logging.
## Verbose output
Specific scripts can generate huge amount of output. These do use a function
`$LogPrintVerbose`, which is declared, but has no code, intentionally.
If you *really* want that output set the function to be the same as
`$LogPrint`:
:set LogPrintVerbose $LogPrint;
To revert that change just run:
:set LogPrintVerbose;
---
[⬅️ Go back to main README](README.md)
[⬆️ Go back to top](#top)

View file

@ -19,7 +19,7 @@ Run the complete base installation:
{ {
/tool/fetch "https://git.eworm.de/cgit/routeros-scripts/plain/certs/ISRG-Root-X2.pem" dst-path="isrg-root-x2.pem" as-value; /tool/fetch "https://git.eworm.de/cgit/routeros-scripts/plain/certs/ISRG-Root-X2.pem" dst-path="isrg-root-x2.pem" as-value;
:delay 1s; :delay 1s;
/certificate/import file-name="isrg-root-x2.pem" passphrase=""; /certificate/import file-name=isrg-root-x2.pem passphrase="";
:if ([ :len [ /certificate/find where fingerprint="69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470" ] ] != 1) do={ :if ([ :len [ /certificate/find where fingerprint="69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470" ] ] != 1) do={
:error "Something is wrong with your certificates!"; :error "Something is wrong with your certificates!";
}; };

View file

@ -87,7 +87,7 @@ file to your MikroTik device.
Then we import the certificate. Then we import the certificate.
/certificate/import file-name="isrg-root-x2.pem" passphrase=""; /certificate/import file-name=isrg-root-x2.pem passphrase="";
Do not worry that the command is not shown - that happens because it contains Do not worry that the command is not shown - that happens because it contains
a sensitive property, the passphrase. a sensitive property, the passphrase.

View file

@ -62,7 +62,7 @@
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \ :if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={ ($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true; :set Updated true;
$RmFile ($File->"name"); $RmFile $Package;
} }
} }

View file

@ -64,7 +64,7 @@
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \ :if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={ ($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true; :set Updated true;
$RmFile ($File->"name"); $RmFile $Package;
} }
} }

View file

@ -62,7 +62,7 @@
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \ :if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={ ($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true; :set Updated true;
$RmFile ($File->"name"); $RmFile $Package;
} }
} }

28
certs/GlobalSign.pem Normal file
View file

@ -0,0 +1,28 @@
# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
# Label: "GlobalSign Root CA - R3"
# Serial: 4835703278459759426209954
# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
WD9f
-----END CERTIFICATE-----

View file

@ -15,7 +15,7 @@ DOMAINS_DUAL = \
git.eworm.de/ISRG-Root-X2 \ git.eworm.de/ISRG-Root-X2 \
lists.blocklist.de/Certum-Trusted-Network-CA \ lists.blocklist.de/Certum-Trusted-Network-CA \
matrix.org/GTS-Root-R4 \ matrix.org/GTS-Root-R4 \
raw.githubusercontent.com/USERTrust-RSA-Certification-Authority \ raw.githubusercontent.com/DigiCert-Global-Root-G2 \
rsc.eworm.de/ISRG-Root-X2 \ rsc.eworm.de/ISRG-Root-X2 \
upgrade.mikrotik.com/ISRG-Root-X1 upgrade.mikrotik.com/ISRG-Root-X1
DOMAINS_IPV4 = \ DOMAINS_IPV4 = \
@ -23,10 +23,12 @@ DOMAINS_IPV4 = \
8.8.8.8/GTS-Root-R1 \ 8.8.8.8/GTS-Root-R1 \
9.9.9.9/DigiCert-Global-Root-G3 \ 9.9.9.9/DigiCert-Global-Root-G3 \
api.mullvad.net/ISRG-Root-X1 \ api.mullvad.net/ISRG-Root-X1 \
feodotracker.abuse.ch/GlobalSign \
ipv4.showipv6.de/ISRG-Root-X1 \ ipv4.showipv6.de/ISRG-Root-X1 \
ipv4.tunnelbroker.net/Starfield-Root-Certificate-Authority-G2 \ ipv4.tunnelbroker.net/Starfield-Root-Certificate-Authority-G2 \
mkcert.org/ISRG-Root-X1 \ mkcert.org/ISRG-Root-X1 \
ntfy.sh/ISRG-Root-X1 \ ntfy.sh/ISRG-Root-X1 \
sslbl.abuse.ch/GlobalSign \
www.dshield.org/ISRG-Root-X1 \ www.dshield.org/ISRG-Root-X1 \
www.spamhaus.org/GTS-Root-R4 www.spamhaus.org/GTS-Root-R4
DOMAINS_IPV6 = \ DOMAINS_IPV6 = \

View file

@ -1,41 +0,0 @@
# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
# Label: "USERTrust RSA Certification Authority"
# Serial: 2645093764781058787591871645665788717
# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5
# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e
# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2
-----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
jjxDah2nGN59PRbxYvnKkKj9
-----END CERTIFICATE-----

View file

@ -48,26 +48,21 @@
:global UrlEncode; :global UrlEncode;
:global WaitForFile; :global WaitForFile;
:foreach Type in={ "p12"; "pem" } do={ :local Return false;
:local CertFileName ([ $UrlEncode $FetchName ] . "." . $Type);
$LogPrint debug $ScriptName ("Trying type '" . $Type . "' for '" . $CertName . \
"' (file '" . $CertFileName . "')...");
:foreach Type in={ ".pem"; ".p12" } do={
:local CertFileName ([ $UrlEncode $FetchName ] . $Type);
:do { :do {
/tool/fetch check-certificate=yes-without-crl http-header-field=({ [ $FetchUserAgentStr $ScriptName ] }) \ /tool/fetch check-certificate=yes-without-crl http-header-field=({ [ $FetchUserAgentStr $ScriptName ] }) \
($CertRenewUrl . $CertFileName) dst-path=$CertFileName as-value; ($CertRenewUrl . $CertFileName) dst-path=$CertFileName as-value;
$WaitForFile $CertFileName; $WaitForFile $CertFileName;
:local DecryptionFailed true; :local DecryptionFailed true;
:foreach I,PassPhrase in=$CertRenewPass do={ :foreach PassPhrase in=$CertRenewPass do={
:do { :local Result [ /certificate/import file-name=$CertFileName passphrase=$PassPhrase as-value ];
$LogPrint debug $ScriptName ("Trying " . $I . ". passphrase... "); :if ($Result->"decryption-failures" = 0) do={
:local Result [ /certificate/import file-name=$CertFileName passphrase=$PassPhrase as-value ]; :set DecryptionFailed false;
:if ($Result->"decryption-failures" = 0) do={ }
$LogPrint debug $ScriptName ("Success!");
:set DecryptionFailed false;
}
} on-error={ }
} }
$RmFile $CertFileName; $RmFile $CertFileName;
@ -82,13 +77,13 @@
$CertificateNameByCN [ /certificate/get $CertInChain common-name ]; $CertificateNameByCN [ /certificate/get $CertInChain common-name ];
} }
:return true; :set Return true;
} on-error={ } on-error={
$LogPrint debug $ScriptName ("Could not download certificate file '" . $CertFileName . "'."); $LogPrint debug $ScriptName ("Could not download certificate file '" . $CertFileName . "'.");
} }
} }
:return false; :return $Return;
} }
:local FormatInfo do={ :local FormatInfo do={

View file

@ -66,27 +66,6 @@
:error "A reboot for update is already scheduled."; :error "A reboot for update is already scheduled.";
} }
:local License [ /system/license/get ];
:if ([ :typeof ($License->"deadline-at") ] = "str") do={
:if ([ :len ($License->"next-renewal-at") ] = 0 && ($License->"limited-upgrades") = true) do={
$LogPrint warning $ScriptName ("Your license expired on " . ($License->"deadline-at") . "!");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \
message=("Your license expired on " . ($License->"deadline-at") . \
", can no longer update RouterOS on " . $Identity . "...") });
:set ExitOK true;
:error false;
}
:if ([ :totime ($License->"deadline-at") ] - 3w < [ :timestamp ]) do={
$LogPrint warning $ScriptName ("Your license will expire on " . ($License->"deadline-at") . "!");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \
message=("Your license failed to renew and is about to expire on " . \
($License->"deadline-at") . " on " . $Identity . "...") });
}
}
$LogPrint debug $ScriptName ("Checking for updates..."); $LogPrint debug $ScriptName ("Checking for updates...");
/system/package/update/check-for-updates without-paging as-value; /system/package/update/check-for-updates without-paging as-value;
:local Update [ /system/package/update/get ]; :local Update [ /system/package/update/get ];

View file

@ -18,11 +18,10 @@ Description
This script downloads, imports and updates firewall address-lists. Its main This script downloads, imports and updates firewall address-lists. Its main
purpose is to block attacking ip addresses, spam hosts, command-and-control purpose is to block attacking ip addresses, spam hosts, command-and-control
servers and similar malicious entities. The default configuration contains a servers and similar malicious entities. The default configuration contains
[collective list by GitHub user @stamparm](https://github.com/stamparm/ipsum), lists from [abuse.ch](https://abuse.ch/), [dshield.org](https://dshield.org/)
lists from [dshield.org](https://dshield.org/) and and [blocklist.de](https://www.blocklist.de/), and
[blocklist.de](https://www.blocklist.de/), and lists from lists from [spamhaus.org](https://spamhaus.org/) are prepared.
[spamhaus.org](https://spamhaus.org/) are prepared.
The address-lists are updated in place, so after initial import you will not The address-lists are updated in place, so after initial import you will not
see situation when the lists are not populated. see situation when the lists are not populated.

View file

@ -22,15 +22,15 @@ server (see `/system/logging`). This has some limitation, however:
* does not work early after boot if network connectivity is not * does not work early after boot if network connectivity is not
yet established, or breaks intermittently yet established, or breaks intermittently
* lots of messages generate a flood of mails * lots of messages generate a flood of mails
* Matrix, Ntfy and Telegram are not supported * Matrix and Telegram are not supported
The script works around the limitations, for example it does: The script works around the limitations, for example it does:
* read from `/log`, including messages from early boot * read from `/log`, including messages from early boot
* skip multi-repeated messages * skip multi-repeated messages
* rate-limit itself to mitigate flooding * rate-limit itself to mitigate flooding
* forward via notification (which includes *e-mail*, *Matrix*, *Ntfy* and * forward via notification (which includes *e-mail*, *Matrix* and *Telegram*
*Telegram* when installed and configured, see below) when installed and configured, see below)
It is intended to be run periodically from scheduler, then collects new It is intended to be run periodically from scheduler, then collects new
log messages and forwards them via notification. log messages and forwards them via notification.
@ -53,12 +53,6 @@ Just install the script:
Configuration Configuration
------------- -------------
The default configuration should provide reasonable presets, filtering
*info*, and effectively forwarding *warning* and *error*.
> 💡️ **Hint**: Please try with defaults first, especially if you are not
> familiar with regular expressions!
The configuration goes to `global-config-overlay`, these are the parameters: The configuration goes to `global-config-overlay`, these are the parameters:
* `LogForwardFilter`: define topics *not* to be forwarded * `LogForwardFilter`: define topics *not* to be forwarded

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -38,21 +38,14 @@ create your own bot:
![create new bot](notification-telegram.d/newbot.avif) ![create new bot](notification-telegram.d/newbot.avif)
Set that token from *BotFather* (use your own!) to `TelegramTokenId`, for Now open a chat with your bot and start it by clicking the `START` button.
now just temporarily:
:set TelegramTokenId "5214364459:AAHLwf1o7ybbKDo6pY24Kd2bZ5rjCakDXTc"; Open just another chat with [GetIDs Bot](https://t.me/getidsbot), again start
with the `START` button. It will send you some information, including the
Now open a chat with your bot and start it by clicking the `START` button, `id`, just below `You`.
then send your first message. Any text will do. On your device run
`$GetTelegramChatId` to retrieve the chat id:
$GetTelegramChatId;
![get chat id](notification-telegram.d/getchatid.avif)
Finally edit `global-config-overlay`, add `TelegramTokenId` with the token Finally edit `global-config-overlay`, add `TelegramTokenId` with the token
from *BotFather* and `TelegramChatId` with your retrieved chat id. Then from *BotFather* and `TelegramChatId` with your id from *GetIDs Bot*. Then
reload the configuration. reload the configuration.
> **Info**: Copy relevant configuration from > **Info**: Copy relevant configuration from
@ -61,13 +54,9 @@ reload the configuration.
### Notifications to a group ### Notifications to a group
Sending notifications to a group is possible as well. Add your bot to a group Sending notifications to a group is possible as well. Add your bot and the
and make it an admin (required for read access!) and send a message and run *GetIDs Bot* to a group, then use the group's id (which starts with a dash)
`$GetTelegramChatId` again. Then use that chat id (which starts with a dash) for `TelegramChatId`. Then remove *GetIDs Bot* from group.
for `TelegramChatId`.
Groups can enable the `Topics` feature. Use `TelegramThreadId` to send to a
specific topic in a group.
Usage and invocation Usage and invocation
-------------------- --------------------

View file

@ -24,7 +24,6 @@
:global HumanReadableNum; :global HumanReadableNum;
:global LogPrint; :global LogPrint;
:global LogPrintOnce; :global LogPrintOnce;
:global LogPrintVerbose;
:global ScriptLock; :global ScriptLock;
:global WaitFullyConnected; :global WaitFullyConnected;
@ -37,11 +36,6 @@
} }
} }
:local GetBranch do={
:global EitherOr;
:return [ :pick [ :convert transform=md5 to=hex [ :pick $1 0 [ $EitherOr [ :find $1 "/" ] [ :len $1 ] ] ] ] 0 2 ];
}
:if ([ $ScriptLock $ScriptName ] = false) do={ :if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true; :set ExitOK true;
:error false; :error false;
@ -105,24 +99,17 @@
:set Address ([ :pick $Line 0 [ $FindDelim $Line ] ] . ($List->"cidr")); :set Address ([ :pick $Line 0 [ $FindDelim $Line ] ] . ($List->"cidr"));
} }
:do { :do {
:local Branch [ $GetBranch $Address ];
:if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$") do={ :if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$") do={
:if ($Address ~ "/32\$") do={ :set ($IPv4Addresses->$Address) $TimeOut;
:set Address [ :pick $Address 0 ([ :len $Address ] - 3) ];
}
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:error true; :error true;
} }
:if ($Address ~ "^[0-9a-zA-Z]*:[0-9a-zA-Z:\\.]+(/[0-9]{1,3})?\$") do={ :if ($Address ~ "^[0-9a-zA-Z]*:[0-9a-zA-Z:\\.]+(/[0-9]{1,3})?\$") do={
:if ($Address ~ "/128\$") do={ :set ($IPv6Addresses->$Address) $TimeOut;
:set Address [ :pick $Address 0 ([ :len $Address ] - 4) ];
}
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:error true; :error true;
} }
:if ($Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={ :if ($Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set ($IPv4Addresses->$Branch->$Address) $TimeOut; :set ($IPv4Addresses->$Address) $TimeOut;
:set ($IPv6Addresses->$Branch->$Address) $TimeOut; :set ($IPv6Addresses->$Address) $TimeOut;
:error true; :error true;
} }
} on-error={ } } on-error={ }
@ -132,17 +119,15 @@
:foreach Entry in=[ /ip/firewall/address-list/find where \ :foreach Entry in=[ /ip/firewall/address-list/find where \
list=$FwListName comment=$ListComment ] do={ list=$FwListName comment=$ListComment ] do={
:local Address [ /ip/firewall/address-list/get $Entry address ]; :local Address [ /ip/firewall/address-list/get $Entry address ];
:local Branch [ $GetBranch $Address ]; :if ([ :typeof ($IPv4Addresses->$Address) ] = "time") do={
:local TimeOut ($IPv4Addresses->$Branch->$Address); $LogPrint debug $ScriptName ("Renewing IPv4 address in list '" . $FwListName . \
:if ([ :typeof $TimeOut ] = "time") do={ "' with " . ($IPv4Addresses->$Address) . ": " . $Address);
$LogPrintVerbose debug $ScriptName ("Renewing IPv4 address in list '" . $FwListName . \ /ip/firewall/address-list/set $Entry timeout=($IPv4Addresses->$Address);
"' with " . $TimeOut . ": " . $Address); :set ($IPv4Addresses->$Address);
/ip/firewall/address-list/set $Entry timeout=$TimeOut;
:set ($IPv4Addresses->$Branch->$Address);
:set CntRenew ($CntRenew + 1); :set CntRenew ($CntRenew + 1);
} else={ } else={
:if ($Failure = false) do={ :if ($Failure = false) do={
$LogPrintVerbose debug $ScriptName ("Removing IPv4 address from list '" . $FwListName . \ $LogPrint debug $ScriptName ("Removing IPv4 address from list '" . $FwListName . \
"': " . $Address); "': " . $Address);
/ip/firewall/address-list/remove $Entry; /ip/firewall/address-list/remove $Entry;
:set CntRemove ($CntRemove + 1); :set CntRemove ($CntRemove + 1);
@ -153,17 +138,15 @@
:foreach Entry in=[ /ipv6/firewall/address-list/find where \ :foreach Entry in=[ /ipv6/firewall/address-list/find where \
list=$FwListName comment=$ListComment ] do={ list=$FwListName comment=$ListComment ] do={
:local Address [ /ipv6/firewall/address-list/get $Entry address ]; :local Address [ /ipv6/firewall/address-list/get $Entry address ];
:local Branch [ $GetBranch $Address ]; :if ([ :typeof ($IPv6Addresses->$Address) ] = "time") do={
:local TimeOut ($IPv6Addresses->$Branch->$Address); $LogPrint debug $ScriptName ("Renewing IPv6 address in list '" . $FwListName . \
:if ([ :typeof $TimeOut ] = "time") do={ "' with " . ($IPv6Addresses->$Address) . ": " . $Address);
$LogPrintVerbose debug $ScriptName ("Renewing IPv6 address in list '" . $FwListName . \ /ipv6/firewall/address-list/set $Entry timeout=($IPv6Addresses->$Address);
"' with " . $TimeOut . ": " . $Address); :set ($IPv6Addresses->$Address);
/ipv6/firewall/address-list/set $Entry timeout=$TimeOut;
:set ($IPv6Addresses->$Branch->$Address);
:set CntRenew ($CntRenew + 1); :set CntRenew ($CntRenew + 1);
} else={ } else={
:if ($Failure = false) do={ :if ($Failure = false) do={
$LogPrintVerbose debug $ScriptName ("Removing IPv6 address from list '" . $FwListName . \ $LogPrint debug $ScriptName ("Removing IPv6 address from list '" . $FwListName . \
"': " . $Address); "': " . $Address);
/ipv6/firewall/address-list/remove $Entry; /ipv6/firewall/address-list/remove $Entry;
:set CntRemove ($CntRemove + 1); :set CntRemove ($CntRemove + 1);
@ -171,35 +154,31 @@
} }
} }
:foreach BranchName,Branch in=$IPv4Addresses do={ :foreach Address,Timeout in=$IPv4Addresses do={
$LogPrintVerbose debug $ScriptName ("Handling branch: " . $BranchName); $LogPrint debug $ScriptName ("Adding IPv4 address to list '" . $FwListName . \
:foreach Address,Timeout in=$Branch do={ "' with " . $Timeout . ": " . $Address);
$LogPrintVerbose debug $ScriptName ("Adding IPv4 address to list '" . $FwListName . \ :do {
"' with " . $Timeout . ": " . $Address); /ip/firewall/address-list/add list=$FwListName comment=$ListComment \
:do { address=$Address timeout=$Timeout;
/ip/firewall/address-list/add list=$FwListName comment=$ListComment \ :set ($IPv4Addresses->$Address);
address=$Address timeout=$Timeout; :set CntAdd ($CntAdd + 1);
:set CntAdd ($CntAdd + 1); } on-error={
} on-error={ $LogPrint warning $ScriptName ("Failed to add IPv4 address to list '" . $FwListName . \
$LogPrint warning $ScriptName ("Failed to add IPv4 address to list '" . $FwListName . \ "': " . $Address);
"': " . $Address);
}
} }
} }
:foreach BranchName,Branch in=$IPv6Addresses do={ :foreach Address,Timeout in=$IPv6Addresses do={
$LogPrintVerbose debug $ScriptName ("Handling branch: " . $BranchName); $LogPrint debug $ScriptName ("Adding IPv6 address to list '" . $FwListName . \
:foreach Address,Timeout in=$Branch do={ "' with " . $Timeout . ": " . $Address);
$LogPrintVerbose debug $ScriptName ("Adding IPv6 address to list '" . $FwListName . \ :do {
"' with " . $Timeout . ": " . $Address); /ipv6/firewall/address-list/add list=$FwListName comment=$ListComment \
:do { address=$Address timeout=$Timeout;
/ipv6/firewall/address-list/add list=$FwListName comment=$ListComment \ :set ($IPv6Addresses->$Address);
address=$Address timeout=$Timeout; :set CntAdd ($CntAdd + 1);
:set CntAdd ($CntAdd + 1); } on-error={
} on-error={ $LogPrint warning $ScriptName ("Failed to add IPv6 address to list '" . $FwListName . \
$LogPrint warning $ScriptName ("Failed to add IPv6 address to list '" . $FwListName . \ "': " . $Address);
"': " . $Address);
}
} }
} }

View file

@ -33,8 +33,6 @@
:global TelegramChatId ""; :global TelegramChatId "";
#:global TelegramTokenId "123456:ABCDEF-GHI"; #:global TelegramTokenId "123456:ABCDEF-GHI";
#:global TelegramChatId "12345678"; #:global TelegramChatId "12345678";
# Use this to send notifications to a specific topic in group.
:global TelegramThreadId "";
# Using telegram-chat you have to define trusted chat ids (not group ids!) # Using telegram-chat you have to define trusted chat ids (not group ids!)
# or user names. Groups allow to chat with devices simultaneously. # or user names. Groups allow to chat with devices simultaneously.
#:global TelegramChatIdsTrusted { #:global TelegramChatIdsTrusted {
@ -58,9 +56,9 @@
# install the module: # install the module:
# $ScriptInstallUpdate mod/notification-ntfy # $ScriptInstallUpdate mod/notification-ntfy
:global NtfyServer "ntfy.sh"; :global NtfyServer "ntfy.sh";
:global NtfyServerUser ""; :global NtfyServerUser [];
:global NtfyServerPass ""; :global NtfyServerPass [];
:global NtfyServerToken ""; :global NtfyServerToken [];
:global NtfyTopic ""; :global NtfyTopic "";
# It is possible to override e-mail, Telegram, Matrix and Ntfy setting # It is possible to override e-mail, Telegram, Matrix and Ntfy setting
@ -92,7 +90,6 @@
:global BackupPartitionCopyBeforeFeatureUpdate false; :global BackupPartitionCopyBeforeFeatureUpdate false;
# This defines the settings for firewall address-lists (fw-addr-lists). # This defines the settings for firewall address-lists (fw-addr-lists).
# Warning: Mind your device's resources - memory and processing!
:global FwAddrLists { :global FwAddrLists {
# "allow"={ # "allow"={
# { url="https://rsc.eworm.de/main/fw-addr-lists.d/allow"; # { url="https://rsc.eworm.de/main/fw-addr-lists.d/allow";
@ -101,9 +98,10 @@
"block"={ "block"={
# { url="https://rsc.eworm.de/main/fw-addr-lists.d/block"; # { url="https://rsc.eworm.de/main/fw-addr-lists.d/block";
# cert="ISRG Root X2" }; # cert="ISRG Root X2" };
{ url="https://raw.githubusercontent.com/stamparm/ipsum/refs/heads/master/levels/4.txt"; { url="https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.txt";
# # higher level (decrease the numerical value) for more addresses, and vice versa cert="GlobalSign" };
cert="USERTrust RSA Certification Authority" }; { url="https://sslbl.abuse.ch/blacklist/sslipblacklist.txt";
cert="GlobalSign" };
{ url="https://www.dshield.org/block.txt"; cidr="/24"; { url="https://www.dshield.org/block.txt"; cidr="/24";
cert="ISRG Root X1" }; cert="ISRG Root X1" };
{ url="https://lists.blocklist.de/lists/strongips.txt"; { url="https://lists.blocklist.de/lists/strongips.txt";
@ -121,17 +119,17 @@
:global FwAddrListTimeOut 1d; :global FwAddrListTimeOut 1d;
# This defines what log messages to filter or include by topic or message # This defines what log messages to filter or include by topic or message
# text. Regular expressions are supported. An empty string has a special # text. Regular expressions are supported. Do *NOT* set an empty string,
# meaning not to filter or include anything. # that will filter or include everything!
# These are filters, so excluding messages from forwarding. # These are filters, so excluding messages from forwarding.
:global LogForwardFilter "(debug|info|packet|raw)"; :global LogForwardFilter "(debug|info|packet|raw)";
:global LogForwardFilterMessage ""; :global LogForwardFilterMessage [];
#:global LogForwardFilterMessage "message text"; #:global LogForwardFilterMessage "message text";
#:global LogForwardFilterMessage "(message text|another text|...)"; #:global LogForwardFilterMessage "(message text|another text|...)";
# ... and another setting with reverse logic. This includes messages even # ... and another setting with reverse logic. This includes messages even
# if filtered above. # if filtered above.
:global LogForwardInclude ""; :global LogForwardInclude [];
:global LogForwardIncludeMessage ""; :global LogForwardIncludeMessage [];
#:global LogForwardInclude "account"; #:global LogForwardInclude "account";
#:global LogForwardIncludeMessage "message text"; #:global LogForwardIncludeMessage "message text";

View file

@ -12,10 +12,8 @@
:local ScriptName [ :jobname ]; :local ScriptName [ :jobname ];
# Git commit id & info, expected configuration version # expected configuration version
:global CommitId "unknown"; :global ExpectedConfigVersion 132;
:global CommitInfo "unknown";
:global ExpectedConfigVersion 135;
# global variables not to be changed by user # global variables not to be changed by user
:global GlobalFunctionsReady false; :global GlobalFunctionsReady false;
@ -55,7 +53,6 @@
:global IsTimeSync; :global IsTimeSync;
:global LogPrint; :global LogPrint;
:global LogPrintOnce; :global LogPrintOnce;
:global LogPrintVerbose;
:global MAX; :global MAX;
:global MIN; :global MIN;
:global MkDir; :global MkDir;
@ -287,8 +284,6 @@
# get readable device info # get readable device info
:set DeviceInfo do={ :set DeviceInfo do={
:global CommitId;
:global CommitInfo;
:global ExpectedConfigVersion; :global ExpectedConfigVersion;
:global Identity; :global Identity;
@ -310,19 +305,16 @@
([ $FormatLine "Location" ($Snmp->"location") ] . "\n") ] . \ ([ $FormatLine "Location" ($Snmp->"location") ] . "\n") ] . \
[ $IfThenElse ([ :len ($Snmp->"contact") ] > 0) \ [ $IfThenElse ([ :len ($Snmp->"contact") ] > 0) \
([ $FormatLine "Contact" ($Snmp->"contact") ] . "\n") ] . \ ([ $FormatLine "Contact" ($Snmp->"contact") ] . "\n") ] . \
"Hardware:\n" . \ [ $FormatLine "Board name" ($Resource->"board-name") ] . "\n" . \
[ $FormatLine " Board" ($Resource->"board-name") ] . "\n" . \ [ $FormatLine "Architecture" ($Resource->"architecture-name") ] . "\n" . \
[ $FormatLine " Arch" ($Resource->"architecture-name") ] . "\n" . \
[ $IfThenElse ($RouterBoard->"routerboard" = true) \ [ $IfThenElse ($RouterBoard->"routerboard" = true) \
([ $FormatLine " Model" ($RouterBoard->"model") ] . \ ([ $FormatLine "Model" ($RouterBoard->"model") ] . \
[ $IfThenElse ([ :len ($RouterBoard->"revision") ] > 0) \ [ $IfThenElse ([ :len ($RouterBoard->"revision") ] > 0) \
(" " . $RouterBoard->"revision") ] . "\n" . \ (" " . $RouterBoard->"revision") ] . "\n" . \
[ $FormatLine " Serial" ($RouterBoard->"serial-number") ] . "\n") ] . \ [ $FormatLine "Serial number" ($RouterBoard->"serial-number") ] . "\n") ] . \
[ $IfThenElse ([ :len ($License->"nlevel") ] > 0) \
([ $FormatLine " License" ("level " . ($License->"nlevel")) ] . "\n") ] . \
"RouterOS:\n" . \
[ $IfThenElse ([ :len ($License->"level") ] > 0) \ [ $IfThenElse ([ :len ($License->"level") ] > 0) \
([ $FormatLine " License" ("level " . ($License->"level")) ] . "\n") ] . \ ([ $FormatLine "License" ($License->"level") ] . "\n") ] . \
"RouterOS:\n" . \
[ $FormatLine " Channel" ($Update->"channel") ] . "\n" . \ [ $FormatLine " Channel" ($Update->"channel") ] . "\n" . \
[ $FormatLine " Installed" ($Update->"installed-version") ] . "\n" . \ [ $FormatLine " Installed" ($Update->"installed-version") ] . "\n" . \
[ $IfThenElse ([ :typeof ($Update->"latest-version") ] != "nothing" && \ [ $IfThenElse ([ :typeof ($Update->"latest-version") ] != "nothing" && \
@ -332,8 +324,6 @@
$RouterBoard->"current-firmware" != $RouterBoard->"upgrade-firmware") \ $RouterBoard->"current-firmware" != $RouterBoard->"upgrade-firmware") \
([ $FormatLine " Firmware" ($RouterBoard->"current-firmware") ] . "\n") ] . \ ([ $FormatLine " Firmware" ($RouterBoard->"current-firmware") ] . "\n") ] . \
"RouterOS-Scripts:\n" . \ "RouterOS-Scripts:\n" . \
[ $IfThenElse ($CommitId != "unknown") \
([ $FormatLine " Commit" ($CommitInfo . "/" . [ :pick $CommitId 0 8 ]) ] . "\n") ] . \
[ $FormatLine " Version" $ExpectedConfigVersion ]); [ $FormatLine " Version" $ExpectedConfigVersion ]);
} }
@ -849,9 +839,6 @@
:return true; :return true;
} }
# The function $LogPrintVerbose is declared, but has no code, intentionally.
# https://rsc.eworm.de/DEBUG.md#verbose-output
# get max value # get max value
:set MAX do={ :set MAX do={
:if ($1 > $2) do={ :return $1; } :if ($1 > $2) do={ :return $1; }
@ -904,10 +891,7 @@
:return true; :return true;
} }
$LogPrint debug $0 ("Making directory: " . $Path);
:if ([ :len [ /file/find where name=$Path type="directory" ] ] = 1) do={ :if ([ :len [ /file/find where name=$Path type="directory" ] ] = 1) do={
$LogPrint debug $0 ("... which already exists.");
:return true; :return true;
} }
@ -1063,12 +1047,12 @@
$LogPrint debug $0 ("Removing file: ". $FileName); $LogPrint debug $0 ("Removing file: ". $FileName);
:if ([ :len [ /file/find where name=$FileName (type=directory or type=disk) ] ] > 0) do={ :if ([ :len [ /file/find where name=$FileName type!=file ] ] > 0) do={
$LogPrint error $0 ("File '" . $FileName . "' is not a file."); $LogPrint error $0 ("File '" . $FileName . "' is not a file.");
:return false; :return false;
} }
:local File [ /file/find where name=$FileName !(type=directory or type=disk) ]; :local File [ /file/find where name=$FileName type=file ];
:if ([ :len $File ] = 0) do={ :if ([ :len $File ] = 0) do={
$LogPrint debug $0 ("... which does not exist."); $LogPrint debug $0 ("... which does not exist.");
:return true; :return true;
@ -1114,8 +1098,6 @@
:local Scripts [ :toarray $1 ]; :local Scripts [ :toarray $1 ];
:local NewComment [ :tostr $2 ]; :local NewComment [ :tostr $2 ];
:global CommitId;
:global CommitInfo;
:global ExpectedConfigVersion; :global ExpectedConfigVersion;
:global Identity; :global Identity;
:global IDonate; :global IDonate;
@ -1148,20 +1130,11 @@
} }
} }
:local CommitIdBefore $CommitId;
:local ExpectedConfigVersionBefore $ExpectedConfigVersion; :local ExpectedConfigVersionBefore $ExpectedConfigVersion;
:local ReloadGlobalFunctions false; :local ReloadGlobalFunctions false;
:local ReloadGlobalConfig false; :local ReloadGlobalConfig false;
:local DeviceMode [ /system/device-mode/get ]; :local DeviceMode [ /system/device-mode/get ];
:local CheckSums ({});
:do {
:local Url ($ScriptUpdatesBaseUrl . "checksums.json" . $ScriptUpdatesUrlSuffix);
$LogPrint debug $0 ("Fetching checksums from url: " . $Url);
:set CheckSums [ :deserialize from=json ([ /tool/fetch check-certificate=yes-without-crl \
http-header-field=({ [ $FetchUserAgentStr $0 ] }) $Url output=user as-value ]->"data") ];
} on-error={ }
:foreach Script in=[ /system/script/find where source~"^#!rsc by RouterOS\r?\n" ] do={ :foreach Script in=[ /system/script/find where source~"^#!rsc by RouterOS\r?\n" ] do={
:local ScriptVal [ /system/script/get $Script ]; :local ScriptVal [ /system/script/get $Script ];
:local ScriptInfo [ $ParseKeyValueStore ($ScriptVal->"comment") ]; :local ScriptInfo [ $ParseKeyValueStore ($ScriptVal->"comment") ];
@ -1175,19 +1148,7 @@
} }
} }
:do { :if (!($ScriptInfo->"ignore" = true)) do={
:if ($ScriptInfo->"ignore" = true) do={
$LogPrint debug $0 ("Ignoring script '" . $ScriptVal->"name" . "', as requested.");
:error true;
}
:local CheckSum ($CheckSums->($ScriptVal->"name"));
:if ([ :len ($ScriptInfo->"base-url") ] = 0 && [ :len ($ScriptInfo->"url-suffix") ] = 0 && \
[ :convert transform=md5 to=hex [ :tolf ($ScriptVal->"source") ] ] = $CheckSum) do={
$LogPrint debug $0 ("Checksum for script '" . $ScriptVal->"name" . "' matches, ignoring.");
:error true;
}
:do { :do {
:local BaseUrl [ $EitherOr ($ScriptInfo->"base-url") $ScriptUpdatesBaseUrl ]; :local BaseUrl [ $EitherOr ($ScriptInfo->"base-url") $ScriptUpdatesBaseUrl ];
:local UrlSuffix [ $EitherOr ($ScriptInfo->"url-suffix") $ScriptUpdatesUrlSuffix ]; :local UrlSuffix [ $EitherOr ($ScriptInfo->"url-suffix") $ScriptUpdatesUrlSuffix ];
@ -1206,9 +1167,10 @@
} else={ } else={
$LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "'!"); $LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "'!");
} }
:error false;
} }
}
:do {
:if ([ :len $SourceNew ] = 0) do={ :if ([ :len $SourceNew ] = 0) do={
$LogPrint debug $0 ("No update for script '" . $ScriptVal->"name" . "'."); $LogPrint debug $0 ("No update for script '" . $ScriptVal->"name" . "'.");
:error false; :error false;
@ -1282,10 +1244,6 @@
} }
} }
:if ($CommitId != "unknown" && $CommitIdBefore != $CommitId) do={
$LogPrint info $0 ("Updated to commit: " . $CommitInfo . "/" . [ :pick $CommitId 0 8 ]);
}
:if ($ExpectedConfigVersionBefore > $ExpectedConfigVersion) do={ :if ($ExpectedConfigVersionBefore > $ExpectedConfigVersion) do={
$LogPrint warning $0 ("The configuration version decreased from " . \ $LogPrint warning $0 ("The configuration version decreased from " . \
$ExpectedConfigVersionBefore . " to " . $ExpectedConfigVersion . \ $ExpectedConfigVersionBefore . " to " . $ExpectedConfigVersion . \
@ -1721,17 +1679,7 @@
:delay $Delay; :delay $Delay;
:set I ($I + 1); :set I ($I + 1);
} }
:return true;
:while ([ :len [ /file/find where name=$FileName ] ] > 0) do={
:do {
/file/get $FileName;
:return true;
} on-error={ }
:delay $Delay;
:set Delay ($Delay * 3 / 2);
}
:return false;
} }
# wait to be fully connected (default route is reachable, time is sync, DNS resolves) # wait to be fully connected (default route is reachable, time is sync, DNS resolves)

View file

@ -20,9 +20,7 @@
:global ScriptLock; :global ScriptLock;
:local NaAddress $"na-address"; :local NaAddress $"na-address";
:local NaValid $"na-valid";
:local PdPrefix $"pd-prefix"; :local PdPrefix $"pd-prefix";
:local PdValid $"pd-valid";
:if ([ $ScriptLock $ScriptName ] = false) do={ :if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true; :set ExitOK true;
@ -35,18 +33,12 @@
:error false; :error false;
} }
:if ([ :typeof $PdPrefix ] = "nothing" || [ :typeof $PdValid ] = "nothing") do={ :if ([ :typeof $PdPrefix ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from ipv6 dhcp-client."); $LogPrint error $ScriptName ("This script is supposed to run from ipv6 dhcp-client.");
:set ExitOK true; :set ExitOK true;
:error false; :error false;
} }
:if ($PdValid != 1) do={
$LogPrint info $ScriptName ("The prefix " . $PdPrefix . " is no longer valid. Ignoring.");
:set ExitOK true;
:error false;
}
:local Pool [ /ipv6/pool/get [ find where prefix=$PdPrefix ] name ]; :local Pool [ /ipv6/pool/get [ find where prefix=$PdPrefix ] name ];
:if ([ :len [ /ipv6/firewall/address-list/find where comment=("ipv6-pool-" . $Pool) ] ] = 0) do={ :if ([ :len [ /ipv6/firewall/address-list/find where comment=("ipv6-pool-" . $Pool) ] ] = 0) do={
/ipv6/firewall/address-list/add list=("ipv6-pool-" . $Pool) address=:: comment=("ipv6-pool-" . $Pool) dynamic=yes; /ipv6/firewall/address-list/add list=("ipv6-pool-" . $Pool) address=:: comment=("ipv6-pool-" . $Pool) dynamic=yes;

View file

@ -57,11 +57,6 @@
:local MessageVal; :local MessageVal;
:local MessageDups ({}); :local MessageDups ({});
:set LogForwardFilter [ $EitherOr $LogForwardFilter [] ];
:set LogForwardFilterMessage [ $EitherOr $LogForwardFilterMessage [] ];
:set LogForwardInclude [ $EitherOr $LogForwardInclude [] ];
:set LogForwardIncludeMessage [ $EitherOr $LogForwardIncludeMessage [] ];
:local LogForwardFilterLogForwardingCached [ $EitherOr [ $LogForwardFilterLogForwarding ] ("\$^") ]; :local LogForwardFilterLogForwardingCached [ $EitherOr [ $LogForwardFilterLogForwarding ] ("\$^") ];
:foreach Message in=[ /log/find where (!(message="") and \ :foreach Message in=[ /log/find where (!(message="") and \
!(message~$LogForwardFilterLogForwardingCached) and \ !(message~$LogForwardFilterLogForwardingCached) and \

View file

@ -10,7 +10,6 @@
# https://rsc.eworm.de/doc/mod/notification-telegram.md # https://rsc.eworm.de/doc/mod/notification-telegram.md
:global FlushTelegramQueue; :global FlushTelegramQueue;
:global GetTelegramChatId;
:global NotificationFunctions; :global NotificationFunctions;
:global PurgeTelegramQueue; :global PurgeTelegramQueue;
:global SendTelegram; :global SendTelegram;
@ -23,6 +22,7 @@
:global IsFullyConnected; :global IsFullyConnected;
:global LogPrint; :global LogPrint;
:global UrlEncode;
:if ([ $IsFullyConnected ] = false) do={ :if ([ $IsFullyConnected ] = false) do={
$LogPrint debug $0 ("System is not fully connected, not flushing."); $LogPrint debug $0 ("System is not fully connected, not flushing.");
@ -41,7 +41,9 @@
:do { :do {
:local Data ([ /tool/fetch check-certificate=yes-without-crl output=user http-method=post \ :local Data ([ /tool/fetch check-certificate=yes-without-crl output=user http-method=post \
("https://api.telegram.org/bot" . ($Message->"tokenid") . "/sendMessage") \ ("https://api.telegram.org/bot" . ($Message->"tokenid") . "/sendMessage") \
http-data=($Message->"http-data") as-value ]->"data"); http-data=("chat_id=" . ($Message->"chatid") . "&disable_notification=" . ($Message->"silent") . \
"&reply_to_message_id=" . ($Message->"replyto") . "&disable_web_page_preview=true" . \
"&parse_mode=MarkdownV2&text=" . [ $UrlEncode ($Message->"text") ]) as-value ]->"data");
:set ($TelegramQueue->$Id); :set ($TelegramQueue->$Id);
:set ($TelegramMessageIDs->[ :tostr ([ :deserialize from=json value=$Data ]->"result"->"message_id") ]) 1; :set ($TelegramMessageIDs->[ :tostr ([ :deserialize from=json value=$Data ]->"result"->"message_id") ]) 1;
} on-error={ } on-error={
@ -59,45 +61,6 @@
:global ExitError; $ExitError false $0; :global ExitError; $ExitError false $0;
} } } }
# get the chat id
:set GetTelegramChatId do={ :do {
:global TelegramTokenId;
:global CertificateAvailable;
:global LogPrint;
:if ([ $CertificateAvailable "Go Daddy Root Certificate Authority - G2" ] = false) do={
$LogPrint warning $0 ("Downloading required certificate failed.");
:return false;
}
:local Data;
:do {
:set Data ([ /tool/fetch check-certificate=yes-without-crl output=user \
("https://api.telegram.org/bot" . $TelegramTokenId . "/getUpdates?offset=0" . \
"&allowed_updates=%5B%22message%22%5D") as-value ]->"data");
} on-error={
$LogPrint warning $0 ("Fetching data failed!");
:return false;
}
:local JSON [ :deserialize from=json value=$Data ];
:local Count [ :len ($JSON->"result") ];
:if ($Count = 0) do={
$LogPrint info $0 ("No message received.");
:return false;
}
:local Message ($JSON->"result"->($Count - 1)->"message");
$LogPrint info $0 ("The chat id is: " . ($Message->"chat"->"id"));
:if (($Message->"is_topic_message") = true) do={
$LogPrint info $0 ("The thread id is: " . ($Message->"message_thread_id"));
}
} on-error={
:global ExitError; $ExitError false $0;
} }
# send notification via telegram - expects one array argument # send notification via telegram - expects one array argument
:set ($NotificationFunctions->"telegram") do={ :set ($NotificationFunctions->"telegram") do={
:local Notification $1; :local Notification $1;
@ -108,8 +71,6 @@
:global TelegramChatIdOverride; :global TelegramChatIdOverride;
:global TelegramMessageIDs; :global TelegramMessageIDs;
:global TelegramQueue; :global TelegramQueue;
:global TelegramThreadId;
:global TelegramThreadIdOverride;
:global TelegramTokenId; :global TelegramTokenId;
:global TelegramTokenIdOverride; :global TelegramTokenIdOverride;
@ -150,8 +111,6 @@
:local ChatId [ $EitherOr ($Notification->"chatid") \ :local ChatId [ $EitherOr ($Notification->"chatid") \
[ $EitherOr ($TelegramChatIdOverride->($Notification->"origin")) $TelegramChatId ] ]; [ $EitherOr ($TelegramChatIdOverride->($Notification->"origin")) $TelegramChatId ] ];
:local ThreadId [ $EitherOr ($Notification->"threadid") \
[ $EitherOr ($TelegramThreadIdOverride->($Notification->"origin")) $TelegramThreadId ] ];
:local TokenId [ $EitherOr ($TelegramTokenIdOverride->($Notification->"origin")) $TelegramTokenId ]; :local TokenId [ $EitherOr ($TelegramTokenIdOverride->($Notification->"origin")) $TelegramTokenId ];
:if ([ :len $TokenId ] = 0 || [ :len $ChatId ] = 0) do={ :if ([ :len $TokenId ] = 0 || [ :len $ChatId ] = 0) do={
@ -186,9 +145,6 @@
(($LenSum - [ :len $Text ]) * 100 / $LenSum) . "%_!") "plain" "_" ]); (($LenSum - [ :len $Text ]) * 100 / $LenSum) . "%_!") "plain" "_" ]);
} }
:local HTTPData ("chat_id=" . $ChatId . "&disable_notification=" . ($Notification->"silent") . \
"&reply_to_message_id=" . ($Notification->"replyto") . "&message_thread_id=" . $ThreadId . \
"&disable_web_page_preview=true&parse_mode=MarkdownV2");
:do { :do {
:if ([ $CertificateAvailable "Go Daddy Root Certificate Authority - G2" ] = false) do={ :if ([ $CertificateAvailable "Go Daddy Root Certificate Authority - G2" ] = false) do={
$LogPrint warning $0 ("Downloading required certificate failed."); $LogPrint warning $0 ("Downloading required certificate failed.");
@ -196,7 +152,9 @@
} }
:local Data ([ /tool/fetch check-certificate=yes-without-crl output=user http-method=post \ :local Data ([ /tool/fetch check-certificate=yes-without-crl output=user http-method=post \
("https://api.telegram.org/bot" . $TokenId . "/sendMessage") \ ("https://api.telegram.org/bot" . $TokenId . "/sendMessage") \
http-data=($HTTPData . "&text=" . [ $UrlEncode $Text ]) as-value ]->"data"); http-data=("chat_id=" . $ChatId . "&disable_notification=" . ($Notification->"silent") . \
"&reply_to_message_id=" . ($Notification->"replyto") . "&disable_web_page_preview=true" . \
"&parse_mode=MarkdownV2&text=" . [ $UrlEncode $Text ]) as-value ]->"data");
:set ($TelegramMessageIDs->[ :tostr ([ :deserialize from=json value=$Data ]->"result"->"message_id") ]) 1; :set ($TelegramMessageIDs->[ :tostr ([ :deserialize from=json value=$Data ]->"result"->"message_id") ]) 1;
} on-error={ } on-error={
$LogPrint info $0 ("Failed sending Telegram notification! Queuing..."); $LogPrint info $0 ("Failed sending Telegram notification! Queuing...");
@ -207,8 +165,8 @@
:set Text ($Text . "\n" . [ $SymbolForNotification "alarm-clock" ] . \ :set Text ($Text . "\n" . [ $SymbolForNotification "alarm-clock" ] . \
[ $EscapeMD ("This message was queued since _" . [ /system/clock/get date ] . \ [ $EscapeMD ("This message was queued since _" . [ /system/clock/get date ] . \
" " . [ /system/clock/get time ] . "_ and may be obsolete.") "plain" "_" ]); " " . [ /system/clock/get time ] . "_ and may be obsolete.") "plain" "_" ]);
:set ($TelegramQueue->[ :len $TelegramQueue ]) { tokenid=$TokenId; :set ($TelegramQueue->[ :len $TelegramQueue ]) { chatid=$ChatId; tokenid=$TokenId;
http-data=($HTTPData . "&text=" . [ $UrlEncode $Text ]) }; text=$Text; silent=($Notification->"silent"); replyto=($Notification->"replyto") };
:if ([ :len [ /system/scheduler/find where name="_FlushTelegramQueue" ] ] = 0) do={ :if ([ :len [ /system/scheduler/find where name="_FlushTelegramQueue" ] ] = 0) do={
/system/scheduler/add name="_FlushTelegramQueue" interval=1m start-time=startup \ /system/scheduler/add name="_FlushTelegramQueue" interval=1m start-time=startup \
on-event=(":global FlushTelegramQueue; \$FlushTelegramQueue;"); on-event=(":global FlushTelegramQueue; \$FlushTelegramQueue;");

View file

@ -4,6 +4,7 @@
# https://rsc.eworm.de/COPYING.md # https://rsc.eworm.de/COPYING.md
# #
# requires RouterOS, version=7.15 # requires RouterOS, version=7.15
# requires device-mode, fetch
# #
# download script and run it once # download script and run it once
# https://rsc.eworm.de/doc/mod/scriptrunonce.md # https://rsc.eworm.de/doc/mod/scriptrunonce.md
@ -17,7 +18,6 @@
:global ScriptRunOnceBaseUrl; :global ScriptRunOnceBaseUrl;
:global ScriptRunOnceUrlSuffix; :global ScriptRunOnceUrlSuffix;
:global FetchHuge;
:global LogPrint; :global LogPrint;
:global ValidateSyntax; :global ValidateSyntax;
@ -30,26 +30,25 @@
:set Script ($ScriptRunOnceBaseUrl . $Script . ".rsc" . $ScriptRunOnceUrlSuffix); :set Script ($ScriptRunOnceBaseUrl . $Script . ".rsc" . $ScriptRunOnceUrlSuffix);
} }
:local Source [ $FetchHuge $0 $Script true ]; :local Source;
:if ($Source = false) do={
$LogPrint warning $0 ("Failed fetching script '" . $Script . "'!");
:return false;
}
:if ([ $ValidateSyntax $Source ] = false) do={
$LogPrint warning $0 ("The script '" . $Script . "' failed syntax validation!");
:return false;
}
:do { :do {
$LogPrint info $0 ("Running script '" . $Script . "' now."); :set Source ([ /tool/fetch check-certificate=yes-without-crl $Script output=user as-value ]->"data");
[ :parse $Source ];
} on-error={ } on-error={
$LogPrint warning $0 ("The script '" . $Script . "' failed to run!"); $LogPrint warning $0 ("Failed fetching script '" . $Script . "'!");
:return false;
} }
:return true; :if ([ :len $Source ] > 0) do={
:if ([ $ValidateSyntax $Source ] = true) do={
:do {
$LogPrint info $0 ("Running script '" . $Script . "' now.");
[ :parse $Source ];
} on-error={
$LogPrint warning $0 ("The script '" . $Script . "' failed to run!");
}
} else={
$LogPrint warning $0 ("The script '" . $Script . "' failed syntax validation!");
}
}
} }
} on-error={ } on-error={
:global ExitError; $ExitError false $0; :global ExitError; $ExitError false $0;

View file

@ -61,19 +61,15 @@
:global GetRandom20CharAlNum; :global GetRandom20CharAlNum;
:local FwAddrList ($ScriptName . "-" . [ $GetRandom20CharAlNum ]); :local FwAddrList ($ScriptName . "-" . [ $GetRandom20CharAlNum ]);
:if ([ :typeof [ :toip $Expected ] ] = "ip") do={ /ip/firewall/address-list/add address=$Name list=$FwAddrList dynamic=yes timeout=1s;
/ip/firewall/address-list/add address=$Name list=$FwAddrList dynamic=yes timeout=10s; :delay 20ms;
:delay 20ms; :if ([ :len [ /ip/firewall/address-list/find where list=$FwAddrList address=$Expected ] ] > 0) do={
:if ([ :len [ /ip/firewall/address-list/find where list=$FwAddrList address=$Expected ] ] > 0) do={ :return true;
:return true;
}
} }
:if ([ :typeof [ :toip6 $Expected ] ] = "ip6") do={ /ipv6/firewall/address-list/add address=$Name list=$FwAddrList dynamic=yes timeout=1s;
/ipv6/firewall/address-list/add address=$Name list=$FwAddrList dynamic=yes timeout=10s; :delay 20ms;
:delay 20ms; :if ([ :len [ /ipv6/firewall/address-list/find where list=$FwAddrList address=$Expected ] ] > 0) do={
:if ([ :len [ /ipv6/firewall/address-list/find where list=$FwAddrList address=$Expected ] ] > 0) do={ :return true;
:return true;
}
} }
:return false; :return false;

View file

@ -57,9 +57,6 @@
130="Dropped intermediate certificates, depending on just root certificates now."; 130="Dropped intermediate certificates, depending on just root certificates now.";
131="Enhanced certificate download to fallback to mkcert.org, so all (commonly trusted) root certificates are available now."; 131="Enhanced certificate download to fallback to mkcert.org, so all (commonly trusted) root certificates are available now.";
132="Split off plugins from 'check-health', so the script works on all devices to monitor CPU and RAM. The supported plugins for sensors in hardware are installed automatically."; 132="Split off plugins from 'check-health', so the script works on all devices to monitor CPU and RAM. The supported plugins for sensors in hardware are installed automatically.";
133="Updated the default configuration for 'fw-addr-lists', deprecated lists were removed, a collective list was added.";
134="Enhanced 'mod/notification-telegram' and 'telegram-chat' to support topics in groups.";
135="Introduced helper function '\$GetTelegramChatId' for 'mod/notification-telegram' which helps retrieve information.";
}; };
# Migration steps to be applied on script updates # Migration steps to be applied on script updates

View file

@ -97,14 +97,13 @@
:foreach Update in=($JSON->"result") do={ :foreach Update in=($JSON->"result") do={
:set UpdateID ($Update->"update_id"); :set UpdateID ($Update->"update_id");
:local Message ($Update->"message"); :local Message ($Update->"message");
:local IsReply ([ :typeof ($Message->"reply_to_message") ] = "string"); :local IsReply [ :len ($Message->"reply_to_message") ];
:local IsMyReply ($TelegramMessageIDs->[ :tostr ($Message->"reply_to_message"->"message_id") ]); :local IsMyReply ($TelegramMessageIDs->[ :tostr ($Message->"reply_to_message"->"message_id") ]);
:if (($IsMyReply = 1 || $TelegramChatOffset->0 > 0 || $Uptime > 5m) && $UpdateID >= $TelegramChatOffset->2) do={ :if (($IsMyReply = 1 || $TelegramChatOffset->0 > 0 || $Uptime > 5m) && $UpdateID >= $TelegramChatOffset->2) do={
:local Trusted false; :local Trusted false;
:local Chat ($Message->"chat"); :local Chat ($Message->"chat");
:local From ($Message->"from"); :local From ($Message->"from");
:local Command ($Message->"text"); :local Command ($Message->"text");
:local ThreadId [ $IfThenElse ($Message->"is_topic_message") ($Message->"message_thread_id") "" ];
:foreach IdsTrusted in=($TelegramChatId, $TelegramChatIdsTrusted) do={ :foreach IdsTrusted in=($TelegramChatId, $TelegramChatIdsTrusted) do={
:if ($From->"id" = $IdsTrusted || $From->"username" = $IdsTrusted) do={ :if ($From->"id" = $IdsTrusted || $From->"username" = $IdsTrusted) do={
@ -116,11 +115,9 @@
:local Done false; :local Done false;
:if ($Command = "?") do={ :if ($Command = "?") do={
$LogPrint info $ScriptName ("Sending notice for update " . $UpdateID . "."); $LogPrint info $ScriptName ("Sending notice for update " . $UpdateID . ".");
$SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=true; \ $SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=true; replyto=($Message->"message_id"); \
replyto=($Message->"message_id"); threadid=$ThreadId; \
subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \ subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \
message=([ $IfThenElse ([ :len ($From->"first_name") ] > 0) ("Hello " . ($From->"first_name") . "!\n\n") ] . \ message=("Online" . [ $IfThenElse $TelegramChatActive " (and active!)" ] . ", awaiting your commands!") });
"Online" . [ $IfThenElse $TelegramChatActive " (and active!)" ] . ", awaiting your commands!") });
:set Done true; :set Done true;
} }
:if ($Done = false && [ :pick $Command 0 1 ] = "!") do={ :if ($Done = false && [ :pick $Command 0 1 ] = "!") do={
@ -133,8 +130,7 @@
" from update " . $UpdateID . "!"); " from update " . $UpdateID . "!");
:set Done true; :set Done true;
} }
:if ($Done = false && ($IsMyReply = 1 || ($IsReply = false && \ :if ($Done = false && ($IsMyReply = 1 || ($IsReply = 0 && $TelegramChatActive = true)) && [ :len $Command ] > 0) do={
$TelegramChatActive = true)) && [ :len $Command ] > 0) do={
:if ([ $ValidateSyntax $Command ] = true) do={ :if ([ $ValidateSyntax $Command ] = true) do={
:local State ""; :local State "";
:local File ("tmpfs/telegram-chat/" . [ $GetRandom20CharAlNum 6 ]); :local File ("tmpfs/telegram-chat/" . [ $GetRandom20CharAlNum 6 ]);
@ -153,8 +149,7 @@
:set State ([ $SymbolForNotification "cross-mark" ] . "The command failed with an error!\n\n"); :set State ([ $SymbolForNotification "cross-mark" ] . "The command failed with an error!\n\n");
} }
:local Content ([ /file/read chunk-size=32768 file=$File as-value ]->"data"); :local Content ([ /file/read chunk-size=32768 file=$File as-value ]->"data");
$SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=true; \ $SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=true; replyto=($Message->"message_id"); \
replyto=($Message->"message_id"); threadid=$ThreadId; \
subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \ subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \
message=([ $SymbolForNotification "gear" ] . "Command:\n" . $Command . "\n\n" . \ message=([ $SymbolForNotification "gear" ] . "Command:\n" . $Command . "\n\n" . \
$State . [ $IfThenElse ([ :len $Content ] > 0) \ $State . [ $IfThenElse ([ :len $Content ] > 0) \
@ -163,8 +158,7 @@
$RmDir "tmpfs/telegram-chat"; $RmDir "tmpfs/telegram-chat";
} else={ } else={
$LogPrint info $ScriptName ("The command from update " . $UpdateID . " failed syntax validation!"); $LogPrint info $ScriptName ("The command from update " . $UpdateID . " failed syntax validation!");
$SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=false; \ $SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=false; replyto=($Message->"message_id"); \
replyto=($Message->"message_id"); threadid=$ThreadId; \
subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \ subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \
message=([ $SymbolForNotification "gear" ] . "Command:\n" . $Command . "\n\n" . \ message=([ $SymbolForNotification "gear" ] . "Command:\n" . $Command . "\n\n" . \
[ $SymbolForNotification "cross-mark" ] . "The command failed syntax validation!") }); [ $SymbolForNotification "cross-mark" ] . "The command failed syntax validation!") });
@ -176,8 +170,7 @@
" (ID " . $From->"id" . ") in update " . $UpdateID . "!"); " (ID " . $From->"id" . ") in update " . $UpdateID . "!");
:if ($Command ~ ("^! *" . [ $EscapeForRegEx $Identity ] . "\$")) do={ :if ($Command ~ ("^! *" . [ $EscapeForRegEx $Identity ] . "\$")) do={
$LogPrint warning $ScriptName $MessageText; $LogPrint warning $ScriptName $MessageText;
$SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=false; \ $SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=false; replyto=($Message->"message_id"); \
replyto=($Message->"message_id"); threadid=$ThreadId; \
subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \ subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \
message=("You are not trusted.") }); message=("You are not trusted.") });
} else={ } else={