A network administrator in a branch office faced an unexpected outage where a Tailwind CSS assembly from CDN stopped loading after weeks of normal operation, while the rest of the internet remained accessible. Investigation on the MikroTik router showed that RouterOS reported healthy DNS resolution and DoH status zero responses, yet clients experienced timeouts. The root cause was two unreachable Cloudflare IP addresses, 8.6.112.0 and 8.47.69.0, which were valid answers but had no route from the affected network.
Default RouterOS DNS traffic travels in plaintext to the provider, exposing queries and allowing potential spoofing. Enabling DoH with a single command appeared to solve privacy concerns, but the single active upstream limitation meant no built-in failover existed. Custom scripting became necessary to meet three requirements: encrypted queries with certificate checks, forced client redirection to the router resolver, and automatic switching between endpoints on failure.
Initial script versions contained critical flaws. They accepted any IP-type response without validating content, performed probes by temporarily changing the active DoH server and thereby removing encryption from the local network, and fell back to plain DNS that itself returned spoofed answers on the measured dates. Later iterations introduced content-based health checks using three control domains, static bootstrap addresses to break resolution loops, and separate pre- and post-switch verification of the backup endpoint.
Certificate verification required importing the correct SSL.com TLS ECC Root CA 2022 because the built-in trust store did not cover the Cloudflare chain. Date validation was added to the monitor to prevent endless switching when system time was incorrect. The final four-stage chain prefers the primary DoH server, falls back through secondary DoH endpoints, and uses plain DNS only when explicitly enabled, with all transitions guarded by failure and recovery thresholds to avoid oscillation.
Measurements confirmed that the unreachable addresses were genuine Cloudflare responses; changing resolver brands did not help because the issue was routing, not DNS content. The working configuration therefore combines static host entries, HTTPS JSON probes with five-second timeouts, and journal-only logging on state changes to maintain both privacy and reachability in production.


