From 302fc0bb82f7a10403a7d029cd06598e20bd2942 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 16:00:08 +0100 Subject: [PATCH 01/31] fw-addr-lists: lists.blocklist.de requires 'GTS Root R4' --- certs/Makefile | 2 +- global-config.rsc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/certs/Makefile b/certs/Makefile index 3ccad6e2..35a50c81 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -13,7 +13,7 @@ DOMAINS_DUAL = \ dns.google/GTS-Root-R4 \ dns.quad9.net/DigiCert-Global-Root-G3 \ git.eworm.de/ISRG-Root-X2 \ - lists.blocklist.de/Certum-Trusted-Network-CA \ + lists.blocklist.de/GTS-Root-R4 \ matrix.org/GTS-Root-R4 \ raw.githubusercontent.com/USERTrust-RSA-Certification-Authority \ rsc.eworm.de/ISRG-Root-X2 \ diff --git a/global-config.rsc b/global-config.rsc index 25254123..19787a8d 100644 --- a/global-config.rsc +++ b/global-config.rsc @@ -119,7 +119,7 @@ { url="https://www.dshield.org/block.txt"; cidr="/24"; cert="ISRG Root X1" }; { url="https://lists.blocklist.de/lists/strongips.txt"; - cert="Certum Trusted Network CA" }; + cert="GTS Root R4" }; # { url="https://www.spamhaus.org/drop/drop_v4.json"; # cert="GTS Root R4" }; # { url="https://www.spamhaus.org/drop/drop_v6.json"; From 156b0e4aaf02b6ad5edf734945253e48d90f2c58 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 16:03:38 +0100 Subject: [PATCH 02/31] fw-addr-lists: www.dshield.org requires 'GTS Root R4' --- certs/Makefile | 2 +- global-config.rsc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/certs/Makefile b/certs/Makefile index 35a50c81..da681d09 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -27,7 +27,7 @@ DOMAINS_IPV4 = \ ipv4.tunnelbroker.net/Starfield-Root-Certificate-Authority-G2 \ mkcert.org/ISRG-Root-X1 \ ntfy.sh/ISRG-Root-X1 \ - www.dshield.org/ISRG-Root-X1 \ + www.dshield.org/GTS-Root-R4 \ www.spamhaus.org/GTS-Root-R4 DOMAINS_IPV6 = \ [2606\:4700\:4700\:\:1111]/DigiCert-Global-Root-G2 \ diff --git a/global-config.rsc b/global-config.rsc index 19787a8d..9c35d13f 100644 --- a/global-config.rsc +++ b/global-config.rsc @@ -117,7 +117,7 @@ # # higher level (decrease the numerical value) for more addresses, and vice versa cert="USERTrust RSA Certification Authority" }; { url="https://www.dshield.org/block.txt"; cidr="/24"; - cert="ISRG Root X1" }; + cert="GTS Root R4" }; { url="https://lists.blocklist.de/lists/strongips.txt"; cert="GTS Root R4" }; # { url="https://www.spamhaus.org/drop/drop_v4.json"; From b72a79824e947871bae437e6ad8095b5cc01b045 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 23:04:07 +0100 Subject: [PATCH 03/31] certs: add 'SSL.com Root Certification Authority ECC'... ... to use with Cloudflare DNS. curl -d '["SSL.com Root Certification Authority ECC"]' https://mkcert.org/generate/ | grep -v '^$' > certs/SSL-com-Root-Certification-Authority-ECC.pem --- certs/Makefile | 6 ++--- ...L-com-Root-Certification-Authority-ECC.pem | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 certs/SSL-com-Root-Certification-Authority-ECC.pem diff --git a/certs/Makefile b/certs/Makefile index da681d09..4114b3ff 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -9,7 +9,7 @@ CURL = curl \ DOMAINS_DUAL = \ api.macvendors.com/GTS-Root-R4 \ api.telegram.org/Go-Daddy-Root-Certificate-Authority-G2 \ - cloudflare-dns.com/DigiCert-Global-Root-G2 \ + cloudflare-dns.com/SSL-com-Root-Certification-Authority-ECC \ dns.google/GTS-Root-R4 \ dns.quad9.net/DigiCert-Global-Root-G3 \ git.eworm.de/ISRG-Root-X2 \ @@ -19,7 +19,7 @@ DOMAINS_DUAL = \ rsc.eworm.de/ISRG-Root-X2 \ upgrade.mikrotik.com/ISRG-Root-X1 DOMAINS_IPV4 = \ - 1.1.1.1/DigiCert-Global-Root-G2 \ + 1.1.1.1/SSL-com-Root-Certification-Authority-ECC \ 8.8.8.8/GTS-Root-R1 \ 9.9.9.9/DigiCert-Global-Root-G3 \ api.mullvad.net/ISRG-Root-X1 \ @@ -30,7 +30,7 @@ DOMAINS_IPV4 = \ www.dshield.org/GTS-Root-R4 \ www.spamhaus.org/GTS-Root-R4 DOMAINS_IPV6 = \ - [2606\:4700\:4700\:\:1111]/DigiCert-Global-Root-G2 \ + [2606\:4700\:4700\:\:1111]/SSL-com-Root-Certification-Authority-ECC \ [2001\:4860\:4860\:\:8888]/GTS-Root-R1 \ [2620\:fe\:\:9]/DigiCert-Global-Root-G3 \ ipv6.showipv6.de/ISRG-Root-X1 diff --git a/certs/SSL-com-Root-Certification-Authority-ECC.pem b/certs/SSL-com-Root-Certification-Authority-ECC.pem new file mode 100644 index 00000000..f1166839 --- /dev/null +++ b/certs/SSL-com-Root-Certification-Authority-ECC.pem @@ -0,0 +1,23 @@ +# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com Root Certification Authority ECC" +# Serial: 8495723813297216424 +# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e +# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a +# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- From ad455c8f1d011ba0bbfcfc25f5b5f7f722b2da51 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 23:10:33 +0100 Subject: [PATCH 04/31] doc/netwatch-dns: cloudflare uses a new CA for certificates --- doc/netwatch-dns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/netwatch-dns.md b/doc/netwatch-dns.md index 23190b12..c81ca8c9 100644 --- a/doc/netwatch-dns.md +++ b/doc/netwatch-dns.md @@ -62,7 +62,7 @@ manually! Importing a certificate automatically is possible. You may want to find the [certificate name from browser](../CERTIFICATES.md). - /tool/netwatch/add comment="doh, doh-cert=DigiCert Global Root G2" host=1.1.1.1; + /tool/netwatch/add comment="doh, doh-cert=SSL.com Root Certification Authority ECC" host=1.1.1.1; /tool/netwatch/add comment="doh, doh-cert=DigiCert Global Root G3" host=9.9.9.9; /tool/netwatch/add comment="doh, doh-cert=GTS Root R1" host=8.8.8.8; From d673f0956c23f0ab30c19b28cf0090a0ddb6df27 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 00:00:58 +0100 Subject: [PATCH 05/31] global-functions: $CertificateAvailable: get missing certificate... ... not the issued and available one. --- global-functions.rsc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/global-functions.rsc b/global-functions.rsc index 5c70a463..5d2a5044 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -150,9 +150,9 @@ :local CertVal [ /certificate/get [ find where common-name=$CommonName ] ]; :while (($CertVal->"akid") != "" && ($CertVal->"akid") != ($CertVal->"skid")) do={ :if ([ :len [ /certificate/find where skid=($CertVal->"akid") ] ] = 0) do={ - $LogPrint info $0 ("Certificate chain for '" . $CommonName . \ - "' is incomplete, missing '" . ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") . "'."); - :if ([ $CertificateDownload $CommonName ] = false) do={ + :local IssuerCN ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN"); + $LogPrint info $0 ("Certificate chain for '" . $CommonName . "' is incomplete, missing '" . $IssuerCN . "'."); + :if ([ $CertificateDownload $IssuerCN ] = false) do={ :return false; } } From 0fee5cea3c6b14e0d612fb0ea28fa49967ce7e1a Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 13:35:05 +0100 Subject: [PATCH 06/31] check-certificates: move the warning below check for key --- check-certificates.rsc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/check-certificates.rsc b/check-certificates.rsc index 1dd61299..88f144a2 100644 --- a/check-certificates.rsc +++ b/check-certificates.rsc @@ -197,16 +197,16 @@ fingerprint!=[ :tostr ($CertVal->"fingerprint") ] expires-after>$CertRenewTime ]; :local CertNewVal [ /certificate/get $CertNew ]; - :if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") "fetch" ] = false) do={ - $LogPrint warning $ScriptName ("The certificate chain is not available!"); - } - :if (($CertVal->"private-key") = true && ($CertVal->"private-key") != ($CertNewVal->"private-key")) do={ /certificate/remove $CertNew; $LogPrint warning $ScriptName ("Old certificate '" . ($CertVal->"name") . "' has a private key, new certificate does not. Aborting renew."); :error false; } + :if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") "fetch" ] = false) do={ + $LogPrint warning $ScriptName ("The certificate chain is not available!"); + } + /ip/service/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ]; /ip/ipsec/identity/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ]; From 330a616406a2cf255236472f3b3ac8cc6d0ac02c Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 13:39:25 +0100 Subject: [PATCH 07/31] check-certificates: abort renew if "new" certificate is older... ... and drop the condition on $CertRenewTime. --- check-certificates.rsc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/check-certificates.rsc b/check-certificates.rsc index 88f144a2..9aa11c10 100644 --- a/check-certificates.rsc +++ b/check-certificates.rsc @@ -194,9 +194,15 @@ :local CertNew [ /certificate/find where name~("^" . [ $EscapeForRegEx [ $UrlEncode $FetchName ] ] . "\\.(p12|pem)_[0-9]+\$") \ (common-name=($CertVal->"common-name") or subject-alt-name~("(^|\\W)(DNS|IP):" . [ $EscapeForRegEx $LastName ] . "(\\W|\$)")) \ - fingerprint!=[ :tostr ($CertVal->"fingerprint") ] expires-after>$CertRenewTime ]; + fingerprint!=[ :tostr ($CertVal->"fingerprint") ] ]; :local CertNewVal [ /certificate/get $CertNew ]; + :if (($CertVal->"expires-after") > ($CertNewVal->"expires-after")) do={ + /certificate/remove $CertNew; + $LogPrint warning $ScriptName ("Old certificate is newer than the new one. Aborting renew."); + :error false; + } + :if (($CertVal->"private-key") = true && ($CertVal->"private-key") != ($CertNewVal->"private-key")) do={ /certificate/remove $CertNew; $LogPrint warning $ScriptName ("Old certificate '" . ($CertVal->"name") . "' has a private key, new certificate does not. Aborting renew."); From 0fffb5198eafe53a02c48a701ec7309244be5242 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 13:51:37 +0100 Subject: [PATCH 08/31] netwatch-dns: support multiple certificates Some services use certificates issued by differnt CA certificates, depending on geolocation. One example is dns.google, which may require either of 'GTS Root R1' or 'GTS Root R4'. /tool/netwatch/add comment="doh, dns, name=google-dns-ipv4, doh-cert=GTS Root R1:GTS Root R4" host=8.8.8.8 type=simple; --- netwatch-dns.rsc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/netwatch-dns.rsc b/netwatch-dns.rsc index 2edbdf8c..06a15f95 100644 --- a/netwatch-dns.rsc +++ b/netwatch-dns.rsc @@ -17,6 +17,7 @@ :local ScriptName [ :jobname ]; :global CertificateAvailable; + :global CharacterReplace; :global EitherOr; :global IsDNSResolving; :global LogPrint; @@ -103,10 +104,12 @@ } :foreach DohServer in=$DohServers do={ - :if ([ :len ($DohServer->"doh-cert") ] > 0) do={ - :if ([ $CertificateAvailable ($DohServer->"doh-cert") "fetch" ] = false || \ - [ $CertificateAvailable ($DohServer->"doh-cert") "dns" ] = false) do={ - $LogPrint warning $ScriptName ("Downloading certificate failed, trying without."); + :foreach DohCert in=[ :toarray [ $CharacterReplace ($DohServer->"doh-cert") ":" "," ] ] do={ + :if ([ :len $DohCert ] > 0) do={ + :if ([ $CertificateAvailable $DohCert "fetch" ] = false || \ + [ $CertificateAvailable $DohCert "dns" ] = false) do={ + $LogPrint warning $ScriptName ("Downloading certificate '" . $DohCert . "' failed, trying without."); + } } } From c0c1c5521eda80539bf26c99d212ab4fe8ba80af Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 14:01:57 +0100 Subject: [PATCH 09/31] doc/netwatch-dns: include examples for dns.quad9.net & dns.google --- doc/netwatch-dns.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/netwatch-dns.md b/doc/netwatch-dns.md index c81ca8c9..41eb7592 100644 --- a/doc/netwatch-dns.md +++ b/doc/netwatch-dns.md @@ -55,6 +55,10 @@ resolves to the same address. /ip/dns/static/add name="cloudflare-dns.com" address=1.1.1.1; /tool/netwatch/add comment="doh" host=1.1.1.1; + /ip dns static add name=dns.quad9.net address=9.9.9.9; + /tool/netwatch/add comment="doh" host=9.9.9.9; + /ip/dns/static/add name=dns.google address=8.8.8.8; + /tool/netwatch/add comment="doh" host=8.8.8.8; Be aware that you have to keep the ip address in sync with real world manually! From ad310e6573c554dca3df3e1fa7dea264d6555bb6 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 14:05:22 +0100 Subject: [PATCH 10/31] doc/netwatch-dns: always use the same order for examples --- doc/netwatch-dns.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/netwatch-dns.md b/doc/netwatch-dns.md index 41eb7592..286fe474 100644 --- a/doc/netwatch-dns.md +++ b/doc/netwatch-dns.md @@ -37,11 +37,11 @@ The DNS and DoH servers to be checked have to be added to netwatch with specific comment: /tool/netwatch/add comment="doh" host=1.1.1.1; - /tool/netwatch/add comment="dns" host=8.8.8.8; /tool/netwatch/add comment="doh, dns" host=9.9.9.9; + /tool/netwatch/add comment="dns" host=8.8.8.8; This will configure *cloudflare-dns* for DoH (`https://1.1.1.1/dnsquery`), and -*google-dns* and *quad-nine* for regular DNS (`8.8.8.8,9.9.9.9`) if up. +*quad-nine* and *google-dns* for regular DNS (`9.9.9.9,8.8.8.8`) if up. If *cloudflare-dns* is down the script will fall back to *quad-nine* for DoH. Giving a specific query url for DoH is possible: From 92759fcca51c20da39b2c44a90f84637d3d34748 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 14:07:44 +0100 Subject: [PATCH 11/31] doc/netwatch-dns: give hint on multiple certificates --- doc/netwatch-dns.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/netwatch-dns.md b/doc/netwatch-dns.md index 286fe474..73829974 100644 --- a/doc/netwatch-dns.md +++ b/doc/netwatch-dns.md @@ -64,11 +64,13 @@ Be aware that you have to keep the ip address in sync with real world manually! Importing a certificate automatically is possible. You may want to find the -[certificate name from browser](../CERTIFICATES.md). +[certificate name from browser](../CERTIFICATES.md). Sometimes a service +randomly switches the CA used to issue the certificate, or it just depends +geolocation - give several certificate delimited with colon (`:`) then. /tool/netwatch/add comment="doh, doh-cert=SSL.com Root Certification Authority ECC" host=1.1.1.1; /tool/netwatch/add comment="doh, doh-cert=DigiCert Global Root G3" host=9.9.9.9; - /tool/netwatch/add comment="doh, doh-cert=GTS Root R1" host=8.8.8.8; + /tool/netwatch/add comment="doh, doh-cert=GTS Root R1:GTS Root R4" host=8.8.8.8; > ⚠️ **Warning**: Combining these techniques can cause some confusion and > troubles! Chances are that a service uses different certificates based From b52936e94686b183122d04a5668b54cd3fc4f480 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 15:52:01 +0100 Subject: [PATCH 12/31] doc/netwatch-dns: mention ip address... ... which can be used for serveral services that have it in SAN. --- doc/netwatch-dns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/netwatch-dns.md b/doc/netwatch-dns.md index 73829974..75933645 100644 --- a/doc/netwatch-dns.md +++ b/doc/netwatch-dns.md @@ -74,7 +74,7 @@ geolocation - give several certificate delimited with colon (`:`) then. > ⚠️ **Warning**: Combining these techniques can cause some confusion and > troubles! Chances are that a service uses different certificates based -> on indicated server name. +> on indicated server name (or ip address). Sometimes using just one specific (possibly internal) DNS server may be desired, with fallback in case it fails. This is possible as well: From 6468c24d6199276676a9ec70dc1fa81fde7eb5c8 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Sat, 17 Jan 2026 16:55:22 +0100 Subject: [PATCH 13/31] update list of contributors --- CONTRIBUTIONS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTIONS.md b/CONTRIBUTIONS.md index c7e05b21..a1b9a22e 100644 --- a/CONTRIBUTIONS.md +++ b/CONTRIBUTIONS.md @@ -56,6 +56,7 @@ Add yourself to the list, * Peter Ponzel * Reiner Vehrenkamp * Richard Österreicher +* Ruben Navarro Huedo * Simon Hitzemann * Sunny Chu (@sunnychuchu) * Ulrich Wessendorf From aebe7bd054aea238b8b2e73eb01fb44f10f9404a Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 14:51:22 +0100 Subject: [PATCH 14/31] certs: add Let's Encrypt 'Root YE' for future use https://letsencrypt.org/2025/11/24/gen-y-hierarchy https://letsencrypt.org/certificates/#root-cas --- certs/Root-YE.pem | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 certs/Root-YE.pem diff --git a/certs/Root-YE.pem b/certs/Root-YE.pem new file mode 100644 index 00000000..855cece5 --- /dev/null +++ b/certs/Root-YE.pem @@ -0,0 +1,19 @@ +# Issuer: C=US, O=ISRG, CN=Root YE +# Subject: C=US, O=ISRG, CN=Root YE +# Label: "Root YE" +# Serial: A4026BA2EF6C7C20D4047E5E65A69380 +# MD5 Fingerprint: 93:61:B1:AC:E4:DC:A4:8B:C6:FF:A4:A2:2B:D4:64:64 +# SHA1 Fingerprint: A9:57:15:57:A7:7D:B7:8F:FA:C2:E9:7B:57:B8:98:56:90:39:C3:40 +# SHA256 Fingerprint: E1:4F:FC:AD:5B:00:25:73:10:06:CA:A4:3A:12:1A:22:D8:E9:70:0F:4F:B9:CF:85:2F:02:A7:08:AA:5D:56:66 +-----BEGIN CERTIFICATE----- +MIIB2TCCAWCgAwIBAgIRAKQCa6LvbHwg1AR+XmWmk4AwCgYIKoZIzj0EAwMwLjEL +MAkGA1UEBhMCVVMxDTALBgNVBAoTBElTUkcxEDAOBgNVBAMTB1Jvb3QgWUUwHhcN +MjUwOTAzMDAwMDAwWhcNNDUwOTAyMjM1OTU5WjAuMQswCQYDVQQGEwJVUzENMAsG +A1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZRTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABDwS/6vhrcVqcbBo+wgdI3fwn9x7DNJJOY/lTOti0vkwuRN87RhEhTH17E7X +yFjWsPYhIPt/wzOqxTd2b+4ZJNy9ID04YywF9U5zasDVyGSNErVNtz8uSGh5izW8 +7j77GaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFKPIJlqOoUzQNWP8myPIOq5W809WMAoGCCqGSM49BAMDA2cAMGQCMHhMr8N9 +LdL1VQKs9BdV81r76eXRB6mtjuNjzk6/lBsPNToWLTDzGYgtQKO1jl63uAIwGV7m +onyF377c+MM1oqVNs17sgu7F9YKZwgLmVbeOMDbKAXHtKMDLbiGllCcs8f47 +-----END CERTIFICATE----- From 244eceafee495d68648412d2c3c583668c802242 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 16 Jan 2026 12:51:43 +0100 Subject: [PATCH 15/31] certs: add Let's Encrypt 'Root YR' for future use https://letsencrypt.org/2025/11/24/gen-y-hierarchy https://letsencrypt.org/certificates/#root-cas --- certs/Root-YR.pem | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 certs/Root-YR.pem diff --git a/certs/Root-YR.pem b/certs/Root-YR.pem new file mode 100644 index 00000000..b4625f4e --- /dev/null +++ b/certs/Root-YR.pem @@ -0,0 +1,37 @@ +# Issuer: C=US, O=ISRG, CN=Root YR +# Subject: C=US, O=ISRG, CN=Root YR +# Label: "Root YR" +# Serial: EC46349360CF4B0FF8A982D93AA9CA3D +# MD5 Fingerprint: B7:C3:9E:B2:5C:FA:D6:0D:0B:F8:7F:A6:D8:A0:95:F7 +# SHA1 Fingerprint: C5:F1:11:DA:84:F7:DE:F8:E6:F3:F9:9F:8F:5F:36:FF:85:BA:B1:B1 +# SHA256 Fingerprint: E5:7B:7E:6F:15:0C:41:91:02:E8:D5:C0:55:72:9F:F9:67:B9:D1:A8:29:BF:00:CE:C8:9C:A6:04:EB:F4:A8:6F +-----BEGIN CERTIFICATE----- +MIIFKTCCAxGgAwIBAgIRAOxGNJNgz0sP+KmC2Tqpyj0wDQYJKoZIhvcNAQELBQAw +LjELMAkGA1UEBhMCVVMxDTALBgNVBAoTBElTUkcxEDAOBgNVBAMTB1Jvb3QgWVIw +HhcNMjUwOTAzMDAwMDAwWhcNNDUwOTAyMjM1OTU5WjAuMQswCQYDVQQGEwJVUzEN +MAsGA1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZUjCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANvGJnN78CTJdWL3+eGfsLN5TrNBJs+VH9hRXqRbwxu9 +sGNiB0BD1fcOxbSUQCJIM1xE13Db+5Cw1w0s0EBYsvuIP/6joF0w8cuImbgR1OGg +YbSQ4OpzI+DG8SGuTlcE873OCS+kh3srlo6vl43M5OJg4Aeo1sfHp6kTJDoIiFBN +JAY+OKfX/FUvYKuhjT+no49lmqmupSBI5PkBQiqrEGtWU5uxU/cQWHGu8jSjFBzn +ZqvbNPLMXMLFxCb3WTfrJBXXjqvWG+v4bjzxjjeAtOlU7qarRDvNOyAuQYLln904 +M+faKx8hnLCpJ15ZqaEgcNlY+9MMWcC5yvL2A2j3l9+2buggZX+dOE91zYmIdawT +vSZuVvlbRrAlLxIB6pwMBjneXCjYQ8+3BCCjssbSNpZU3hTcBDdhfAlEDlYr6pEa +tnMdmDT5BqnKC92bd0EhM1fbLHioLccLCuievT8ZkPhZrq7Mii7gNXAcUEAR8+lz +Yal+9zTg7C5DALyVOeG/CqfRAMn1KSHCR0NSA6P8tn/mGRlnCct5rtVCLnVySVpU +6H1qGg3DgTOuskf8eahTMiYbI5ezPJmO5ertalskQ1utp74+eDy92PI4ftHKTbq9 +IWhH4YZKh3WnJEIt+oQvlYZbY8tpEroKrFB6PFGzrJIDRyts4HqvuH52RFj2zv/B +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTe51tg0CJtQCh9Pw0B/qS1UrRRlDANBgkqhkiG9w0BAQsFAAOCAgEAWHnf +713Bdkq7t5yN2dNIgQakUb94X9WuyhMEHHkgx4oDpSUlnG0w4g94MoqaEUE31ZjR +LU7L5LD1g9ujFHTQu8AD215AHMVQFbm6j8hQxdXHAzDajFNQnOlDJrLjzIx176oy +AjvUtejZx2NNmdb5fd0WGVGsCdoAJ3N8ozo7ajE8t6vfxStZb4BQ9WYJGHUDrv2N +i5tJF6CNiPnlzs3BUfECRbE4JSk+jvy8+VoGiFE8qsH/j78x2fjgQhAQFV7P7Zxy +dBTZ1wEkNpZNW2qnaK1SKBLa+xf6E06YRIq5uaI+HWH8SY1y5VbRgzq40EKg3yxP +06fz+uYAUIFJoLNfhwRCc3Q6pQVuMX3yAjHAes4gk4moGcLQ5p7HAh39yeylZc1J +41sx/jKwLIkPE6Rr1Nf4pxdsxf9SA4yOEiAkDgq04DVxn8hgYFdUtBCuiuVC2heA +EiqVEa+8QZjuw8Gj0EbHXcRd1nInvGqRS1o9Is7YBdQN57X1AYveGBNNqjICSb7c +awuw1EawTDrs13VUlJVEsbQ0/O/1aaV73mCdOQ8azqL2KTv1Ewu1xbquE2S+kdQU +To9TUwat3wUA6cwXh1EfpS/3fJ0aGah5hdpRyoCLDlsSn8tkrjMfFFX0viC+GxHc +sI1ANRYvqSFC2X1VRZfDg+wD6E21BccmifG4yWc= +-----END CERTIFICATE----- From 68a4ac942e6f2521426359c717f101733c916d60 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 15:57:29 +0100 Subject: [PATCH 16/31] certs: update *.eworm.de for new Let's Encrypt 'Root YE' --- certs/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certs/Makefile b/certs/Makefile index 4114b3ff..2f6155b3 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -12,11 +12,11 @@ DOMAINS_DUAL = \ cloudflare-dns.com/SSL-com-Root-Certification-Authority-ECC \ dns.google/GTS-Root-R4 \ dns.quad9.net/DigiCert-Global-Root-G3 \ - git.eworm.de/ISRG-Root-X2 \ + git.eworm.de/Root-YE \ lists.blocklist.de/GTS-Root-R4 \ matrix.org/GTS-Root-R4 \ raw.githubusercontent.com/USERTrust-RSA-Certification-Authority \ - rsc.eworm.de/ISRG-Root-X2 \ + rsc.eworm.de/Root-YE \ upgrade.mikrotik.com/ISRG-Root-X1 DOMAINS_IPV4 = \ 1.1.1.1/SSL-com-Root-Certification-Authority-ECC \ From 9919b9fe7653bbcde0afb3e6b51b0e4ed89e4045 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 15:40:21 +0100 Subject: [PATCH 17/31] global-functions: $ScriptInstallUpdate: get new Let's Encrypt CA 'Root YE' --- global-functions.rsc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global-functions.rsc b/global-functions.rsc index 5d2a5044..fc60ff63 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -1265,7 +1265,7 @@ :global SymbolForNotification; :global ValidateSyntax; - :if ([ $CertificateAvailable "ISRG Root X2" "fetch" ] = false) do={ + :if ([ $CertificateAvailable "Root YE" "fetch" ] = false) do={ $LogPrint warning $0 ("Downloading certificate failed, trying without."); } From 6e8e841906411ac0b0d8910354688e2603dcd7c1 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 15:44:54 +0100 Subject: [PATCH 18/31] README: update for new Let's Encrypt CA 'Root YE' --- README.d/01-download-certs.avif | Bin 2761 -> 2671 bytes README.d/03-check-certs.avif | Bin 5079 -> 4970 bytes README.md | 12 ++++++------ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.d/01-download-certs.avif b/README.d/01-download-certs.avif index f2afeb545aa1e191f3e9382963bcdc172c40603e..e4d8755c85172346e4e3660279c66b6ad43df4aa 100644 GIT binary patch delta 2337 zcmV++3EuX}74H;~cmZ6Ic}oF?k;O?8WNl<&bP@mx1~?`1cvcBA&k~a$0cU^D{&0_W z{V!CWUXNHh-u^}J?CgQ%DYk$d;V1gdpvMgw(&sRr6=KY;D3V;?#;6CKT$;8lMP$TG z7KS zNZatTxu$Xq|D6I4EB%b$WS@UlJvZ!h9)JHrI)rSPrmHyimH_gmk^41jWmYLG{332f z|G7WY^1Nth#)&-3toHUAhq$H9_JXHWwnXq|gF)J#o49pG=Ve=tN&tCxl#S&z`j-No z$_dBc=O9`|5tG9e4@sxjL@(p|3CcQ^P zEc!|nr>Zb*EoHqW&DEJ*(9wwtv6r2;t|QHdGctE|7;!{B21pQH5y0EHM=67t*GGU- z+^I=`i5fv$D3y^lC%VIRhX2_cO&lWd@{r?kBO;9{&W$As>u*`fjdXhf7B zkYv6UFvMN^BPLN0&a^^_Eh^E@`(qfV9k}h7DKxQj0suSnd5(XBA2xmsG%vxz>SNVU zZW;n_elA|0!#4IZ*Z$Q-s&Tp+fB0cC*6q;)C)Ox@##u17`V)W9OZO1+*jz-KLsv7u zk~|@8&?Q?AyC@bJ$S#H_T*uh#Q#zrp*cY$|F4vgDt>~&1SIAI)e=0@_k_mQUDgVum z4EIj@_NMV;OfD=e|>E zY1UFN`x}3I_6tNHg=oIrInZ({MXs}VSiqLvKU`!%lKxvPVZQ>C1NYfwQ68QV|5`FX zqX^={l<8nwO4EtmEJrC^ZxuEkfMU@?yc9p7*vd8AMG^gr>W0>;$ zZT5;e!`o`&(~`0UF)ifU|Bbgm4(BCW3;40eI3|Bsk%u`OEFHa`V{!bw!W5Mhk;Zc zcK-pVb$^0#a@t-}CUjUZNcgmJ)C#et(E}FJ?7a@D1mk~a7TKe~#nC;CT%eYmp_p|>0HdnerY0?v z4#~s>Kej9oFzSU6yj&yHjy;_Llmj}WhZ0H?+V0cjG_T~&gg%cRy9X&FBCS_l#=QXF zuJmcWM-NH4a)AUgRa5wy9s155wXB_j(;maNrL_E=%cvG;+BW4ye)#xy0 zY^ELo^7Xl*U|ZdFnB=^aYhL`$*$K&(SxOO{*fvsaA*&@rC4+basmbADD)lXlGM!_C zU8bDc!U=UjPqhMej!%nbCZ=Cq1-rz)iO)pA1DBFsj*FZ`uF|yy8*zTtBU@0e>Pq#( z6Ma#px9d)LkG~Ij7qNSfo84Abdv1S-bkx!VpIv>2g?RIgr)u%Cq4EE=0BM~v*u2rB<|#g1juEW<)1C^s zx&BI2v&5w|R5-T~kDmHp2_y8S90dlU!u$e9;+Y^&;um7kr_BMOpIhkUIc$HOg5YC* z?n;G-qrnPkIJs|=V}`Nbk6zbaY1lHaOSzXX`j-SGHaktKVg;5t*(sA~=xf_$;$;?P znrNB0pi0ISFyxSGO3R28$cWu34B|K60;u{F_#06=j+d|fs#1vG1pI*ssR~T#e&N-!w!xzH)-SeLMHz4!fd3dk}ink~L|E9aMR# zQn3?ScH|5Yl>{-h_ZmEnZETI1pC9B9FcZJ0Aoq*J4-5ZpM0d`A{Z!*)ZDYW(Y`6ms ziQ`3MpjE`Q&L%64Apj{mi;wz$wZZP@P4Aq?lD1lKuG2-0AV_&Juuv|9I&Wc+E|u+t z=-C8BcDJ(OXr(Sn{AKYQ=EiCZcy|gX(6C~`xZ{>OEju-mB zs(N$RuBgh6vz#eBsd|Jbi)@GGW5}GEj-+5;5hVIW8?kEE{O7<`hof?a$4tixS#^8y Hl?|HG#Q=}6 delta 2428 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 delta 4815 zcmV;=5-{!RCf6sBcmc$bd6g2(ZDe6|5&#MYI3@CWRtYkyrBZtbArEC)UUwN5eFA1p&AI9!r3M{p4{QJXFbaq6t>De<{jC>B;r0TG{2{`u4{zI@~{jQo}o&_u*^- zfW=PBboc|d%Q4Luue8LPjU1W7Iw#in%gy+(X=8NcC9_kptG${d6Ol#mNo>z~r$$1E zcO|bAda2>)-U1z;d2`h&YGSp-#6jx)f|l|EF3rY0d-5dn_7J-(D3NTG^|wkYM$&S4)DAlZEN^0*eB$y1qZX)vrzUi(?2_~6Azd4 zhMjkGJnD73FY1kcaIEVu=TBPie=DQ&smC?<;er)2_I91Z3IE=CIeaH zJxfGhz;YzazS2c4a;ucJy8bV{DX^Y#ubhMoCzCmu683#sd1Oy~0UpwOH`GekpF*TQ z;6&*DQi&N7G$oI(nXa+QwsLVi!XlA++>b>w{L`zHh>G{XqA(oMdy8xrf1%sNeL<%8 zd%l3Pa|GJ^YT{?%^k=@p1rLmJ;CcE#@T8J@y%qw}l3n@n^8yQ5kQ-G!k;{1EQNJ9o zg61|@0w}-VgMePkv^o8kdVjA@(Sj%k)yXXb)iIn}@osT}GGbM}LdNl`X8-c8nWHVr znDTt<#%n0lU*g8cSHiFne@5H{D??(4Fr8B# zZYRx%eCj-bFpG;}Wcd>}5i*dY_>I$*251at7zNcV1Kf?R6P4sUT(>X`j}n)bCJ{!K z+$!6x_ISun_fP&46EiaiVU4zs&E)g9bt3)oeXP>W zUcqkD6gK-Tq8vwHbyAHZuvCRhpyjMg^|UVRpykKAoYF7AZExC0{9N9_)QX7xh~);-$P<)!}ZIUHH(!$89sj zS>b;kG;_RLRSZnKd$+@bRN6C@0>6(}M z7Z_CotPSCwenji!8P2z5Qe z_1>Kr#m!s^H(ky@rghW>`BQ8gVw7m@rdVZ#;`xCJ_>FYJl`dKM954!ui-TQx4paP= z^sf={$@uFPq`M6Ycjz1^*bA5d-~mKG`)anH*I3|fmo|o&`B>#&n<6G$!!WBL$;5tX z{2tJxe=P!rG_S}JU{-9Ar?E!ma|TIy6nS+5#TE0wg{v)3f1A(b zk;AaCyt=HE`+;U)uO13q%|m?7crMROdqIeb(d<22YCq ze`AkGW+HG*9^l2DU|JswCcFhEe+*OyIO+5sbZ*m_c^p52V$Tdd@I(q@*QkmA{M+z@ zL`8aWeGI7=0^UuL$LcUJ&_}8BCOfB?=a8-^^GWCiX7nK_RD+`Tqf!*m}4m$ZK*;7ZO>8b}se;n_Afb0xj z>j?{%7#iN&?pL94A~ne&L)Aqbn820 zq*`^tquOM*T+zY(qy*r@gSP~RoQi3t(y29Nn(>a~O%p6el3oS{l#HT711l@FP<0)W z5`!@QAepjsF72IoZ$7u(f1!TmT@H(8$AS@>#Zm%gT@pD~#i}gWIbU1;^bUC3A48dD zd(I8aB`wQ}Khi+iZvH1Ln-*tQVe?W2UPljA5P%?&I3@a)DqHh^hJ=}pw~W-$DJwf` z^rjbe;)ZSX!FGXdv~kTwhiV{o`&onD^jAMH9dRo{{XU!dCZ+E`f2?GlED5#rEsiC% z1D9VnXAX_~m0II1mqyVQg!OK1k|OVYODtASM47s#huEK5)nq|CsJ_K`GD_c{)ZAKg zw(EAb_^u)gJ-KQvzTcB&)~Moe2Eb6D3t!0+$+aP!Z-fEWw4E4oGTXOS3OnNYNvasI+b>?=WpdNzQgwl3`Q~^68=}hv@JO+=4xMnW; z)4UUe7X{5IAu7U~Zi?Ix9BeOfn`7dwiAve#9QbR?0F$R;(}d2e^R2zo~I06qr8V_dEpr> zDC8DAgLl;M5Y8?E!(v*|fuxCB?#gsXtGHZ$S;^bakcV>jM!l8a_LlB`fNscrrF~}C zzye~)9QHGs)?VjagHw207%q|4&n49dF7W1{vkXIRs}T~hr#mtqo-IfQ=%|)n!{jg1 zkxl124Mq{tW>O88={3{2HtQQFjq?6y)W2-;MY!i`re^0)t6NQ6Yowq@dY{Qe)_m=p$v`SUR ze$mVcDbV4Ld@pSS;3N4Tw8``XzO0O8fHG_msr7Wh#)y=G zsNaMBMA3sS@hDfZwlPDdoA;P=WDYCIWq6Qtknq~?)(CkWrJ2Qnk&X`N;$S!;@On!0 ze_(ZfX`QN-ds1_db;%u0aqD4ur4pMM-PA^t!)e|G#>7+waBTxRw9QD+#7u_?8>B(q z_6F!kRt-O)qJnT*69SC?pdE^aTj_#hdW1>wB2?D3(Q1-^{0~e2`jTc65i|V-uPYke z5+R->=PU_8?+Ns13)~$@(eOUTNKea4fB$n4;G6>_xDaxUBM`h8HrHq<>eLfPyFY_*WuMwNDim{$Ab~emNObdb5(vw(E%=B7cLPcSHLRC z1{q2z9``wbHK{+3{s6z}6xBE`DcKfoY(Khe-T(EeGBbmzz6w#ho)omhFZsHGe^Ag` zTNC3|k+rS%o()?>PnC;?1yC zB;)JHyNZIW^dnp=8wV+bOV2R2ynpZf4S|zhgPmAEj;@Yyz$VI)8kI4|{_-}Gl@>d| zbjTM4mhn7p%QTt*PcIq@6lct&f3;hakDy||Hv^$*tB6vQ=WSSU*&6Q(-68JrD-~L? z%CDKTuf+cp3tNXrl*P&CMXD0d>TPf6Njey>08Dc?BRX;pXA8}Q**p9zUZjDxmzRe| zyKGGkpSf<0doMUO`Y3hjI4*RQgwDxkDzL$ze^#9oxi4f4nxY8^zi; zl&Ae5HsQBd7x0XtSnJ_Bp5xnheP_9w=!yZz$wHcwZMy2un4_PdT;Bl!OX9PPQAWyh z<%XRtd1@4Hk`9ztv}mYHHkOzD zq@aCQZP^9}2o%Y+B#8O{tm0et>YRD=w%ska;em>zo7}wyi0zdWf6E>aU=fGyHh`q! z#n<$29340VX@LB4KC(MU9&NI{dQOp(3(CG|Ou=>t++dGU70usRBqW1Tk+4%0DH(qT zWML)56)kN{@ieO)#Y~{)m=3}FC@w~2kf>qfQGopad}#7~*XXwDj6_-I`8v^p)yHeY zXr`H+Z-CiDS=rzIf7hfTOgEH}ZyLX0@hEHgl0_TGt+B`QP1?*ul_$XKeWgsZ$Vz*A zLW0tMn)*YwNLaEs=oG2u0)yj+(N{CnWMb}+8qR|3jKV8hH=|N?jD^*v3bDJt|197t zPcRzfE2vv;%+k~B=q0YtDvU+B>Rpx+>4Nhib^~zxSq7hHe|CA$b30b|5QhpJk$*|} zfHe;au&a~9zW`HgJ#RQ4ACPOG5D%6X!7{sIu*u#a-%9&64a4UbgBm1`ppn!;QQCLp z92PYhD?Ez8ihtvG0>@YR$XF@#OW1bevq~C zejJw|SZQehf31G;(Ff7Kc*QoPOqg7Ck8hMP`eG?%!OTSiC8keUyltCmZSK*kX@4sD zz~=VHhhfQT(+us#Ge~f$NpUAXyp_DeV-Iy7Y2Ch*N;3I3s)|m>3gtodhXh?gy@nVD zd;n|!_NXbvq!ga Date: Thu, 15 Jan 2026 15:54:57 +0100 Subject: [PATCH 19/31] INITIAL-COMMANDS: update for new Let's Encrypt CA 'Root YE' --- INITIAL-COMMANDS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/INITIAL-COMMANDS.md b/INITIAL-COMMANDS.md index eb06ad29..c823826b 100644 --- a/INITIAL-COMMANDS.md +++ b/INITIAL-COMMANDS.md @@ -18,9 +18,9 @@ Run the complete base installation: { :local BaseUrl "https://rsc.eworm.de/main/"; - :local CertCommonName "ISRG Root X2"; - :local CertFileName "ISRG-Root-X2.pem"; - :local CertFingerprint "69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470"; + :local CertCommonName "Root YE"; + :local CertFileName "Root-YE.pem"; + :local CertFingerprint "e14ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666"; :local CertSettings [ /certificate/settings/get ]; :if (!((($CertSettings->"builtin-trust-anchors") = "trusted" || \ From 7716bb9d6c1830c010f5d14e58191ef2e459a624 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 16:05:33 +0100 Subject: [PATCH 20/31] fw-addr-lists: rsc.eworm.de requires 'Root YE' --- global-config.rsc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/global-config.rsc b/global-config.rsc index 9c35d13f..e55d9830 100644 --- a/global-config.rsc +++ b/global-config.rsc @@ -108,11 +108,11 @@ :global FwAddrLists { # "allow"={ # { url="https://rsc.eworm.de/main/fw-addr-lists.d/allow"; -# cert="ISRG Root X2"; timeout=1w }; +# cert="Root YE"; timeout=1w }; # }; "block"={ # { url="https://rsc.eworm.de/main/fw-addr-lists.d/block"; -# cert="ISRG Root X2" }; +# cert="Root YE" }; { url="https://raw.githubusercontent.com/stamparm/ipsum/refs/heads/master/levels/4.txt"; # # higher level (decrease the numerical value) for more addresses, and vice versa cert="USERTrust RSA Certification Authority" }; @@ -127,7 +127,7 @@ }; # "mikrotik"={ # { url="https://rsc.eworm.de/main/fw-addr-lists.d/mikrotik"; -# cert="ISRG Root X2"; timeout=1w }; +# cert="Root YE"; timeout=1w }; # }; }; :global FwAddrListTimeOut 1d; From a0f39c0a40256ccbd6a422623de0210ded77300e Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Sat, 7 Jun 2025 22:38:55 +0200 Subject: [PATCH 21/31] INITIAL-COMMANDS: drop the compatibility workaround... ... and make it depend in RouterOS 7.19 and its builtin certificates. --- INITIAL-COMMANDS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INITIAL-COMMANDS.md b/INITIAL-COMMANDS.md index c823826b..e033b576 100644 --- a/INITIAL-COMMANDS.md +++ b/INITIAL-COMMANDS.md @@ -4,7 +4,7 @@ Initial commands [![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.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/) +[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.19-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) @@ -26,7 +26,7 @@ Run the complete base installation: :if (!((($CertSettings->"builtin-trust-anchors") = "trusted" || \ ($CertSettings->"builtin-trust-store") ~ "fetch" || \ ($CertSettings->"builtin-trust-store") = "all") && \ - [[ :parse (":return [ :len [ /certificate/builtin/find where common-name=\"" . $CertCommonName . "\" ] ]") ]] > 0)) do={ + [ :len [ /certificate/builtin/find where common-name=$CertCommonName ] ] > 0)) do={ :put "Importing certificate..."; /tool/fetch ($BaseUrl . "certs/" . $CertFileName) dst-path=$CertFileName as-value; :delay 1s; From 749891216bc4b1e0dc6a0b19381f9d420b355877 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Sat, 7 Jun 2025 22:41:29 +0200 Subject: [PATCH 22/31] global-functions: $CertificateAvailable: drop the compatibility workaround... ... and make it depend in RouterOS 7.19 and its builtin certificates. --- README.md | 2 +- global-functions.rsc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6f7c03c8..5257b979 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ RouterOS Scripts [![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.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/) +[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.19-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) diff --git a/global-functions.rsc b/global-functions.rsc index fc60ff63..17c7bf49 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -4,7 +4,7 @@ # Michael Gisbers # https://rsc.eworm.de/COPYING.md # -# requires RouterOS, version=7.17 +# requires RouterOS, version=7.19 # requires device-mode, fetch, scheduler # # global functions @@ -131,7 +131,7 @@ :if ((($CertSettings->"builtin-trust-anchors") = "trusted" || \ ($CertSettings->"builtin-trust-store") ~ $UseFor || \ ($CertSettings->"builtin-trust-store") = "all") && \ - [[ :parse (":return [ :len [ /certificate/builtin/find where common-name=\"" . $CommonName . "\" ] ]") ]] > 0) do={ + [ :len [ /certificate/builtin/find where common-name=$CommonName ] ] > 0) do={ :return true; } From b1b9604e6b941388e5c33556fe2d6d34efa416f9 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Mon, 12 Jan 2026 09:22:46 +0100 Subject: [PATCH 23/31] check-certificates: drop the compatibility workaround... ... and make it depend in RouterOS 7.19 and its builtin certificates. --- check-certificates.rsc | 7 ++----- doc/check-certificates.md | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/check-certificates.rsc b/check-certificates.rsc index 9aa11c10..f54d3259 100644 --- a/check-certificates.rsc +++ b/check-certificates.rsc @@ -3,7 +3,7 @@ # Copyright (c) 2013-2026 Christian Hesse # https://rsc.eworm.de/COPYING.md # -# requires RouterOS, version=7.17 +# requires RouterOS, version=7.19 # requires device-mode, fetch # # check for certificate validity @@ -117,10 +117,7 @@ :local Return ""; :for I from=0 to=5 do={ :set Return ($Return . [ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN"); - :local CertSettings [ /certificate/settings/get ]; - :if (([ :len ($CertSettings->"builtin-trust-anchors") ] > 0 || \ - [ :len ($CertSettings->"builtin-trust-store") ] > 0) && \ - [[ :parse (":return [ :len [ /certificate/builtin/find where skid=\"" . ($CertVal->"akid") . "\" ] ]") ]] > 0) do={ + :if ([ :len [ /certificate/builtin/find where skid=($CertVal->"akid") ] ] > 0) do={ :return $Return; } :do { diff --git a/doc/check-certificates.md b/doc/check-certificates.md index 456d4b1f..1e69af46 100644 --- a/doc/check-certificates.md +++ b/doc/check-certificates.md @@ -4,7 +4,7 @@ Renew certificates and notify on expiration [![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.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/) +[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.19-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) From ccd669742e01901bab185799822d26095af402a1 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 13 Jan 2026 21:02:02 +0100 Subject: [PATCH 24/31] log-forward: use comparison for ids This was introduced with RouterOS 7.22beta1. Initializing $LogForwardLast with boolean value looks odd, but this is reuqired to match the very first message. --- doc/log-forward.md | 2 +- log-forward.rsc | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/doc/log-forward.md b/doc/log-forward.md index 25991fba..f51d61a5 100644 --- a/doc/log-forward.md +++ b/doc/log-forward.md @@ -4,7 +4,7 @@ Forward log messages via notification [![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.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/) +[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.22beta1-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) diff --git a/log-forward.rsc b/log-forward.rsc index ed2226f0..7a40a7a9 100644 --- a/log-forward.rsc +++ b/log-forward.rsc @@ -3,7 +3,7 @@ # Copyright (c) 2020-2026 Christian Hesse # https://rsc.eworm.de/COPYING.md # -# requires RouterOS, version=7.17 +# requires RouterOS, version=7.22beta1 # # forward log messages via notification # https://rsc.eworm.de/doc/log-forward.md @@ -24,7 +24,6 @@ :global LogForwardRateLimit; :global EitherOr; - :global HexToNum; :global IfThenElse; :global LogForwardFilterLogForwarding; :global LogPrint; @@ -38,6 +37,10 @@ :error false; } + :if ([ :typeof $LogForwardLast ] = "nothing") do={ + :set LogForwardLast false; + } + :if ([ :typeof $LogForwardRateLimit ] = "nothing") do={ :set LogForwardRateLimit 0; } @@ -51,7 +54,6 @@ :local Count 0; :local Duplicates false; - :local Last [ $IfThenElse ([ :len $LogForwardLast ] > 0) [ $HexToNum $LogForwardLast ] -1 ]; :local Messages ""; :local Warning false; :local MessageVal; @@ -63,19 +65,16 @@ :set LogForwardIncludeMessage [ $EitherOr $LogForwardIncludeMessage [] ]; :local LogAll [ /log/find ]; - :local MaxId ($LogAll->([ :len $LogAll ] - 1)); - :local MaxNum [ $HexToNum $MaxId ]; + :local Max ($LogAll->([ :len $LogAll ] - 1)); :local LogForwardFilterLogForwardingCached [ $EitherOr [ $LogForwardFilterLogForwarding ] ("\$^") ]; - :foreach Message in=[ /log/find where (!(message="") and \ - !(message~$LogForwardFilterLogForwardingCached) and \ - !(topics~$LogForwardFilter) and !(message~$LogForwardFilterMessage)) or \ - topics~$LogForwardInclude or message~$LogForwardIncludeMessage ] do={ + :foreach Message in=[ /log/find where .id>$LogForwardLast and .id<=$Max and \ + ((!(message="") and !(message~$LogForwardFilterLogForwardingCached) and \ + !(topics~$LogForwardFilter) and !(message~$LogForwardFilterMessage)) or \ + topics~$LogForwardInclude or message~$LogForwardIncludeMessage) ] do={ :set MessageVal [ /log/get $Message ]; :local Bullet "information"; - :local Current [ $HexToNum ($MessageVal->".id") ]; - :if ($Last < $Current && $Current <= $MaxNum) do={ :local DupCount ($MessageDups->($MessageVal->"message")); :if ($MessageVal->"topics" ~ "(warning)") do={ :set Warning true; @@ -93,7 +92,6 @@ } :set ($MessageDups->($MessageVal->"message")) ($DupCount + 1); :set Count ($Count + 1); - } } :if ($Count > 0) do={ @@ -111,7 +109,7 @@ :set LogForwardRateLimit [ $MAX 0 ($LogForwardRateLimit - 1) ]; } - :set LogForwardLast $MaxId; + :set LogForwardLast $Max; } do={ :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; } From b99cc053e1dcdf69279c4d9af3421082d1bcd757 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 13 Jan 2026 21:26:11 +0100 Subject: [PATCH 25/31] log-forward: fix indention --- log-forward.rsc | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/log-forward.rsc b/log-forward.rsc index 7a40a7a9..e89fdc18 100644 --- a/log-forward.rsc +++ b/log-forward.rsc @@ -75,23 +75,23 @@ :set MessageVal [ /log/get $Message ]; :local Bullet "information"; - :local DupCount ($MessageDups->($MessageVal->"message")); - :if ($MessageVal->"topics" ~ "(warning)") do={ - :set Warning true; - :set Bullet "large-orange-circle"; - } - :if ($MessageVal->"topics" ~ "(emergency|alert|critical|error)") do={ - :set Warning true; - :set Bullet "large-red-circle"; - } - :if ($DupCount < 3) do={ - :set Messages ($Messages . "\n" . [ $SymbolForNotification $Bullet ] . \ - $MessageVal->"time" . " " . [ :tostr ($MessageVal->"topics") ] . " " . $MessageVal->"message"); - } else={ - :set Duplicates true; - } - :set ($MessageDups->($MessageVal->"message")) ($DupCount + 1); - :set Count ($Count + 1); + :local DupCount ($MessageDups->($MessageVal->"message")); + :if ($MessageVal->"topics" ~ "(warning)") do={ + :set Warning true; + :set Bullet "large-orange-circle"; + } + :if ($MessageVal->"topics" ~ "(emergency|alert|critical|error)") do={ + :set Warning true; + :set Bullet "large-red-circle"; + } + :if ($DupCount < 3) do={ + :set Messages ($Messages . "\n" . [ $SymbolForNotification $Bullet ] . \ + $MessageVal->"time" . " " . [ :tostr ($MessageVal->"topics") ] . " " . $MessageVal->"message"); + } else={ + :set Duplicates true; + } + :set ($MessageDups->($MessageVal->"message")) ($DupCount + 1); + :set Count ($Count + 1); } :if ($Count > 0) do={ From 24cc13ecbbfafd369c4b7811d9f4f048b3563202 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 13 Jan 2026 21:33:26 +0100 Subject: [PATCH 26/31] global-functions: drop $HexToNum --- global-functions.rsc | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/global-functions.rsc b/global-functions.rsc index 17c7bf49..2aad406e 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -47,7 +47,6 @@ :global GetRandom20CharHex; :global GetRandomNumber; :global Grep; -:global HexToNum; :global HumanReadableNum; :global IfThenElse; :global IsDefaultRouteReachable; @@ -717,19 +716,6 @@ :return []; } -# convert from hex (string) to num -:set HexToNum do={ - :local Input [ :tostr $1 ]; - - :global HexToNum; - - :if ([ :pick $Input 0 ] = "*") do={ - :return [ $HexToNum [ :pick $Input 1 [ :len $Input ] ] ]; - } - - :return [ :tonum ("0x" . $Input) ]; -} - # return human readable number :set HumanReadableNum do={ :local Input [ :tonum $1 ]; From 6acdcb600e570f376e2ec044ff3d5fb2206b4c4d Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 09:25:48 +0100 Subject: [PATCH 27/31] netwatch-dns: early exit with :exit --- netwatch-dns.rsc | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/netwatch-dns.rsc b/netwatch-dns.rsc index 06a15f95..7af659e6 100644 --- a/netwatch-dns.rsc +++ b/netwatch-dns.rsc @@ -3,13 +3,12 @@ # Copyright (c) 2022-2026 Christian Hesse # https://rsc.eworm.de/COPYING.md # -# requires RouterOS, version=7.17 +# requires RouterOS, version=7.22beta1 # requires device-mode, fetch # # monitor and manage dns/doh with netwatch # https://rsc.eworm.de/doc/netwatch-dns.md -:local ExitOK false; :onerror Err { :global GlobalConfigReady; :global GlobalFunctionsReady; :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ @@ -26,15 +25,13 @@ :global ScriptLock; :if ([ $ScriptLock $ScriptName ] = false) do={ - :set ExitOK true; - :error false; + :exit; } :local SettleTime (5m30s - [ /system/resource/get uptime ]); :if ($SettleTime > 0s) do={ $LogPrint info $ScriptName ("System just booted, giving netwatch " . $SettleTime . " to settle."); - :set ExitOK true; - :error true; + :exit; } :local DnsServers ({}); @@ -89,8 +86,7 @@ :if ($DohCurrent = $HostInfo->"doh-url" && [ $IsDNSResolving ] = true) do={ $LogPrint debug $ScriptName ("Current DoH server is still up and resolving: " . $DohCurrent); - :set ExitOK true; - :error true; + :exit; } :set ($DohServers->[ :len $DohServers ]) $HostInfo; @@ -135,8 +131,7 @@ } /ip/dns/cache/flush; $LogPrint info $ScriptName ("Setting DoH server: " . ($DohServer->"doh-url")); - :set ExitOK true; - :error true; + :exit; } else={ $LogPrint warning $ScriptName ("Received unexpected response from DoH server: " . \ ($DohServer->"doh-url")); @@ -144,5 +139,5 @@ } } } do={ - :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; + :global ExitError; $ExitError true [ :jobname ] $Err; } From 332c2867c69fb7fc6332a1eeca130fe7eb3b01bf Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 09:34:40 +0100 Subject: [PATCH 28/31] telegram-chat: early exit with :exit --- telegram-chat.rsc | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/telegram-chat.rsc b/telegram-chat.rsc index 53ab6c66..a38e63f9 100644 --- a/telegram-chat.rsc +++ b/telegram-chat.rsc @@ -3,13 +3,12 @@ # Copyright (c) 2023-2026 Christian Hesse # https://rsc.eworm.de/COPYING.md # -# requires RouterOS, version=7.17 +# requires RouterOS, version=7.22beta1 # requires device-mode, fetch # # use Telegram to chat with your Router and send commands # https://rsc.eworm.de/doc/telegram-chat.md -:local ExitOK false; :onerror Err { :global GlobalConfigReady; :global GlobalFunctionsReady; :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ @@ -48,8 +47,7 @@ :global WaitFullyConnected; :if ([ $ScriptLock $ScriptName ] = false) do={ - :set ExitOK true; - :error false; + :exit; } $WaitFullyConnected; @@ -63,8 +61,7 @@ :if ([ $CertificateAvailable "Go Daddy Root Certificate Authority - G2" "fetch" ] = false) do={ $LogPrint warning $ScriptName ("Downloading required certificate failed."); - :set ExitOK true; - :error false; + :exit; } $RandomDelay $TelegramRandomDelay; @@ -89,8 +86,7 @@ :if ($Data = false) do={ $LogPrint warning $ScriptName ("Failed getting updates."); - :set ExitOK true; - :error false; + :exit; } :local JSON [ :deserialize from=json value=$Data ]; @@ -146,8 +142,7 @@ :local File ("tmpfs/telegram-chat/" . [ $GetRandom20CharAlNum 6 ]); :if ([ $MkDir "tmpfs/telegram-chat" ] = false) do={ $LogPrint error $ScriptName ("Failed creating directory!"); - :set ExitOK true; - :error false; + :exit; } $LogPrint info $ScriptName ("Running command from update " . $UpdateID . ": " . $Command); :execute script=(":do {\n" . $Command . "\n} on-error={ /file/add name=\"" . $File . ".failed\" };" . \ @@ -197,5 +192,5 @@ :set TelegramChatOffset ([ :pick $TelegramChatOffset 1 3 ], \ [ $IfThenElse ($UpdateID >= $TelegramChatOffset->2) ($UpdateID + 1) ($TelegramChatOffset->2) ]); } do={ - :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; + :global ExitError; $ExitError true [ :jobname ] $Err; } From 003b5f4506545db3c7c49da02a49ebf6bb12a66e Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 09:28:38 +0100 Subject: [PATCH 29/31] telegram-chat: use :continue in loop --- telegram-chat.rsc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/telegram-chat.rsc b/telegram-chat.rsc index a38e63f9..5b15227e 100644 --- a/telegram-chat.rsc +++ b/telegram-chat.rsc @@ -115,7 +115,6 @@ } :if ($Trusted = true) do={ - :local Done false; :if ($Command = "?") do={ $LogPrint info $ScriptName ("Sending notice for update " . $UpdateID . "."); $SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=true; \ @@ -123,9 +122,9 @@ subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \ message=([ $IfThenElse ([ :len ($From->"first_name") ] > 0) ("Hello " . ($From->"first_name") . "!\n\n") ] . \ "Online" . [ $IfThenElse $TelegramChatActive " (and active!)" ] . ", awaiting your commands!") }); - :set Done true; + :continue; } - :if ($Done = false && [ :pick $Command 0 1 ] = "!") do={ + :if ([ :pick $Command 0 1 ] = "!") do={ :if ($Command ~ ("^! *(" . [ $EscapeForRegEx $Identity ] . "|@" . $TelegramChatGroups . ")\$")) do={ :set TelegramChatActive true; } else={ @@ -133,9 +132,9 @@ } $LogPrint info $ScriptName ("Now " . [ $IfThenElse $TelegramChatActive "active" "passive" ] . \ " from update " . $UpdateID . "!"); - :set Done true; + :continue; } - :if ($Done = false && ($IsMyReply = 1 || ($IsAnyReply = false && \ + :if (($IsMyReply = 1 || ($IsAnyReply = false && \ $TelegramChatActive = true)) && [ :len $Command ] > 0) do={ :if ([ $ValidateSyntax $Command ] = true) do={ :local State ""; From 5ed36f5a5399f46c9184996aa11a77279828b0b3 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 10:29:17 +0100 Subject: [PATCH 30/31] mod/ssh-keys-import: drop old property The property name changed in RouterOS 7.21beta2, so bump required version to 7.21. --- mod/ssh-keys-import.rsc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mod/ssh-keys-import.rsc b/mod/ssh-keys-import.rsc index 16a02859..f858a545 100644 --- a/mod/ssh-keys-import.rsc +++ b/mod/ssh-keys-import.rsc @@ -3,7 +3,7 @@ # Copyright (c) 2020-2026 Christian Hesse # https://rsc.eworm.de/COPYING.md # -# requires RouterOS, version=7.17 +# requires RouterOS, version=7.21 # # import ssh keys for public key authentication # https://rsc.eworm.de/doc/mod/ssh-keys-import.md @@ -40,9 +40,8 @@ :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex ($KeyVal->1) ]; - :local RegEx ("\\bmd5=" . $FingerPrintMD5 . "\\b"); :if ([ :len [ /user/ssh-keys/find where user=$User \ - (key-owner~$RegEx or info~$RegEx) ] ] > 0) do={ + info~("\\bmd5=" . $FingerPrintMD5 . "\\b") ] ] > 0) do={ $LogPrint warning $0 ("The ssh public key (MD5:" . $FingerPrintMD5 . \ ") is already available for user '" . $User . "'."); :return false; From eb9960eaa9ac52f11f84bffbc30b514d362c9d11 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Thu, 15 Jan 2026 10:32:21 +0100 Subject: [PATCH 31/31] doc/mod/ssh-keys-import: update for RouterOS 7.21 --- doc/mod/ssh-keys-import.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/mod/ssh-keys-import.md b/doc/mod/ssh-keys-import.md index 434caa51..c6530ec2 100644 --- a/doc/mod/ssh-keys-import.md +++ b/doc/mod/ssh-keys-import.md @@ -4,7 +4,7 @@ Import ssh keys for public key authentication [![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.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/) +[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.21-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) @@ -38,9 +38,8 @@ import that key: $SSHKeysImport "ssh-rsa AAAAB3Nza...QYZk8= user" admin; The third part of the key (`user` in this example) is inherited as -`info` in RouterOS (or `key-owner` with RouterOS 7.20.x and before). Also -the `MD5` fingerprint is recorded, this helps to audit and verify the -available keys. +`info` in RouterOS. Also the `MD5` fingerprint is recorded, this helps +to audit and verify the available keys. > ℹ️️ **Info**: Use `ssh-keygen` to show a fingerprint of an existing public > key file: `ssh-keygen -l -E md5 -f ~/.ssh/id_ed25519.pub`