Repository navigation
Upgrading
| Area | 0.3.1 | 0.4.0 |
|---|---|---|
| Probe |
/tool fetch to a temp file, then /file remove
|
/tool fetch ... as-value output=user (in memory, no /file) |
| JSON check |
"Status":0 only |
"Status":0 or "Status": 0
|
| Fallback | one secondary DoH | primary → secondary → tertiary (dohUrlC) → plain DNS (plainFallback) |
| States | healthy … manual-only | + plain
|
| Defaults | — |
dohUrlC="", plainFallback=false (behaviour unchanged until set) |
| Area | 0.2.0 | 0.3.0 |
|---|---|---|
| State machine | healthy / stub / dead / failoverB | explicit: healthy → suspect → fallback → recovering → healthy (+ stub, degraded, clock-invalid, manual-only) |
| Failover trigger | any bad run |
failureThreshold (2) consecutive bad runs (anti-flap) |
| Recovery | one good run |
recoveryThreshold (2) consecutive good runs |
| Interval | hardcoded 3 m | configurable monitorInterval, default 60 s |
| Enforcement | 53 redirect only |
enforcement=strict blocks DoT 853 + known public DoH endpoints |
| device-mode=home | "both endpoints unreachable" | explicit MONITOR_DISABLED_BY_DEVICE_MODE + manual-only
|
| Wording | — | "managed failover" (not transparent): fallback is a different operator |
/import file-name=02-security-policies.rsc
/import file-name=05-dns-health-monitor.rsc
:global DNSMonitorState; :set DNSMonitorState ""
:global DNSFailCount; :set DNSFailCount 0
:global DNSRecoverCount; :set DNSRecoverCount 0
:global DNSFailoverAttempts; :set DNSFailoverAttempts 0| Area | 0.1.0 | 0.2.0 |
|---|---|---|
| Default upstream | Family (family.cloudflare-dns.com) |
Standard (cloudflare-dns.com) |
| Failover target | plain Family DNS | a second DoH endpoint (Google) |
| Health check | any valid IP counts as healthy | content: empty, 0.0.0.0 and the stub pair are unusable |
| Check side effect | flipped use-doh-server (whole LAN off DoH during a check) |
/tool fetch probe, /ip dns untouched |
| Failed failover | left on the plain path | verified, then rolled back to the primary |
| Clock | unchecked | checked first, reported explicitly |
| Scheduler policy | default full set | read,write,policy,test |
| Bootstrap records | primary host only | primary and fallback host |
# 1. Re-import the scripts whose behaviour changed
/import file-name=01-configure-doh.rsc
/import file-name=05-dns-health-monitor.rsc
# 2. Clear the old state so the new monitor logs its transitions
:global DNSMonitorState; :set DNSMonitorState ""
:global DNSFailoverAttempts; :set DNSFailoverAttempts 0
:global DNSCurrentMode; :set DNSCurrentMode "" # unused since 0.2.0
# 3. Confirm
/ip dns print
/ip dns static print where comment~"DoH bootstrap"
/system script run DNS_HealthMonitor_Failover
/log print where message~"DNS monitor"02-security-policies.rsc changed only in its comments (a documented scope
limit), so re-importing it is optional. If you came from a 0.1.0 Family setup,
the old family.cloudflare-dns.com static records stay behind: they are
harmless, but they resolve to an endpoint you no longer use. Remove them, or
follow “If you want to keep Family” below and keep them deliberately.
The checklist to expect: four bootstrap records (two per host), use-doh-server
pointing at cloudflare-dns.com, and filtering left at false.
01 defaults to the standard resolver. To stay on Family:
/ip dns set servers=1.1.1.3,1.0.0.3
/ip dns set use-doh-server="https://family.cloudflare-dns.com/dns-query" verify-doh-cert=yes
/ip dns static add name=family.cloudflare-dns.com address=1.1.1.3 ttl=1d comment="DoH bootstrap"
/ip dns static add name=family.cloudflare-dns.com address=1.0.0.3 ttl=1d comment="DoH bootstrap"and set filtering=true in 05-dns-health-monitor.rsc for the reader's sake —
be aware that this flag is not read by the script: it is a marker that records
which kind of endpoint you chose, and nothing in the log depends on it
(05-dns-health-monitor.rsc declares it once and never uses it). What the monitor
does is decided by the URL, the probe URLs and the CA.
examples/cloudflare-family.rsc does all of this in one file.
Every device that answers with the stub pair will log one line per state change:
DNS monitor: answers are the stub pair — example.com=8.47.69.0 (stub pair); …
That is not an error in the monitor: at the time of writing, all six field devices answered exactly like that. See Troubleshooting for what to do if CDNs actually fail.
/system scheduler remove [find name="Scheduler_DNS_Health_Check"]
/system script remove [find name="DNS_HealthMonitor_Failover"]
# then re-import the 0.1.0 files from the v0.1.0 tagWiki for mikrotik-doh-failover 0.4.1 (2026-10-28, RouterOS 7.23.1 / 7.24.5).
The repository is the source of truth: when a page here disagrees with
README.md or
docs/, the
repository wins. Found a wrong statement? Open an issue with the command you ran
and its output — a claim without a measurement is not accepted.
mikrotik-doh-failover — wiki for version 0.4.3
- Getting started
- Configuration
- How it works — full flowchart
- Health monitor
- Verification
- Troubleshooting
- Changelog
- Upgrading from 0.1.0
- Zabbix monitoring
Package: PyPI — mikrotik-doh-failover · Repository: paulmann/mikrotik-doh-failover · README · Releases · Changelog