I am using Pihole as my DNS server and configured RouterOS to use Pihole DNS which is working fine. What I want to do is configure RouterOS to use a failover DNS (ISP or any public DNS like Google) in case of pihole stopped working and mikrotik takes DNS server from predefined DNS servers. I do not want load balancing. Just wanted to use them as failover in case of pihole goes down since it is running inside a VM. Some times I get electricity issues or sometimes windows get updates and workstation takes longer to install them in restarting procedure.
Generally, DNS resolvers are not meant to function like this. You can have multiple for redundancy, but it’s assumed that all are equal and client can use any of them. But it doesn’t work for this use case, where you need a special one that knows something that others don’t and you want to only use others when the special one fails.
A not completely foolproof, but possibly good enough solution could be to use Netwatch, to monitor Pihole’s IP address. If it goes down, set system resolvers to public ones. If it goes up, set it to Pihole.
I looked into the Netwatch feature https://wiki.mikrotik.com/wiki/Manual:Tools/Netwatch and it seems to do the trick! Netwatch will watch a host with pings, and run a script if the host is up or down.
/tool netwatch
add comment=“pi-hole failover” down-script=“/ip dhcp-server network set 0 dns-server=""” host=192.168.88.15
up-script=“/ip dhcp-server network set 0 dns-server=192.168.88.15”
my pi-hole is 192.168.88.15
if up: /ip dhcp-server network set 0 dns-server=192.168.88.15
if down, blank it out (or set it to 1.1.1.1 or 192.168.88.1): /ip dhcp-server network set 0 dns-server=""
my dhcp network settings
This is exactly correct, all DNS servers are equal to the client so setting a “secondary” DNS server doesn’t work the way you might think. I use a Pihole which runs on a 2010 Mac Mini, and even though I dropped in a new hard drive I had concerns about redundancy. So I use scripts with netwatch to set the router as a backup DNS, and it works pretty well. I’m out of town right now but can take a look at the script when I get home.
Everything starting with my_* should be customized for your environment. I use the router as the DNS server so I can still have control and a central place to redirect via NAT rule. For this to work best, I also recommend setting the router as a second DNS server address on all clients. This works fast enough that I receive all the notification emails
EDIT: I realized that, if the device never went down, Netwatch will always run the “Up” script any time a change is made to it (because the device is still “up”). I don’t want this to happen if the pihole never went down, so I put a condition in to check whether the router is actually acting as a DNS server before doing anything.
EDIT 2: Turns out you can’t script firewall rule changes unless you either enumerate all rules first with a print, or determine their internal IDs and use those (see http://forum.mikrotik.com/t/ask-modify-firewall-order-or-add-firewall-with-script/15392/6 for more details). I cheated and just did the print, but later when I have the chance I’ll do it a better way.
Netwatch down script for the pihole IP:
# script to enable backupDNS if pihole doesn't ping
# this script does nothing if the core switch is also down
# set variables
:local myhost ([/system identity get name])
:local recv my_alerts@email.com
:local target my_pihole;
# Query the core switch interface
:local inetinterface "ether1"
:if ([/interface get [find name="$inetinterface"] running]=true) do={
:log info "BackupDNS: Pihole down, enabling"
# change to your upstream resolvers
/ip dns set servers=your_resolver_IP1,your_resolver_IP2
:delay 2
:log info "BackupDNS: resolvers changed"
# enable DNS server
/ip dns set allow-remote-requests=yes
:delay 2
:log info "BackupDNS: started server"
# assuming you have one NAT redirect rule which is first in the list, change the to-address to your router IP
/ip firewall nat print; /ip firewall nat set to-addresses=your_router_IP numbers=1
:delay 1
:log info "BackupDNS: NAT rule redirected"
# email notification
/tool e-mail send to=$recv subject="$myhost started BackupDNS" body="On $mydate at $mytime, $myhost started BackupDNS because $target was reported down."
} else={ :log info "BackupDNS: Core switch interface $inetinterface is not running, script exited" }
Netwatch up script for the pihole IP:
# script to disable secondary DNS when pihole is back up
# set variables
:local myhost ([/system identity get name])
:local recv my_alerts@email.com
:local target my_pihole;
:if ([/ip dns get allow-remote-requests]=true) do={
# email notification
/tool e-mail send to=$recv subject="$myhost stopping BackupDNS" body="On $mydate at $mytime, $myhost stopping BackupDNS because $target was reported back up."
:delay 10
:log info "BackupDNS: Pihole up, stopping"
# change resolver back to my_pihole
/ip dns set servers=my_pihole_IP
:delay 1
:log info "BackupDNS: pihole now set as resolver"
# assuming you have one NAT redirect rule which is first in the list, change back to your pihole
/ip firewall print; /ip firewall nat set to-addresses=my_pihole_IP numbers=1
:delay 1
:log info "BackupDNS: NAT rule changed back to pihole"
# disable DNS server and flush the cache
/ip dns set allow-remote-requests=no
:delay 1
/ip dns cache flush
:log info "BackupDNS: DNS server disabled and cache flushed"
} else={ :log info "BackupDNS: Pihole is up but router wasn't DNS server, script exited" }
this is the easiest way, but maybe you can add another line for disabling firewall nat rules that dst-nat port 53 udp/tcp to the pihole server? Because some of us maybe restrict the end users from using external dns server, so we redirect all dns request to the pihole no matter what ip they change.
I couldn’t get netwatch to trigger properly with all of its permissions restrictions. For my home use case, running a little script once a minute from the scheduler seems to work well. I have my DHCP Server > Networks > DNS Servers pointed to my MikroTik router gateway address so clients do not need to reconfigure.
Here is my script if it’s helpful. You can customize the fallbackDNS addresses, Pi-Hole ip address, and resolve url to fit your needs.
# set variables
:local fallbackDNS 1.1.1.1,1.0.0.1
:local pihole 192.XXX.XX.XXX;
:local currentDNS
:set $currentDNS [/ip dns get servers];
:do {
:put [resolve google.com server=$pihole];
if ($currentDNS!=pihole) do={
:log info "DNS Failover: Switching to Pi-Hole";
ip dns set servers $pihole
} else={}
} on-error={ :set $currentDNS [/ip dns get servers];
if ($currentDNS!=$fallbackDNS) do={
:log info "DNS Failover: Switching to FallbackDNS";
ip dns set servers $fallbackDNS;
} else={:log info "DNS Failover: Pi-Hole Unavailable"}
}
#try to reach google through the pi-hole
#if it works and we are on a different DNS, set the DNS server to the pi-hole
#if it works and we are already on the pi-hole, do nothing
#if we can't reach google and we aren't already on our FallbackDNS, switch to fallback
#if we can't reach google through pi-hole and we are on the fallback, log that pi-hole is unavailable
Is this suppose to work? Because everyone else in this topic is using a script.. but your solution would be smarter since you don’t have to ping your pihole every minute.
The problem with netwatch is that it just pings the server. The server may be up but Pi-hole can be down. I wrote the following script and run it once a minute. If Pi-hole is down the fetch will fail and the on-error code executes. Once Pi-hole is back up it is set as DNS server again.
:local servers [/ip dns get servers];
:do {
/tool fetch url="http://192.168.1.26:8082/admin/api.php?status";
if ($servers != "192.168.1.26") do={
/ip dns set servers=192.168.1.26;
}
} on-error {
if ($servers != "208.67.220.123;208.67.222.123") do={
/ip dns set servers=208.67.220.123,208.67.222.123;
:log error "Pi-hole isn't working, using OpenDNS instead";
}
}
I’m using this solution actually with a script to change to public dns if PiHole is offline. I wonder if it’s possible to point clients directly to PiHole bypass MikroTik to speed up the query.
If I set the PiHole address by dhcp network to the client, I need to wait for a renewal to change the addresses to the clients, any other solutions? Perhaps a NAT redirect would be the best solution?!
So in practice… assuming your PiHole sits at 192.168.1.3
Set your DHCP server to tell clients to use 8.8.8.8 and 8.8.4.4.
Make a firewall address list named Google