Mikrotik DNS failover script, for Pi-Hole

MikroTik DNS Failover Script for Pi-Hole

If you have a Pi-hole configured on your home lab and you’re anything like me, there’ll be occasions in which you’ll be tinkering with your Pi-hole and affecting your home network.

But this shouldn’t be the case. You can configure your MikroTik so it automatically takes over DNS resolution upon Pi-hole failure — seamlessly, with zero manual intervention, and with a Telegram notification so you know exactly what happened and when.


How It Works

The setup relies on a MikroTik Netwatch rule that monitors a secondary IP on the Pi-hole VM. When that IP stops responding, MikroTik assumes the DNS service is down and activates a fallback — by enabling a dormant IP address directly on the router that answers DNS queries itself. When the Pi-hole comes back, the process reverses.

Here’s the full flow:

Normal state (Pi-hole up):

  • Pi-hole VM has two interfaces: one serving DNS (10.1.1.10) and one dedicated to monitoring (10.1.100.2) with no gateway, on a separate VLAN only the MikroTik can reach
  • MikroTik’s Netwatch pings the monitoring IP (10.1.100.2) at regular intervals
  • Two IP addresses are configured on the MikroTik but kept disabled: 10.1.1.10/24 and 10.1.100.2/24
  • MikroTik forwards DNS to the Pi-hole at 10.1.1.10

Failover state (Pi-hole down):

  • Netwatch detects the monitoring IP is unreachable
  • MikroTik enables its own 10.1.1.10 and 10.1.100.2 addresses, effectively impersonating the Pi-hole on the network
  • MikroTik clears the ARP entries for both IPs so clients pick up the new owner immediately
  • MikroTik switches its DNS server to AdGuard’s public DNS (94.140.14.14, 94.140.15.15) — which still blocks ads and trackers, keeping the experience close to normal even during failover
  • A Telegram notification fires

Recovery (Pi-hole back up):

  • Netwatch detects the monitoring IP is reachable again
  • MikroTik disables its own 10.1.1.10 and 10.1.100.2 addresses
  • ARP entries are cleared again so clients reconnect to the real Pi-hole
  • MikroTik switches DNS back to 10.1.1.10
  • Another Telegram notification fires

The reason for the separate monitoring interface is important: you don’t want Netwatch pinging the DNS IP itself (10.1.1.10), because MikroTik would be impersonating that IP during failover — which would make Netwatch think the Pi-hole is back up when it isn’t. The monitoring IP on its own isolated VLAN can only be answered by the real VM, never by the MikroTik fallback.


Prerequisites

  • MikroTik router with RouterOS
  • Pi-hole running on a VM with two network interfaces
  • A Telegram bot token and chat ID for notifications
  • The monitoring VLAN must be routable from the MikroTik but not from other devices

MikroTik Configuration

Step 1 — Add the fallback IP addresses (disabled by default)

These are the addresses MikroTik will enable during failover. Replace the interface name with your actual LAN bridge or interface.

/ip address
add address=10.1.1.10/24 interface=bridge-home disabled=yes
add address=10.1.100.2/24 interface=bridge-mgmt disabled=yes

Step 2 — Configure Netwatch

Netwatch monitors the Pi-hole’s dedicated monitoring IP. Adjust the interval and timeout to your preference.

/tool netwatch
add host=10.1.100.2 interval=30s timeout=5s \
    up-script=dns-up \
    down-script=dns-down \
    comment="Pi-hole DNS monitor"

Step 3 — The down script (Pi-hole unreachable)

/system script
add name=dns-down source={
:global telegramMessage "DNS Server not detected, backup DNS enabled"
:log error "$telegramMessage"
/ip dns set servers=94.140.14.14,94.140.15.15
/ip address enable [find address="10.1.1.10/24"]
/ip address enable [find address="10.1.100.2/24"]
/ip arp remove [find address=10.1.1.10]
/ip arp remove [find address=10.1.100.2]
/tool fetch url="https://api.telegram.org/bot<YOUR_TOKEN>/sendMessage?chat_id=<YOUR_CHAT_ID>&text=$telegramMessage" keep-result=no
}

Step 4 — The up script (Pi-hole restored)

/system script
add name=dns-up source={
:global telegramMessage "DNS Server detected, DNS Service Restored"
:log warning "$telegramMessage"
/ip dns set servers=10.1.1.10
/ip address disable [find address="10.1.1.10/24"]
/ip address disable [find address="10.1.100.2/24"]
/ip arp remove [find address=10.1.1.10]
/ip arp remove [find address=10.1.100.2]
/tool fetch url="https://api.telegram.org/bot<YOUR_TOKEN>/sendMessage?chat_id=<YOUR_CHAT_ID>&text=$telegramMessage" keep-result=no
}

Replace <YOUR_TOKEN> with your Telegram bot token and <YOUR_CHAT_ID> with your chat ID.


Why Clear the ARP Table?

This is the detail that makes the whole thing work cleanly. When MikroTik enables a new IP address, clients on the network may still have the old ARP entry cached — pointing to the Pi-hole’s MAC address. By clearing the ARP entries for both IPs immediately after the switch, you force clients to re-resolve, and they’ll get the MikroTik’s MAC address instead. Without this step, clients could experience a gap in DNS resolution even after the failover has technically completed.

The same logic applies on recovery — you clear the ARP entries so clients stop pointing at the MikroTik and pick up the Pi-hole again.


Result

With this in place, a Pi-hole restart, a VM crash, or any maintenance you do on the DNS server will cause a seamless failover in under 30 seconds (or whatever interval you set). Your network keeps resolving DNS, your devices never notice, and you get a Telegram message telling you exactly what happened.

When you bring the Pi-hole back up, everything switches back automatically — including your ad-blocking and local DNS records — again without touching anything manually.


Tested on RouterOS 7.x. The Netwatch tool and script engine behave consistently across recent RouterOS versions, but always test in your own environment before relying on it in production.