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 diff --git a/INITIAL-COMMANDS.md b/INITIAL-COMMANDS.md index eb06ad29..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) @@ -18,15 +18,15 @@ 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" || \ ($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; diff --git a/README.d/01-download-certs.avif b/README.d/01-download-certs.avif index f2afeb54..e4d8755c 100644 Binary files a/README.d/01-download-certs.avif and b/README.d/01-download-certs.avif differ diff --git a/README.d/03-check-certs.avif b/README.d/03-check-certs.avif index 1f03ad2c..6610ac47 100644 Binary files a/README.d/03-check-certs.avif and b/README.d/03-check-certs.avif differ diff --git a/README.md b/README.md index f9149217..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) @@ -112,7 +112,7 @@ If you intend to download the scripts from a different location (for example from github.com) install the corresponding certificate chain. - /tool/fetch "https://rsc.eworm.de/main/certs/ISRG-Root-X2.pem" dst-path="isrg-root-x2.pem"; + /tool/fetch "https://rsc.eworm.de/main/certs/Root-YE.pem" dst-path="root-ye.pem"; ![screenshot: download certs](README.d/01-download-certs.avif) @@ -120,11 +120,11 @@ Note that the commands above do *not* verify server certificate, so if you want to be safe download with your workstations's browser and transfer the file to your MikroTik device. -* [ISRG Root X2 ↗️](https://letsencrypt.org/certs/isrg-root-x2.pem) +* Let's Encrypt [Root YE ↗️](https://letsencrypt.org/certs/gen-y/root-ye.pem) Then we import the certificate. - /certificate/import file-name="isrg-root-x2.pem" passphrase=""; + /certificate/import file-name="root-ye.pem" passphrase=""; Do not worry that the command is not shown - that happens because it contains a sensitive property, the passphrase. @@ -132,11 +132,11 @@ a sensitive property, the passphrase. ![screenshot: import certs](README.d/02-import-certs.avif) For basic verification we rename the certificate and print it by -fingerprint. Make sure exactly this one certificate ("*ISRG-Root-X2*") +fingerprint. Make sure exactly this one certificate ("*Root-YE*") is shown. - /certificate/set name="ISRG-Root-X2" [ find where common-name="ISRG Root X2" ]; - /certificate/print proplist=name,fingerprint where fingerprint="69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470"; + /certificate/set name="Root-YE" [ find where common-name="Root YE" ]; + /certificate/print proplist=name,fingerprint where fingerprint="e14ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666"; ![screenshot: check certs](README.d/03-check-certs.avif) diff --git a/certs/Makefile b/certs/Makefile index 3ccad6e2..2f6155b3 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -9,17 +9,17 @@ 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 \ - lists.blocklist.de/Certum-Trusted-Network-CA \ + 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/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 \ @@ -27,10 +27,10 @@ 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 \ + [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/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----- 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----- 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----- diff --git a/check-certificates.rsc b/check-certificates.rsc index 1dd61299..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 { @@ -194,11 +191,13 @@ :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 ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") "fetch" ] = false) do={ - $LogPrint warning $ScriptName ("The certificate chain is not available!"); + :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={ @@ -207,6 +206,10 @@ :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") ]; 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) 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/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` diff --git a/doc/netwatch-dns.md b/doc/netwatch-dns.md index 23190b12..75933645 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: @@ -55,20 +55,26 @@ 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! 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=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; + /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 -> 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: diff --git a/global-config.rsc b/global-config.rsc index 25254123..e55d9830 100644 --- a/global-config.rsc +++ b/global-config.rsc @@ -108,18 +108,18 @@ :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" }; { 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="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"; @@ -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; diff --git a/global-functions.rsc b/global-functions.rsc index 5c70a463..2aad406e 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 @@ -47,7 +47,6 @@ :global GetRandom20CharHex; :global GetRandomNumber; :global Grep; -:global HexToNum; :global HumanReadableNum; :global IfThenElse; :global IsDefaultRouteReachable; @@ -131,7 +130,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; } @@ -150,9 +149,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; } } @@ -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 ]; @@ -1265,7 +1251,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."); } diff --git a/log-forward.rsc b/log-forward.rsc index ed2226f0..e89fdc18 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,37 +65,33 @@ :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; - :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={ @@ -111,7 +109,7 @@ :set LogForwardRateLimit [ $MAX 0 ($LogForwardRateLimit - 1) ]; } - :set LogForwardLast $MaxId; + :set LogForwardLast $Max; } do={ :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; } 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; diff --git a/netwatch-dns.rsc b/netwatch-dns.rsc index 2edbdf8c..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) \ @@ -17,6 +16,7 @@ :local ScriptName [ :jobname ]; :global CertificateAvailable; + :global CharacterReplace; :global EitherOr; :global IsDNSResolving; :global LogPrint; @@ -25,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 ({}); @@ -88,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; @@ -103,10 +100,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."); + } } } @@ -132,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")); @@ -141,5 +139,5 @@ } } } do={ - :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; + :global ExitError; $ExitError true [ :jobname ] $Err; } diff --git a/telegram-chat.rsc b/telegram-chat.rsc index 53ab6c66..5b15227e 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 ]; @@ -119,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; \ @@ -127,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={ @@ -137,17 +132,16 @@ } $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 ""; :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 +191,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; }