netwatch-dns: check DoH server with fetch

This way we do not have to configure possibly non-functional servers to
check. The query is for doh-check.eworm.de of type TXT, the expected
answer is 'doh-check-OK'.

% dig TXT doh-check.eworm.de +https @1.1.1.1

; <<>> DiG 9.18.21 <<>> TXT doh-check.eworm.de +https @1.1.1.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42226
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;doh-check.eworm.de.		IN	TXT

;; ANSWER SECTION:
doh-check.eworm.de.	63791	IN	TXT	"doh-check-OK"

;; Query time: 16 msec
;; SERVER: 1.1.1.1#443(1.1.1.1) (HTTPS)
;; WHEN: Mon Jan 15 13:55:36 CET 2024
;; MSG SIZE  rcvd: 72
This commit is contained in:
Christian Hesse 2024-01-14 22:36:21 +01:00
parent 85aeeadcee
commit 5fd8c8a760

View file

@ -12,7 +12,6 @@
:global CertificateAvailable;
:global EitherOr;
:global IsDNSResolving;
:global LogPrintExit2;
:global ParseKeyValueStore;
:global ScriptLock;
@ -58,7 +57,6 @@ $ScriptLock $0;
}
}
:local DohCertVerify [ /ip/dns/get verify-doh-cert ];
:local DohCurrent [ /ip/dns/get use-doh-server ];
:local DohServers ({});
@ -77,34 +75,46 @@ $ScriptLock $0;
}
:if ($DohCurrent = $HostInfo->"doh-url") do={
$LogPrintExit2 debug $0 ("Current DoH server is still up.") true;
$LogPrintExit2 debug $0 ("Current DoH server is still up: " . $DohCurrent) true;
}
:set ($DohServers->[ :len $DohServers ]) $HostInfo;
}
}
:if ([ :len $DohCurrent ] > 0 && [ :len $DohServers ] = 0) do={
$LogPrintExit2 info $0 ("DoH server (" . $DohCurrent . ") is down, disabling.") false;
:if ([ :len $DohCurrent ] > 0) do={
$LogPrintExit2 info $0 ("Current DoH server is down, disabling: " . $DohCurrent) false;
/ip/dns/set use-doh-server="";
/ip/dns/cache/flush;
}
:foreach DohServer in=$DohServers do={
$LogPrintExit2 info $0 ("Updating DoH server: " . ($DohServer->"doh-url")) false;
:if ([ :len ($DohServer->"doh-cert") ] > 0) do={
:set DohCertVerify true;
/ip/dns/set use-doh-server="";
:if ([ $CertificateAvailable ($DohServer->"doh-cert") ] = false) do={
$LogPrintExit2 warning $0 ("Downloading certificate failed, trying without.") false;
}
}
/ip/dns/set use-doh-server=($DohServer->"doh-url") verify-doh-cert=$DohCertVerify;
/ip/dns/cache/flush;
:if ([ $IsDNSResolving ] = true) do={
$LogPrintExit2 debug $0 ("DoH server is functional.") true;
} else={
/ip/dns/set use-doh-server="";
$LogPrintExit2 warning $0 ("DoH server not functional, trying next.") false;
:local Data false;
:do {
:set Data ([ /tool/fetch check-certificate=yes-without-crl output=user \
http-header-field=({ "accept: application/dns-message" }) \
url=(($DohServer->"doh-url") . "?dns=" . [ :convert to=base64 ([ :rndstr length=2 ] . \
"\01\00" . "\00\01" . "\00\00" . "\00\00" . "\00\00" . "\09doh-check\05eworm\02de\00" . \
"\00\10" . "\00\01") ]) as-value ]->"data");
} on-error={
$LogPrintExit2 warning $0 ("Request to DoH server failed (network or certificate issue): " . \
($DohServer->"doh-url")) false;
}
:if ($Data != false) do={
:if ([ :typeof [ :find $Data "doh-check-OK" ] ] = "num") do={
/ip/dns/set use-doh-server=($DohServer->"doh-url") verify-doh-cert=yes;
/ip/dns/cache/flush;
$LogPrintExit2 info $0 ("Setting DoH server: " . ($DohServer->"doh-url")) true;
} else={
$LogPrintExit2 warning $0 ("Received unexpected response from DoH server: " . \
($DohServer->"doh-url")) false;
}
}
}