Skip to content

Verification

Mikhail Deynekin edited this page Nov 1, 2026 · 6 revisions

Verification

Commands with the expected output, then the measured results.

Per-subsystem

/certificate print where trusted=yes
#   expect: "SSL.com TLS ECC Root CA 2022", trusted=yes

/ip dns print
#   expect (0.2.0 defaults): servers=1.1.1.1,1.0.0.1;
#           use-doh-server=https://cloudflare-dns.com/dns-query; verify-doh-cert=yes

/ip dns static print where comment~"DoH bootstrap"
#   expect: two addresses for the primary host, two for dns.google

/system clock print          # expect the current date
/system ntp client print     # expect status: synchronized

/ip firewall nat print where comment~"force DNS"
/ip firewall filter print where comment~"DNS"

/ip dns cache flush
:put [:resolve example.com]  # 104.20.x / 172.66.x = real
                             # 8.6.112.0 / 8.47.69.0 = stub pair (Troubleshooting)
:put [:resolve pornhub.com]  # filtering: 0.0.0.0; standard: a real IP

:local r [/tool fetch url="https://cloudflare-dns.com/dns-query?name=example.com&type=A" \
    http-header-field="accept: application/dns-json" mode=https as-value output=user]
:put ($r->"status")                            # finished
:put ([:find ($r->"data") "\"Status\":0"])     # >= 0, no temp file

/log print where message~"DNS monitor"

Failover checklist

Reset the state globals before a test so the transition is logged again:

:global DNSMonitorState; :set DNSMonitorState ""
:global DNSFailCount; :set DNSFailCount 0
:global DNSRecoverCount; :set DNSRecoverCount 0
:global DNSFailoverAttempts; :set DNSFailoverAttempts 0
:global DNSMonitorRunning; :set DNSMonitorRunning false
# Scenario Setup Expected
1 normal DoH configured, real answers state healthy, log HEALTHY: answers look sane … (once)
2 single blip break primary, run the monitor once state suspect, log SUSPECT: primary unreachable (1/2) — no failover (anti-flap)
3 two bad runs run the monitor a second time state fallback, log FALLBACK: switched to fallback DoH …, endpoint = fallback
4 stub pair resolver returns 8.6.112.0/8.47.69.0 state stub, log STUB …, no failover
5 both down primary + fallback both unreachable state degraded, log DEGRADED: both endpoints unreachable …
6 fallback broken CA fallback host without a trusted CA log DEGRADED: fallback DoH did not resolve either — rolled back
7 recovery, first run restore primary, run once state recovering, log RECOVERING: primary answers again (1/2)
8 recovery, second run run again state healthy, log HEALTHY: primary DoH answers again …
9 wrong clock set the year back, run log CLOCK_INVALID …, nothing else
10 device-mode home run on a home device log MONITOR_DISABLED_BY_DEVICE_MODE …, state manual-only
11 CAPsMAN clients rejoin a client client uses the router and resolves
12 concurrency guard :global DNSMonitorRunning; :set DNSMonitorRunning true, run the monitor log DNS monitor: skipped — a previous run is still active, state unchanged

Restore afterwards:

/ip dns set use-doh-server="https://cloudflare-dns.com/dns-query" verify-doh-cert=yes
/ip dns cache flush

Measured results

0.2.0 — RouterOS 7.23.1 (hAP ax²), 2026-10-26

Check Observed
import Script file loaded and executed successfully; script + scheduler created
scheduler policy policy=read,write,policy,test
JSON probe code 200, 251-byte body, "Status":0 located by :find
content check answers look sane (N of 3) / answers are the stub pair …
failover switched to fallback, example.com -> 8.6.112.0, endpoint = fallback
rollback both endpoints dead → configuration untouched
clock guard wrong year → explicit message, no further action
Quad9 JSON DoH unable to decode BASE64-URL — not probeable

0.1.0 baseline — 2026-10-22, RouterOS 7.23.1 / 7.24.5

Check Observed
CA import 118 CAs imported; trusted=yes set
CA required without it: failure: dns server failure
builtin store parameter builtin-trust-anchors → bad parameter; the real one is builtin-trust-store
:resolve server= supported
:resolve timeout= bad parameter timeout
DoH resolve :resolve example.com → 8.6.112.0 / 8.47.69.0, recorded then as "real IP" — it is the stub pair

Fleet check (2026-10-26)

Six devices, RouterOS 7.23.1 / 7.24.5:

Device device-mode Result
office gateway (Chateau PRO ax) advanced monitor installed, one stub warning, VPN untouched
AP (cAP ax) advanced installed, one stub warning
test box (hAP ax²) advanced installed, failover and rollback exercised
branch A advanced installed, tunnel to the gateway 3 ms
branch B home not installed: fetch and scheduler are blocked by device-mode
branch C advanced installed

Per-model device-mode is recorded in the compatibility table of README.md — that table is the reference, and this one only records what the field run met.

All monitored devices reported the stub pair for the canaries at the time of installation — the reason this release exists.

0.4.2 checks (2026-11-02, RouterOS 7.24.5)

Check How Expected
payload check probe URL whose body contains a stub address substituted, not ok
STUB_CLEARED stub prefixes forced to match a live answer flush, re-check, state healthy
STUB stub prefixes forced, answers unchanged after flush STUB: logged with per-name detail
probeMode "resolve" own endpoint as primary, probeUrlA empty healthy, no switching, honest answers
no side effects three runs with applyChanges=false /ip dns unchanged

Clone this wiki locally