Merge branch 'certificates' into next

This commit is contained in:
Christian Hesse 2026-01-17 16:57:34 +01:00
commit fd4bf59bae
7 changed files with 61 additions and 23 deletions

View file

@ -9,17 +9,17 @@ CURL = curl \
DOMAINS_DUAL = \ DOMAINS_DUAL = \
api.macvendors.com/GTS-Root-R4 \ api.macvendors.com/GTS-Root-R4 \
api.telegram.org/Go-Daddy-Root-Certificate-Authority-G2 \ 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.google/GTS-Root-R4 \
dns.quad9.net/DigiCert-Global-Root-G3 \ dns.quad9.net/DigiCert-Global-Root-G3 \
git.eworm.de/ISRG-Root-X2 \ git.eworm.de/ISRG-Root-X2 \
lists.blocklist.de/Certum-Trusted-Network-CA \ lists.blocklist.de/GTS-Root-R4 \
matrix.org/GTS-Root-R4 \ matrix.org/GTS-Root-R4 \
raw.githubusercontent.com/USERTrust-RSA-Certification-Authority \ raw.githubusercontent.com/USERTrust-RSA-Certification-Authority \
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 = \
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 \ 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 \
@ -27,10 +27,10 @@ DOMAINS_IPV4 = \
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 \
www.dshield.org/ISRG-Root-X1 \ www.dshield.org/GTS-Root-R4 \
www.spamhaus.org/GTS-Root-R4 www.spamhaus.org/GTS-Root-R4
DOMAINS_IPV6 = \ 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 \ [2001\:4860\:4860\:\:8888]/GTS-Root-R1 \
[2620\:fe\:\:9]/DigiCert-Global-Root-G3 \ [2620\:fe\:\:9]/DigiCert-Global-Root-G3 \
ipv6.showipv6.de/ISRG-Root-X1 ipv6.showipv6.de/ISRG-Root-X1

View file

@ -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-----

View file

@ -194,11 +194,13 @@
:local CertNew [ /certificate/find where name~("^" . [ $EscapeForRegEx [ $UrlEncode $FetchName ] ] . "\\.(p12|pem)_[0-9]+\$") \ :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|\$)")) \ (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 ]; :local CertNewVal [ /certificate/get $CertNew ];
:if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") "fetch" ] = false) do={ :if (($CertVal->"expires-after") > ($CertNewVal->"expires-after")) do={
$LogPrint warning $ScriptName ("The certificate chain is not available!"); /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={ :if (($CertVal->"private-key") = true && ($CertVal->"private-key") != ($CertNewVal->"private-key")) do={
@ -207,6 +209,10 @@
:error false; :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/service/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ];
/ip/ipsec/identity/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ]; /ip/ipsec/identity/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ];

View file

@ -37,11 +37,11 @@ The DNS and DoH servers to be checked have to be added to netwatch with
specific comment: specific comment:
/tool/netwatch/add comment="doh" host=1.1.1.1; /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="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 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. If *cloudflare-dns* is down the script will fall back to *quad-nine* for DoH.
Giving a specific query url for DoH is possible: 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; /ip/dns/static/add name="cloudflare-dns.com" address=1.1.1.1;
/tool/netwatch/add comment="doh" host=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 Be aware that you have to keep the ip address in sync with real world
manually! manually!
Importing a certificate automatically is possible. You may want to find the 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=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 > ⚠️ **Warning**: Combining these techniques can cause some confusion and
> troubles! Chances are that a service uses different certificates based > 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 Sometimes using just one specific (possibly internal) DNS server may be
desired, with fallback in case it fails. This is possible as well: desired, with fallback in case it fails. This is possible as well:

View file

@ -117,9 +117,9 @@
# # higher level (decrease the numerical value) for more addresses, and vice versa # # higher level (decrease the numerical value) for more addresses, and vice versa
cert="USERTrust RSA Certification Authority" }; cert="USERTrust RSA Certification Authority" };
{ url="https://www.dshield.org/block.txt"; cidr="/24"; { 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"; { 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"; # { url="https://www.spamhaus.org/drop/drop_v4.json";
# cert="GTS Root R4" }; # cert="GTS Root R4" };
# { url="https://www.spamhaus.org/drop/drop_v6.json"; # { url="https://www.spamhaus.org/drop/drop_v6.json";

View file

@ -150,9 +150,9 @@
:local CertVal [ /certificate/get [ find where common-name=$CommonName ] ]; :local CertVal [ /certificate/get [ find where common-name=$CommonName ] ];
:while (($CertVal->"akid") != "" && ($CertVal->"akid") != ($CertVal->"skid")) do={ :while (($CertVal->"akid") != "" && ($CertVal->"akid") != ($CertVal->"skid")) do={
:if ([ :len [ /certificate/find where skid=($CertVal->"akid") ] ] = 0) do={ :if ([ :len [ /certificate/find where skid=($CertVal->"akid") ] ] = 0) do={
$LogPrint info $0 ("Certificate chain for '" . $CommonName . \ :local IssuerCN ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN");
"' is incomplete, missing '" . ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") . "'."); $LogPrint info $0 ("Certificate chain for '" . $CommonName . "' is incomplete, missing '" . $IssuerCN . "'.");
:if ([ $CertificateDownload $CommonName ] = false) do={ :if ([ $CertificateDownload $IssuerCN ] = false) do={
:return false; :return false;
} }
} }

View file

@ -17,6 +17,7 @@
:local ScriptName [ :jobname ]; :local ScriptName [ :jobname ];
:global CertificateAvailable; :global CertificateAvailable;
:global CharacterReplace;
:global EitherOr; :global EitherOr;
:global IsDNSResolving; :global IsDNSResolving;
:global LogPrint; :global LogPrint;
@ -103,10 +104,12 @@
} }
:foreach DohServer in=$DohServers do={ :foreach DohServer in=$DohServers do={
:if ([ :len ($DohServer->"doh-cert") ] > 0) do={ :foreach DohCert in=[ :toarray [ $CharacterReplace ($DohServer->"doh-cert") ":" "," ] ] do={
:if ([ $CertificateAvailable ($DohServer->"doh-cert") "fetch" ] = false || \ :if ([ :len $DohCert ] > 0) do={
[ $CertificateAvailable ($DohServer->"doh-cert") "dns" ] = false) do={ :if ([ $CertificateAvailable $DohCert "fetch" ] = false || \
$LogPrint warning $ScriptName ("Downloading certificate failed, trying without."); [ $CertificateAvailable $DohCert "dns" ] = false) do={
$LogPrint warning $ScriptName ("Downloading certificate '" . $DohCert . "' failed, trying without.");
}
} }
} }