Community discussions

MikroTik App
 
erkexzcx
Member Candidate
Member Candidate
Topic Author
Posts: 153
Joined: Mon Oct 07, 2019 11:42 pm

[Script] Automatically change DNS if Pi-hole is no longer working

Sun May 31, 2020 2:44 pm

I've wrote a script that detects when Pi-Hole is no longer working, and automatically switches to public DNS 1.1.1.2,1.0.0.2.

Disclaimer: I am aware of possibility to set multiple DNS servers, but for Pi-Hole to work you need to set only Pi-Hole IP address.

Use case: Set-up Mikrotik and RPI with Pi-Hole. When RPI goes down, internet will "stop" working for everyone on the LAN, and you don't want it to happen. Add script to Mikrotik that detects when Pi-Hole is no longer resolving queries and switch all DNS settings on Mikrotik to public DNS servers, such as 1.1.1.2,1.0.0.2. Also notify yourself that RPI is down. Second RPI costs money, and brings no benefits rather than high-availability, so this is not an option in this case.

Variant 1 - changes only DNS server for router. Assumes that all devices use router as the only DNS server:
:local currentDNS [/ip dns get server]
:local piholeDNS "192.168.0.50"
:local backupDNS "1.1.1.2,1.0.0.2"
:local testDomain "www.google.com"

:if ($currentDNS = $piholeDNS) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
        /ip dns set servers=$backupDNS
    }
} else={
    :do {
        :resolve $testDomain server $piholeDNS
        /ip dns set servers=$piholeDNS
    } on-error={}
}
Variant 2 - changes only DNS server for router + notify yourself when Pi-Hole goes down via Telegram Bot. Assumes that all devices use router as the only DNS server:
:local telegramBotKey "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
:local chatID "XXXXXXXXX"

:local currentDNS [/ip dns get server]
:local piholeDNS "192.168.0.50"
:local backupDNS "1.1.1.2,1.0.0.2"
:local testDomain "www.google.com"

:if ($currentDNS = $piholeDNS) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
        /ip dns set servers=$backupDNS
        /tool fetch "https://api.telegram.org/bot$telegramBotKey/sendmessage?chat_id=$chatID&text=Pi-Hole not working! Changed DNS from $currentDNS to $backupDNS." keep-result=no
    }
} else={
    :do {
        :resolve $testDomain server $piholeDNS
        /ip dns set servers=$piholeDNS
        /tool fetch "https://api.telegram.org/bot$telegramBotKey/sendmessage?chat_id=$chatID&text=Pi-Hole is working again. Changed DNS from $currentDNS to $piholeDNS." keep-result=no
    } on-error={}
}
Variant 3 - changes DNS server for router and for all the networks (IP --> DHCP Server --> Networks). Depending on lease time, DNS will not update instantly for all clients, but allows Pi-Hole to show what uses it:
:local currentDNS [/ip dns get server]
:local piholeDNS "192.168.0.50"
:local backupDNS "1.1.1.2,1.0.0.2"
:local testDomain "www.google.com"

:if ($currentDNS = $piholeDNS) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
        /ip dns set servers=$backupDNS
        /ip dhcp-server network set [find] dns-server=$backupDNS;
    }
} else={
    :do {
        :resolve $testDomain server $piholeDNS
        /ip dns set servers=$piholeDNS
        /ip dhcp-server network set [find] dns-server=$piholeDNS;
    } on-error={}
}
Variant 4 - changes DNS server for router and for all the networks (IP --> DHCP Server --> Networks) + notify yourself when Pi-Hole goes down via Telegram Bot. Depending on lease time, DNS will not update instantly for all clients, but allows Pi-Hole to show what uses it:
:local telegramBotKey "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
:local chatID "XXXXXXXXX"

:local currentDNS [/ip dns get server]
:local piholeDNS "192.168.0.50"
:local backupDNS "1.1.1.2,1.0.0.2"
:local testDomain "www.google.com"

:if ($currentDNS = $piholeDNS) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
        /ip dns set servers=$backupDNS
        /ip dhcp-server network set [find] dns-server=$backupDNS;
        /tool fetch "https://api.telegram.org/bot$telegramBotKey/sendmessage?chat_id=$chatID&text=Pi-Hole not working! Changed DNS from $currentDNS to $backupDNS." keep-result=no
    }
} else={
    :do {
        :resolve $testDomain server $piholeDNS
        /ip dns set servers=$piholeDNS
        /ip dhcp-server network set [find] dns-server=$piholeDNS;
        /tool fetch "https://api.telegram.org/bot$telegramBotKey/sendmessage?chat_id=$chatID&text=Pi-Hole is working again. Changed DNS from $currentDNS to $piholeDNS." keep-result=no
    } on-error={}
}
Usage: Use system --> scheduler --> add. Set interval to 00:00:30, any name and paste script into "On Event:" field. Do not forget to change variable values to match your Pi-Hole IP address.

EDIT: Updated scripts according to suggestions in comments & offered more variants.
Last edited by erkexzcx on Sun May 31, 2020 7:43 pm, edited 1 time in total.
 
User avatar
jvanhambelgium
Member
Member
Posts: 386
Joined: Thu Jul 14, 2016 9:29 pm
Location: Belgium

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Sun May 31, 2020 3:13 pm

This will not work for all clients that have received their DHCP-lease.
I don't know how many hours of lease-time you provide so these clients don't really benefit from the switchover you make on RouterOS. If their (only) DNS-server fails it is over & out.

Multiple DNS would be a / the only true "redundant solution" for your clients.

EDIT : Ah ok, so your Mikrotik IS already the DNS for your client and you are only forwarding to either Pi-hole (if operational) or some public upstream DNS in case of failure ? Or not ?
Because if your Mikrotik is in the DNS-chain, do you see in the Pi-hole stats the individual clients ? Aren't they all appearing come from 1 client "mikrotik" ?
 
User avatar
Jotne
Forum Guru
Forum Guru
Posts: 1878
Joined: Sat Dec 24, 2016 11:17 am
Location: jo.overland at gmail.com

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Sun May 31, 2020 6:43 pm

Thanks for the script.

I do see a use for it in my case. I have a DoH server running separately on an MT running 6.47 beta. On my main MT Router i have one DNS point to that DoH MT router. If add a second DNS on main router, that will be used without going trough the DoH server. So I can use the script to test the if the DNS on the DoH router works, if not replace DNS with a working one.


Some tips.

If you do suggest to use local variable. I do not see in your script any reason to use global variable. It will just fill up the variable space.

Noe need for semicolon at the end of the line. Only needed when multiple commands are on the same line.

So:
:local currentDNS [/ip dns get server]
:local piholeDNS "192.168.0.50"
:local backupDNS "1.1.1.2,1.0.0.2"
:local testDomain "www.google.com"

:if ($currentDNS = $piholeDNS) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
        /ip dns set servers=$backupDNS
        /ip dhcp-server network set [find] dns-server=$backupDNS
    }
} else={
    :do {
        :resolve $testDomain server $piholeDNS
        /ip dns set servers=$piholeDNS
        /ip dhcp-server network set [find] dns-server=$piholeDNS
    } on-error={}
}
 
Why do not use Splunk to monitor your MikroTik Router(s)? Look at this page in how to set it up.

MikroTik->Splunk
 
 
User avatar
Jotne
Forum Guru
Forum Guru
Posts: 1878
Joined: Sat Dec 24, 2016 11:17 am
Location: jo.overland at gmail.com

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Sun May 31, 2020 7:15 pm

Here is my version of DoH server not working any more. Thanks again for the idea.
Added logging when things change. I love to log everything (see my signature)
:local currentDNS [/ip dns get server]
:local DoHDNS "192.168.20.10"
:local backupDNS "8.8.8.8,1.1.1.1"
:local testDomain "www.google.com"

:if ($currentDNS = $DoHDNS) do={
    :do {
        :resolve $testDomain server $DoHDNS
    } on-error={
        /ip dns set servers=$backupDNS
		:log info message="DNS_server=$backupDNS"
    }
} else={
    :do {
        :resolve $testDomain server $DoHDNS
        /ip dns set servers=$DoHDNS
		:log info message="DNS_server=$DoHDNS"
    } on-error={}
}
I do run this with an one minute schedule. 00:01:00
Last edited by Jotne on Wed Jul 29, 2020 11:01 am, edited 1 time in total.
 
Why do not use Splunk to monitor your MikroTik Router(s)? Look at this page in how to set it up.

MikroTik->Splunk
 
 
erkexzcx
Member Candidate
Member Candidate
Topic Author
Posts: 153
Joined: Mon Oct 07, 2019 11:42 pm

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Sun May 31, 2020 7:44 pm

Thank you. I updated my initial comment with your suggestions. :)
 
ladegro
just joined
Posts: 8
Joined: Tue Apr 03, 2018 11:05 am

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Wed Jul 29, 2020 10:25 am

Thanks a lot for this, exactly what I was looking for and very useful. Even if there is some downtime because of not yet expired lease time, this guarantees it will eventually come back up. So if I'm away from home, the misses doesn't have to worry. Great!

(using it with adGuard by the way but that of course doesn't matter)
 
TDJ211
just joined
Posts: 7
Joined: Mon Jul 01, 2019 2:30 am

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Tue Aug 11, 2020 1:05 pm

Oh wow, this is perfect for me!

Im using a local Unbound DNS server for perfomance and like you Ive found the only way to get the Mikrotik to reliably use the local DNS is to set only the one DNS server.

Ive been bitten once before by forgetting to change my DNS when doing server maintenance. Nice to know ill have a backup just in case the server goes down for real.
 
Dennypr
just joined
Posts: 2
Joined: Tue Aug 11, 2020 7:30 pm

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Tue Aug 11, 2020 8:04 pm

Please help,

Can i change mac address automatically by script on every day?..
Btw thx can any one to help me
 
User avatar
Jotne
Forum Guru
Forum Guru
Posts: 1878
Joined: Sat Dec 24, 2016 11:17 am
Location: jo.overland at gmail.com

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Tue Aug 18, 2020 11:00 pm

Can i change mac address automatically by script on every day?..
Yes it can be do.
Post it as a new question.
 
Why do not use Splunk to monitor your MikroTik Router(s)? Look at this page in how to set it up.

MikroTik->Splunk
 
 
hollerauer
just joined
Posts: 3
Joined: Wed Jan 06, 2021 12:55 pm

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Wed Jan 06, 2021 1:52 pm

!! Due to sporadic failures (in my installation) affecting DNS-queries it is NOT advised to use the proposed configuration in PRODUCTIVE environment. This post will be updated after problem is fixed!!
I've wrote a script that detects when Pi-Hole is no longer working, and automatically switches to public DNS 1.1.1.2,1.0.0.2.Disclaimer: I am aware of possibility to set multiple DNS servers, but for Pi-Hole to work you need to set only Pi-Hole IP address.

Use case: Set-up Mikrotik and RPI with Pi-Hole. When RPI goes down, internet will "stop" working for everyone on the LAN, and you don't want it to happen. Add script to Mikrotik that detects when Pi-Hole is no longer resolving queries and switch all DNS settings on Mikrotik to public DNS servers, such as 1.1.1.2,1.0.0.2. Also notify yourself that RPI is down. Second RPI costs money, and brings no benefits rather than high-availability, so this is not an option in this case.
This script is exactly what I was looking for. I want to share an even more elegant way how to integrate a Pi-Hole in your LAN.
Use case:
  1. Set mikrotik as DNS server for your LAN(-segments)
    /ip dns set allow-remote-requests=yes servers=$YourPrefferedPublicDNSServers$; \
    /ip dhcp-server network set dns-server=$YourMikrotikLANAddress$
  2. Add a NAT rule for each LAN(-segment) to redirect any traffic from LAN(-segment) associated with udp port 53 to Pi-Hole. Comment the rule with "pihole".
    /ip firewall nat add chain=dstnat action=dst-nat to-addresses=$YourPiHoleAddress$ protocol=udp src-address=$YourLANSegment$ dst-address=!$YourPiHoleAddress$ dst-port=53 comment="pihole"
  3. Add script to switch (enable|disable) NAT rule
    :local piholeDNS "$YourPiHoleAddress$"
    :local testDomain "www.example.com"
    :local piholeRulesEnabled [/ip firewall nat print count-only where comment~"pihole" && !disabled]
    
    if ($piholeRulesEnabled > 0)
    do={ \
    	:do {:resolve $testDomain server=$piholeDNS} \
    	on-error={/ip firewall nat disable [find comment~"pihole"]} \
    	}
    else={ \
    	:do { \
    		:resolve $testDomain server=$piholeDNS; \
    		/ip firewall nat enable [find comment~"pihole"] \
    		} \
    	on-error={} \
    	}
    
  4. Add scheduler to execute script time based
Benefits:
  • All DNS queries (even the ones from clients where you can not change DNS server) are redirected to Pi-Hole
  • Pi-Hole can "see" all LAN clients
  • Fallback if Pi-Hole is down
!! Due to sporadic failures (in my installation) affecting DNS-queries it is NOT advised to use the proposed configuration in PRODUCTIVE environment. This post will be updated after problem is fixed!!
Last edited by hollerauer on Fri Jan 22, 2021 8:25 am, edited 1 time in total.
 
zilexa
just joined
Posts: 6
Joined: Tue Apr 10, 2018 6:05 pm

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Thu Jan 14, 2021 5:50 pm

This script is exactly what I was looking for. I want to share an even more elegant way how to integrate a Pi-Hole in your LAN.
Use case:
  1. Set mikrotik as DNS server for your LAN(-segments)
    /ip dns set allow-remote-requests=yes servers=$YourPrefferedPublicDNSServers$; \
    /ip dhcp-server network set dns-server=$YourMikrotikLANAddress$
  2. Add a NAT rule for each LAN(-segment) to redirect any traffic from LAN(-segment) associated with udp port 53 to Pi-Hole. Comment the rule with "pihole".
    /ip firewall nat add chain=dstnat action=dst-nat to-addresses=$YourPiHoleAddress$ protocol=udp src-address=$YourLANSegment$ dst-address=!$YourPiHoleAddress$ dst-port=53 comment="pihole"
    Benefits:
    • All DNS queries (even the ones from clients where you can not change DNS server) are redirected to Pi-Hole
    • Pi-Hole can "see" all LAN clients
    • Fallback if Pi-Hole is down

Without using the fallback script yet: the NAT rule does not work as expected.

Scenario 1, my working situation without fallback:
Router IP: 192.168.88.1 with IP > DHCP Server > DNS set to 192.168.88.1
IP > DNS is set to 192.168.88.2
My (Ubuntu) Server running PiHole has IP 192.168.88.2. This way, internet works.

Scenario 1-modified to support a fallback (without the actual script yet):
I change IP > DNS to 1.1.1.1 (necessary for the fallback scenario).
I add the NAT rule:
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=192.168.88.2 protocol=udp src-address=192.168.88.0/24 dst-address=!192.168.88.2 dst-port=53 comment="pihole"
Issue 1:
After I add the NAT rule, my clients cannot resolve DNS anymore. Not even when I disconnect/reconnect them.
Issue 2:
Your rule includes dst-address=!$YourPiHoleAddress$ not sure what it means, but doesn't that exclude the server? I still need my server for other things that requires resolving of domains.

I would love for your NAT rule to work though..

EDIT: to get it to work at all, you also need a masquerade rule like this:
[/code]add action=masquerade chain=srcnat src-address=192.168.88.0/24 dst-address-list=192.168.88.2 dst-port=53 protocol=udp[/code]

But still, the server that runs Pi-Hole is now unable to resolve domains. Also, it seems none of my devices work.
As soon as I disable your NAT rule and my masquarade rule, everything works again.
 
hollerauer
just joined
Posts: 3
Joined: Wed Jan 06, 2021 12:55 pm

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Thu Jan 14, 2021 9:14 pm

Without using the fallback script yet: the NAT rule does not work as expected.
You are correct. That's what I meant with $YourFavoritePublicDNSServers$ = e.g. 1.1.1.1, 1.0.0.1, etc.
Scenario 1-modified to support a fallback (without the actual script yet):
I change IP > DNS to 1.1.1.1 (necessary for the fallback scenario).
I add the NAT rule:
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=192.168.88.2 protocol=udp src-address=192.168.88.0/24 dst-address=!192.168.88.2 dst-port=53 comment="pihole"
Issue 1:
After I add the NAT rule, my clients cannot resolve DNS anymore. Not even when I disconnect/reconnect them.
The parameters are set correct. But your use-case is different then mine. In my case the pihole is in another IP-Segment (10.0.0.0/8). If your mikrotik device is your Internet-gateway than it will loop DNS-traffic (udp p53) back to pihole.
You will need a second rule which is placed above your pihole-rule (processed first):
ip firewall nat add chain=dstnat src-address=192.168.88.2 protocol=udp dst-port=53 comment="traffic pihole to www"
Issue 2:
Your rule includes dst-address=!$YourPiHoleAddress$ not sure what it means, but doesn't that exclude the server? I still need my server for other things that requires resolving of domains.
Means if there is DNS traffic directly to your server it is excluded from this rule. You should configure your server to use 127.0.0.1 for DNS.
EDIT: to get it to work at all, you also need a masquerade rule like this:
[/code]add action=masquerade chain=srcnat src-address=192.168.88.0/24 dst-address-list=192.168.88.2 dst-port=53 protocol=udp[/code]
Not true. there is no need to masquerade or srcnat or redirect. Masquerade is a special version of srcnat designed for traffic from LAN -> www with changing public ip address.
The dstnat rule will take care of redirecting DNS traffic back to device.

It works like this:
  1. device A asks mikrotik (= per DHCP defined DNS server) for Domain "example.com"
  2. mikrotik recieves the request and checks if there is a firewall (nat) rule for it
  3. as there is a rule (pihole), mikrotik asks pihole for Domain "example.com" in the name of device A
  4. pihole answers to mikrotik and asks mikrotik to forward the answer to device A
  5. mikrotik receives the answer and checks if there is a firewall (nat) ruie for it
  6. mikrotik forwards answer of pihole to device A
Please test the additional NAT rule in your setup. If it works for you I'll edit my original post.
 
LordTMortis
just joined
Posts: 1
Joined: Fri Jan 15, 2021 5:39 pm

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Fri Jan 15, 2021 5:59 pm

Hey,

I've sucessfully used PiHole to improve my ad-situation and have been trying to use some sort of script to have working failsafe in place in case my Pi is not running.
I am not seeing Mikrotik for the first time, but I am quite new to scripting.

However, I am a bit stuck at the moment, as I do not want to change DNS systemwide, I only want to change DNS for clients that use DHCP.

I used following code to have working switch from piholeDNS to backupDNS:
:local piholeDNS "192.168.88.6"
:local backupDNS "8.8.8.8,8.8.4.4"
:local currentDHCPDNS []

:if ([/ping $piholeDNS count=20] =0) do={
        :log info "PiHole server nedostupny, pro DHCP klienty měním DNS server na zalozni." 
	/ip dhcp-server network set [find] dns-server=$backupDNS;
    } else={
	     
	    :log info "PiHole server dostupny, netreba nic menit." 
		 }
 
This code allows my MK to change DNS for my DHCP clients. It's not ideal, as when my Pi comes back online, there is no automatic change from backupDNS to piholeDNS.
What I did at the moment was adding following line into my else statement:
/ip dhcp-server network set [find] dns-server=$piholeDNS;
Which works... but the problem is, it works everytime and in my Log i can see that DNS has been changed everytime. This behaviour is not optimal and I would like to make it work only, if the DNS for my DHCP clients is not piholeDNS. This is the place that made me stuck as I found no way to get information about DHCP DNS only.

I tried to make local variable in which I store the value of currentDHCPDNS:
:local currentDHCPDNS [/ip dhcp-server network get [find dns-server]]
That does not work, so I tried:
:local currentDHCPDNS [/ip dhcp-server network get dns-server]
It seems I cannot figure out how to get desired info.

Could you please give me some hint how to extract current value of DHCP DNS?

Thank you very much.
Last edited by LordTMortis on Fri Jan 15, 2021 6:02 pm, edited 1 time in total.
 
hollerauer
just joined
Posts: 3
Joined: Wed Jan 06, 2021 12:55 pm

Re: [Script] Automatically change DNS if Pi-hole is no longer working

Fri Jan 22, 2021 9:23 am

I've sucessfully used PiHole to improve my ad-situation and have been trying to use some sort of script to have working failsafe in place in case my Pi is not running.
I am not seeing Mikrotik for the first time, but I am quite new to scripting.
You can get the number of DHCP server which use pihole as DNS server:
:local currentDHCPDNS [/ip dhcp-server network print count-only where dns-server=$piholeDNS] 
and decide based on that:
:if ($currentDHCPDNS = 0) ...


Another solution might be, instead of using a script you could use the netwatch tool.
/tool netwatch add host=$piholeDNS up-script=[/ip dhcp-server network set dns-server=$piholeDNS] down-script=[/ip dhcp-server network set dns-server=$backupDNS]
A major drawback of both methods is, that clients will notice the change first after dhcp lease renew. Depending on lease-time this can be quite a while (default 10m).

Who is online

Users browsing this forum: No registered users and 35 guests