Community discussions

MikroTik App
 
User avatar
erkexzcx
Member Candidate
Member Candidate
Topic Author
Posts: 264
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
Forum Guru
Forum Guru
Posts: 1086
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: 3334
Joined: Sat Dec 24, 2016 11:17 am
Location: Magrathean

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={}
}
 
User avatar
Jotne
Forum Guru
Forum Guru
Posts: 3334
Joined: Sat Dec 24, 2016 11:17 am
Location: Magrathean

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.
 
User avatar
erkexzcx
Member Candidate
Member Candidate
Topic Author
Posts: 264
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: 14
Joined: Tue Apr 03, 2018 11:05 am
Location: Netherlands

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: 3334
Joined: Sat Dec 24, 2016 11:17 am
Location: Magrathean

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.
 
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: 16
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).
 
zilexa
just joined
Posts: 16
Joined: Tue Apr 10, 2018 6:05 pm

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

Fri Jan 29, 2021 1:16 pm

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.

Sorry it really doesn't work:
  • Router on 192.168.88.1
  • I have a server/nas/workstation on 192.168.88.2.
  • No VLANs or other networks configured besides 192.168.88.0/24.
  • IP > DNS: a public DNS server (9.9.9.9) and Allow Remote Requests enabled.
  • IP > DHCP Server > Networks > 192.168.88.0/24 > 192.168.88.1 (the router itself).
  • chain=dstnat protocol=udp src-address=192.168.88.2 dst-port=53
  • 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
The short rule is placed above the long rule. They are at the top of my NAT list, below those two rules I only have a few port forwarding rules (to my server at 192.168.88.2). My Firewall rules are just the default rules. I am on RouterOS 6.48 stable.
 
zilexa
just joined
Posts: 16
Joined: Tue Apr 10, 2018 6:05 pm

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

Fri Jan 29, 2021 6:06 pm

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=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.
Ok so just as a test I added the masquerade rule, below the 2 rules you gave me:
add action=masquerade chain=srcnat src-address=192.168.88.0/24 dst-address-list=192.168.88.2 dst-port=53 protocol=udp
Now it works BUT Pihole sees all requests coming from my router. No statistics per client unfortunately.
Without this masquerade rule, no client can resolve domains unfortunately.

As soon as I disable the masquerade rule, it does not work anymore :(
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Tue Feb 09, 2021 5:38 pm

Hi,

I also had some problems here. My Pi-Hole is configured with unbound on Port 5335 to resolve from DNS-Rootservers.

The solution that works for me comes from another thread here: viewtopic.php?f=9&t=170487 and i changed some things according to my setup and some overthinking i've done.

Mysetup is:
RB2011iL: 192.168.0.1 configured with two external DNS Servers (1.1.1.1, 1.0.0.1)
Pi-Hole: 192.168.0.250
DHCP-Range: 192.168.0.0/24 and Pi-Hole as DNS

I added two NAT-Rules to grab every dns request and force it to use my configured server.
6 X  ;;; Mikrotik forced
      chain=dstnat action=dst-nat to-addresses=192.168.0.1 
      protocol=udp src-address=!192.168.0.1 
      dst-address=!192.168.0.1 in-interface=bridge dst-port=53 
      log=no log-prefix="" 

 7    ;;; pihole forced
      chain=dstnat action=dst-nat to-addresses=192.168.0.250 
      protocol=udp src-address=!192.168.0.250 
      dst-address=!192.168.0.250 in-interface=bridge 
      dst-port=53 log=no log-prefix="" 
To check pi-hole running state i have configured a scheduler task that resolves google.com every 5 minutes via pihole. If there's an error the pihole NAT-Rule would be disabled and the mikrotik would be enabled.
:local piholedown [/ip firewall nat get value-name=disabled [find comment="pihole forced"]]
:local piholeDNS "192.168.0.250"
:local testDomain "www.google.com"


:if ($piholedown = false) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
		/ip firewall nat;
			disable [find comment="pihole forced"];
			enable [find comment="Mikrotik forced"];
    		}
} else={
    :do {
        :resolve $testDomain server $piholeDNS;
		/ip firewall nat;
			enable [find comment="pihole forced"];
			disable [find comment="Mikrotik forced"];
    } on-error={}
}
In short the pi is my standard and only in case of error there is a forced dns redirection to the router with the external dns servers.

Maybe you could give it a try. (hopefully a successfull one)

As mentioned before, the initial idea came from this thread viewtopic.php?f=9&t=170487

Have a nice day!

PS: English is not my native language, so be careful while reading, it could be nonsense :)
 
zilexa
just joined
Posts: 16
Joined: Tue Apr 10, 2018 6:05 pm

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

Fri Feb 12, 2021 11:13 am

Mysetup is:
RB2011iL: 192.168.0.1 configured with two external DNS Servers (1.1.1.1, 1.0.0.1)
Pi-Hole: 192.168.0.250
DHCP-Range: 192.168.0.0/24 and Pi-Hole as DNS

I added two NAT-Rules to grab every dns request and force it to use my configured server.
6 X  ;;; Mikrotik forced
      chain=dstnat action=dst-nat to-addresses=192.168.0.1 
      protocol=udp src-address=!192.168.0.1 
      dst-address=!192.168.0.1 in-interface=bridge dst-port=53 
      log=no log-prefix="" 

 7    ;;; pihole forced
      chain=dstnat action=dst-nat to-addresses=192.168.0.250 
      protocol=udp src-address=!192.168.0.250 
      dst-address=!192.168.0.250 in-interface=bridge 
      dst-port=53 log=no log-prefix="" 
To check pi-hole running state i have configured a scheduler task that resolves google.com every 5 minutes via pihole. If there's an error the pihole NAT-Rule would be disabled and the mikrotik would be enabled.
:local piholedown [/ip firewall nat get value-name=disabled [find comment="pihole forced"]]
:local piholeDNS "192.168.0.250"
:local testDomain "www.google.com"


:if ($piholedown = false) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
		/ip firewall nat;
			disable [find comment="pihole forced"];
			enable [find comment="Mikrotik forced"];
    		}
} else={
    :do {
        :resolve $testDomain server $piholeDNS;
		/ip firewall nat;
			enable [find comment="pihole forced"];
			disable [find comment="Mikrotik forced"];
    } on-error={}
}
In short the pi is my standard and only in case of error there is a forced dns redirection to the router with the external dns servers.

Maybe you could give it a try. (hopefully a successfull one)

As mentioned before, the initial idea came from this thread viewtopic.php?f=9&t=170487

Have a nice day!

PS: English is not my native language, so be careful while reading, it could be nonsense :)
@Ddram thank you for posting this. Could you please confirm a few things?
1. the RouterOS version you are using
2. you only have 1 subnet/dhcp range right? So your pihole and your LAN clients are all in the same IP range.
3. In PiHole, do you see DNS requests and nice stats per client? Or does this solution mean PiHole will "see" all DNS requests coming from your router? Because I really want to be able to have per-client stats and I believe your solution works, but in PiHole it will look like you only have 1 client because all requests come from the router?
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Fri Feb 12, 2021 7:44 pm

Hi zilexa,

1. I'm on Version 6.48
2. Yes that's my small home setup only one subnet with everything in it.
3. Yes, i've read your previous postings and that's exactly what i want and have! ;) Every client calls the Pi with it's own fqdn. As an example, i can see my Mobilephone querying as "OnePlus7T.home.arpa" in pihole querys.

I think the Problem is the srcnat masquerading rule (someone mentioned this before).

With masquerading, every request seems top be sent from your Router. That's the opposit from what you want.

Greetings
 
zilexa
just joined
Posts: 16
Joined: Tue Apr 10, 2018 6:05 pm

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

Sun Feb 14, 2021 1:31 am

Hi zilexa,

1. I'm on Version 6.48
2. Yes that's my small home setup only one subnet with everything in it.
3. Yes, i've read your previous postings and that's exactly what i want and have! ;) Every client calls the Pi with it's own fqdn. As an example, i can see my Mobilephone querying as "OnePlus7T.home.arpa" in pihole querys.

I think the Problem is the srcnat masquerading rule (someone mentioned this before).

With masquerading, every request seems top be sent from your Router. That's the opposit from what you want.

Greetings
My point is, it should be impossible without the masquerade rule.
None of my clients are able to access any domains, with only the single rule you mention to force DNS to your pihole.
Are you using the default Firewall rules from 6.48? Do you have other NAT rules set up?
I asked this in a Dutch forum and they confirm it cannot work without the masquerade rule.
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Sun Feb 14, 2021 2:58 pm

Hi,

well I see it working every day since exactly one week ago.

Yes I have other nat rules active but none of them handles DNS traffic.

I split my rule with some explanation, maybe someone can correct me, where I'm wrong (or right).
Do
chain=dstnat (declare outgoing nat)
action=dst-nat (redirect for outgoing NAT)
to-addresses=192.168.0.250 (redirect to my pi)
to-ports=53 (to DNS port)

But only if:
protocol=udp (maybe TCP but mostly DNS is a udp thing)
And 
src-address=!192.168.0.250 (not from pi, so requests from pi could passthrough)
And
dst-address=!192.168.0.250 (no requests already sent to my pi)
And
in-interface=bridge (request is from local network)
And
dst-port=53 (if DNS port is used)

So every matching request is redirected to the pi. I can use 'ping' and 'dig' commands from my pi (via SSH) as much as I want, everything works as expected.

Maybe I'm wrong, but it's working.

Have a nice Sunday
 
zilexa
just joined
Posts: 16
Joined: Tue Apr 10, 2018 6:05 pm

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

Mon Feb 15, 2021 12:23 pm

So every matching request is redirected to the pi. I can use 'ping' and 'dig' commands from my pi (via SSH) as much as I want, everything works as expected.

Maybe I'm wrong, but it's working.

Have a nice Sunday
Would you mind posting the output of:
/ip firewall export
You can ofcourse remove all port forwarding rules of NAT.

In my case, I only use the default Mikrotik/RouterOS firewall rules:
/ip firewall filter
add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=invalid
add action=accept chain=input comment="defconf: accept ICMP" protocol=icmp
add action=accept chain=input comment="defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1
add action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=!LAN
add action=accept chain=forward comment="defconf: accept in ipsec policy" ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related
add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid
add action=drop chain=forward comment="defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface-list=WAN
/ip firewall nat
add action=dst-nat chain=dstnat comment=DNS-to-server-rule1 dst-address=!192.168.88.2 dst-port=53 in-interface=bridge protocol=udp src-address=!192.168.88.2 to-addresses=192.168.88.2 to-ports=53
add action=masquerade chain=srcnat comment=DNS-to-server-rule2 dst-address=192.168.88.2 dst-port=53 protocol=udp src-address=192.168.88.0/24
add action=masquerade chain=srcnat out-interface=pppoe-client
NAT only contains the 2 rules to force DNS to pihole. The very last rule is required for internet access as my proivider uses PPOE.
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Mon Feb 15, 2021 1:00 pm

Hi,

Here is my Firewall export, without lists and mangle rules.
/ip firewall filter
add action=drop chain=input comment="Winbox on WAN" dst-port=\
    8291 in-interface=pppoe-out1 log-prefix="winbox on wan " \
    protocol=tcp
add action=drop chain=forward comment=\
    "Drop incoming packets that are not NATted" \
    connection-nat-state=!dstnat connection-state=new \
    in-interface=pppoe-out1 log=yes log-prefix=!NAT
add action=drop chain=forward comment=" Drop  Invalid" \
    connection-state=invalid log-prefix=invalid
add action=drop chain=forward comment=\
    "Drop incoming from internet which is not public IP" \
    in-interface=pppoe-out1 log=yes log-prefix=!public \
    src-address-list=not_in_internet
add action=drop chain=input comment="Drop Wan2Lan DNS (TCP)" \
    dst-port=53 in-interface=pppoe-out1 protocol=tcp
add action=drop chain=input comment="Drop Wan2Lan DNS (UDP)" \
    dst-port=53 in-interface=pppoe-out1 protocol=udp
add action=drop chain=forward comment=\
    "Drop packets from LAN that do not have LAN IP" \
    in-interface=bridge log=yes log-prefix=LAN_!LAN \
    src-address=!192.168.0.0/24
add action=drop chain=forward comment="Firehol list" \
    connection-state=new disabled=yes dst-address-list=firehol
add action=accept chain=input comment=\
    "Allow established, related" \
    connection-state=established,related
add action=accept chain=input comment="Allow internal" \
    src-address-list=allowed_to_router
add action=fasttrack-connection chain=forward comment=\
    "FastTrack" connection-state=\
    established,related
add action=accept chain=forward comment="Established,  Related" \
    connection-state=established,related
add action=accept chain=forward comment=\
    "Forward Portmapping (Plex)" connection-nat-state=dstnat \
    dst-port=32400 in-interface=pppoe-out1 log=yes log-prefix=\
    "Forward Plex" protocol=tcp
add action=accept chain=forward comment="SIP forward" \
    connection-nat-state=dstnat log=yes log-prefix=SIP \
    src-address-list=SIP
add action=accept chain=forward comment="Zyxel Forward Rule" \
    dst-address=192.168.1.1 in-interface=bridge log=yes \
    log-prefix="Forward to Zyxel" out-interface=ether1 \
    src-address-list=allowed_to_router
add action=drop chain=forward comment=\
    " Drop  tries  to  reach  not public  addresses  from  LAN" \
    dst-address-list=not_in_internet in-interface=bridge \
    log-prefix=!publich_from_LAN out-interface=!bridge
add action=drop chain=input comment="Drop everything" \
    in-interface=pppoe-out1 log-prefix=dropped
and the NAT part:
/ip firewall nat
add action=dst-nat chain=dstnat comment=\
    "SIP Connection forward 3478 to FB7590 (UDP)" \
    connection-type=sip dst-port=3478 in-interface=pppoe-out1 \
    log=yes log-prefix="UDP(5060)" protocol=udp \
    src-address-list=SIP to-addresses=192.168.0.254 to-ports=\
    3478
add action=dst-nat chain=dstnat comment=\
    "SIP Connection forward 5060 to FB7590 (UDP)" \
    connection-type=sip dst-port=5060 in-interface=pppoe-out1 \
    log=yes log-prefix="UDP(5060)" protocol=udp \
    src-address-list=SIP to-addresses=192.168.0.254 to-ports=\
    5060
add action=dst-nat chain=dstnat comment=\
    "SIP Connection forward 5060 to FB7590 (TCP)" dst-port=5060 \
    in-interface=pppoe-out1 log=yes log-prefix="TCP(5060)" \
    protocol=tcp src-address-list=SIP to-addresses=\
    192.168.0.254 to-ports=5060
add action=dst-nat chain=dstnat comment=\
    "SIP forward to FB7590 only 1and1-IPs" in-interface=\
    pppoe-out1 log=yes log-prefix="UDP(CALL)" protocol=udp \
    src-address-list=SIP to-addresses=192.168.0.254 to-ports=\
    7077-7110
add action=dst-nat chain=dstnat comment="Plex forward to 32400" \
    dst-port=24179 in-interface=pppoe-out1 log=yes log-prefix=\
    Plex protocol=tcp to-addresses=192.168.0.31 to-ports=32400
add action=dst-nat chain=dstnat comment="PS4 Forward" disabled=\
    yes dst-port=3074 in-interface=pppoe-out1 protocol=udp \
    to-addresses=192.168.0.18 to-ports=3074
add action=dst-nat chain=dstnat comment="Mikrotik forced" \
    disabled=yes dst-address=!192.168.0.1 dst-port=53 \
    in-interface=bridge protocol=udp src-address=!192.168.0.1 \
    to-addresses=192.168.0.1
add action=dst-nat chain=dstnat comment="pihole forced" \
    dst-address=!192.168.0.250 dst-port=53 in-interface=bridge \
    protocol=udp src-address=!192.168.0.250 to-addresses=\
    192.168.0.250 to-ports=53
add action=masquerade chain=srcnat comment=\
    "Outbound to Zyxel for Configuration" dst-address=\
    192.168.1.1 out-interface=ether1
add action=masquerade chain=srcnat comment=\
    "Outgoing NAT for WAN" dst-address-list=!not_in_internet \
    out-interface=pppoe-out1
I hope there's something that could help, but i don't see anything related. Maybe there's some difference in your other dns related configuration (pihole or router)?

Here is mine from the router :
/ip dns
set allow-remote-requests=yes cache-max-ttl=12h servers=1.1.1.1,1.0.0.1
How is your pihole configuration?

Greetings
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Mon Feb 15, 2021 8:48 pm

Hello again,

I did some testing and reconfiguration on my setup, because I was interested, what's wrong on your site.

Guess what happened? Well it doesn't work anymore...

Never touch a running system, I guess....

So I think I was wrong all the time. Maybe someone with more networking experience finds a way.

Until then I will use the solution from the thread I've posted, because it's not DHCP TTL dependent.

Have a nice evening.
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Thu May 06, 2021 1:37 pm

These are the command that are added:
/ip dhcp-server network

add address=192.168.88.0/24 dns-server=192.168.88.5 gateway=192.168.88.1 netmask=24

add address=192.168.88.5/32 dns-server=192.168.88.1 gateway=192.168.88.1 netmask=24
For fallback I modified the script and need some help, whether its written in right order or wrong. I am confused about this line
 [/ip dhcp-server network address=192.168.88.0/24 comment=defconf get dns-server]
, and the script formatting. This line doesn't worked for me
:local currentDHCPDNS [/ip dhcp-server network print count-only where dns-server=$piholeDNS
]. How do I get dns server status from dhcp server network?
where dns-server
probably cause issue because I have another entry which has 192.168.88.5 as address in dhcp networks.
:local currentDNS [/ip dhcp-server network address=192.168.88.0/24  comment=defconf get dns-server]
:local piholeDNS "192.168.88.5"
:local testDomain "www.google.com"

:if ($currentDNS = $piholeDNS) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
        /ip dhcp-server network set 0 address=192.168.88.0/24 dns-server=$piholeDNS comment=defconf dns-none=yes gateway=192.168.88.1 netmask=24
    }
} else={
    :do {
        :resolve $testDomain server $piholeDNS
        /ip dhcp-server network set 0 address=192.168.88.0/24 dns-server=$piholeDNS comment=defconf gateway=192.168.88.1 netmask=24
    } on-error={}
}
Any help will be very much helpful.
 
zilexa
just joined
Posts: 16
Joined: Tue Apr 10, 2018 6:05 pm

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

Wed Jun 30, 2021 12:39 am

The definitive version, in case anyone is searching for it. Note most scripts above lack a space or two, making them incorrect.

With the below, you will get the following:
1. ALWAYS force dns requests to go either via your server (AdGuard Home or PiHole or Unbound etc) OR the public fallback DNS servers configured in your router (blocking Amazon devices, Google devices, smartTVs using their own dns server for tracking & ads).

HOW-TO:
  1. In IP > DHCP Server > Networks, set DNS to the same address as the router: 192.168.88.1
  2. In IP > DNS set your preferred fallback DNS servers, for example AdGuard DNS: 94.140.14.14 and 94.140.14.15.
  3. Now go to TERMINAL and type (without arrows) < /ip firewall nat >, hit ENTER then enter the folowing 3 rules (no typos!) and hit enter after each one:
    1. add action=dst-nat chain=dstnat comment=force-own-DNS1 dst-address=!192.168.88.2 dst-port=53 in-interface=bridge protocol=udp src-address=!192.168.88.2 to-addresses=192.168.88.2 to-ports=53
    2. add action=masquerade chain=srcnat comment=force-own-DNS2 dst-address=192.168.88.2 dst-port=53 protocol=udp src-address=192.168.88.0/24
    3. add chain=dstnat action=dst-nat comment=force-router-DNS to-addresses=192.168.88.1 protocol=udp src-address=!192.168.88.1 dst-address=!192.168.88.1 in-interface=bridge dst-port=53
The first 2 NAT rules are required to force your server DNS, the 3rd NAT rule is required to force the DNS servers that are configured in IP / DNS:

Finally, in System > Scripts, create the following script with name: DNS-fallback:
:local serverIP "192.168.88.2"
:local testDomain "www.google.com"
:do {
     :resolve $testDomain server $serverIP
      /ip firewall nat;
          enable [find comment="force-own-DNS1"];
          enable [find comment="force-own-DNS2"];
          disable [find comment="force-router-DNS"];
    } on-error={
                /ip firewall nat;
                    enable [find comment="force-router-DNS"];
                    disable [find comment="Force-own-DNS1"];
                    disable [find comment="Force-own-DNS2"];
               }
    }
In System > Scheduler: add a new one, use the name of your script (DNS-fallback) and set interval to 10 seconds (to test).
Go to IP > Firewall > NAT, disable the 2 'force-own-DNS' rules, enable the 'force-router-DNS' rule, wait max 10 seconds. If your server is up and running, the 2 rules should be enabled and the third rule disabled.

Go back to scheduler and change the interval to 1:00 (every minute, should be enough).


Remaining issue: since we need a masquerade rule, we cannot see clients in AdGuard Home or PiHole. Which means you cannot disable blocking per client or set rules per client :(
To solve this, I understand your server should be in a different subnet (IP > DHCP Server > Networks). I tried creating a seperate subnet, changed the static lease of the server IP to reflect the change, refreshed my server network connection etc. But I didn't have internet access, couldn't access the router from the server. Or the clients couldn't access anything on the server.
If anyone has NOOB instructions how to solve this, please share!
Last edited by zilexa on Tue Apr 18, 2023 3:53 pm, edited 3 times in total.
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Wed Jun 30, 2021 8:54 pm

Hi zilexa,

I've found another Thread, started by shafiqrahman at viewtopic.php?p=858144 .

It took me about 2 hours today, to get a second pihole running, with this configuration, for testing purpose. i used information from post #5 and #20, except the part with upnp.

I keep it running until the weekend, and if everything works well, i will move my normal setup (pihole with huge filterlists and unbound) into the second subnet. Until now everything seems to works as we want it to, especially that part with clientnames.

If you have any problems i will try to help you ( maybe this time with some success ;))

greetings
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Wed Jun 30, 2021 10:56 pm

@Ddram,
Will you please share the unbound functionality or usage here? To my understanding unbound kinda unnecessary because mikrotik already act as a dns cache. If not I am interested too. Also, please let us know your test result with the new setup. Any update/issue will be highly appreciated. :D
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Thu Jul 01, 2021 8:57 pm

@shafiqrahman,

thanks for your work in the other thread, and all the contributors there. You've achived what many people are searching for ( noobs like me of course :) ).

One day i found pihole for ad/tracker/phishing/malware blocking and there was a tutorial for using unbound as local dns-resolver and caching the root-dns-zone ( it's called "hyperlocal" ), so i gave it a try. Basically i liked the idea to query on a direct way and not be dependend from ISP, Google or Quad9 etc. - dns servers. Another point was that unbound does some cache refresh for often requested domains, so there is a little speedup.

Just for clarification, i'm a noob with about 20 years of experience and it's mostly a thing of "I do it, because i can and maybe i'm learning something new". My actual plan is to keep pihole/unbound running and have the mikrotik dns as failover.

Until now (about 28hours) everything works very well. The alternativ subnet was the solution (i guess it was mentioned in other posts, but i couldn't figure out how to do).

Greetz :)
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Fri Jul 02, 2021 3:55 am

viewtopic.php?f=13&t=175322&p=858329#p858329
This link might help you. Basically, all ethernet ports are attached to a bridge. You detach your desired ethernet port from that bridge. Make a DHCP server for that port,add ip addresses and define ip pool. Also there is a video on YouTube by Tksja , https://youtu.be/6G6dWF1nipY
Here is the break down of subnet creation:
Remove the desired port from the default bridge(for my case its ether5):
/interface bridge port remove [find interface="ether5"]
This portion is firewall dependent, my firewall requires that it should be in "LAN"
/interface list member add interface=ether5 list=LAN
Now, Give Ip address to that ethernet port.
/ip address 
add address=192.168.188.1/24 comment=pinet interface=ether5 network=192.168.188.0
Assign an IP range for the subnet.
/ip pool
add name=pinet ranges=192.168.188.20-192.168.188.40
Add a dhcp server for that newly created subnet and dhcp server network.
/ip dhcp-server
add address-pool=pinet disabled=no interface=ether5 name=pinetDHCP
/ip dhcp-server network
add address=192.168.188.0/24 comment=pinet gateway=192.168.188.1 netmask=24
If you need more clarification or help, please post on the above mentioned thread, there are other more advance/experienced members who might help :D
 
Ddram
just joined
Posts: 19
Joined: Mon Feb 08, 2021 7:56 pm

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

Sun Jul 04, 2021 3:46 pm

Hi,

everything is fine. It's running since wednesday and i switched my original pihole setup to the second subnet yesterday.

There was a little problem, because you have to run "pihole -r" to reconfigure the pi with the new ip and gateway. The problem is, that something is messed up with this routine. The gateway doesn't change. I had to open "/etc /dhcpcd.conf" and there where both configurations. I deleted the old one, did a reboot and now everything works as expected.

In the pihole adminpage i had to keep my original subnet and gateway to have nameresolution for my clients.

In short:
Pihole is in 192.168.3.0/24 with 192.168.3.1 as gateway
My clients are in 192.168.0.0/24 and get recognized from the pi

Thanks again :)
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Sun Jul 04, 2021 9:09 pm

I use pihole inside a container. But, glad it worked for you.
 
teonok
just joined
Posts: 2
Joined: Tue May 12, 2020 2:15 pm

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

Thu Jul 29, 2021 11:19 am

When you put pithole server on different subnet what changes you make on firewall rules?
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Thu Jul 29, 2021 11:27 am

 
eb123456
just joined
Posts: 23
Joined: Sat Jul 24, 2021 6:20 am
Location: California

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

Sat Aug 14, 2021 7:42 pm

:resolve $testDomain server $piholeDNS
This seems to resolve against the mikrotik cache, therefore introducing a delay in detection of a pihole outage.
How do we skip the cache for this particular request?
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Sat Aug 14, 2021 10:02 pm

Most probably not. Not sure about that, but it worked perfectly for me. Try disabling your wan port and see what happens.
 
eb123456
just joined
Posts: 23
Joined: Sat Jul 24, 2021 6:20 am
Location: California

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

Sun Aug 15, 2021 10:04 pm

what do you mean
most probably not
?
 
pe1chl
Forum Guru
Forum Guru
Posts: 10512
Joined: Mon Jun 08, 2015 12:09 pm

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

Sun Aug 15, 2021 10:49 pm

Actually, when you want to do things like this you should look at the possibilities of "IP anycast routing".
You can add another IP address to the Pi (it would be possible without that but it would have some disadvantages) and then you can add a route to that address with "ping" check enabled. So the route will disappear as soon as the ping fails.
Then, you also add another route to the same address with a greater distance to the alternative you want to use for the service. In this case it would be a route via the default gateway.
And, you in this case also need to setup a dst-nat to map that address to the DNS service you want to use instead (e.g. 1.1.1.1)

Now, your DNS settings are set to the anycast address on all systems (e.g. via DHCP).
Normally the DNS requests will go to the configured address and are routed to the Pi, but as soon as the Pi does not respond to ping anymore that route will get disabled, the next one takes over, and it will process the traffic.
You can also have multiple servers. E.g. when you have a larger network, where you use BGP or OSPF to route the traffic, you can have multiple places in the network where traffic for that anycast address is routed to a local server. As soon as the server fails, the route disappears, BGP/OSPF will no longer distribute it, and another route to another place in the network where you have this address configured will take over.

Very powerful concept for such failovers... and of course the big players use this all the time, e.g. to provide the service for 1.1.1.1 or 8.8.8.8.
 
eb123456
just joined
Posts: 23
Joined: Sat Jul 24, 2021 6:20 am
Location: California

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

Mon Aug 16, 2021 5:12 am

ok thank you this is definitely very informative. I was wondering how 1.1.1.1 and 8.8.8.8 could work with the `static` IP.
Any chance you can give me a bit more detail to set it up though? I am a beginner with both mikrotik and pihole.
Thanks!
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Mon Aug 16, 2021 12:49 pm

what do you mean
most probably not
?
To me, the only thing I needed is to determine whether pihole is up or down. That , what the script does. It only checks whether pihole can resolve or not, then change accordingly. For instances , when the internet is down it also change the route through the router.
 
mndtrp
just joined
Posts: 3
Joined: Thu Feb 16, 2023 6:26 pm

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

Sat Apr 01, 2023 11:01 am

Hi all,

Thought I'd share my version of this script.

It's essentially the same, but it uses arrays. And this way you can have multiple pihole and backup DNS servers.
It also excludes DHCP networks that have "Exclude" as comment.
It will not update anything if there is no change.
Remove comments to get verbose output.
    :local currentDNS [/ip dns get server]
    :local dnsup [ :toarray "" ];
    :local piholeDNS {"192.168.x.15";"192.168.x.26"}
    :local backupDNS {"192.168.x.1";"192.168.x.254"}
    :local testDomain "www.google.com"

    :foreach i in $piholeDNS do={
        # :put $i
        :do {
            :resolve $testDomain server $i
            :set dnsup ( dnsup, $i );
        } on-error={
            # :put "$i error"
        }
    }
    :if ([:len $dnsup] > 0) do={
            # :put "$dnsup"
            if ($currentDNS=$dnsup) do={
                # put ("DNS no change")
            } else {
                /ip dns set servers $dnsup
                /ip dhcp-server network set [ find comment!="Exclude" ] dns-server=$dnsup;
            }
        } else={
            # :put "$dnsup"
            if ($currentDNS=$backupDNS) do={
                # put ("DNS no change")
            } else {
                /ip dns set servers $backupDNS
                /ip dhcp-server network set [ find comment!="Exclude" ] dns-server=$backupDNS;
            }
        }
    # :put "$currentDNS"
    # :put "$dnsup"
Last edited by mndtrp on Sat Apr 01, 2023 11:05 am, edited 1 time in total.
 
User avatar
baragoon
Member
Member
Posts: 365
Joined: Thu Jan 05, 2017 10:38 am
Location: Kyiv, UA
Contact:

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

Tue Apr 04, 2023 9:15 am

Why not to use a VRRP (keepalived) for VIP address and when PI is down this IP will move to router and when PI is back will move back to PI.
Assign VIP to your clients via DHCP server.
 
mndtrp
just joined
Posts: 3
Joined: Thu Feb 16, 2023 6:26 pm

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

Tue Apr 04, 2023 12:25 pm

Thank you for the suggestion!
Took a look at VRRP and it looks cool, but I dont think this alone will improve the solution.
Because the PI / Pi-hole might be up, but DNS queries still fail for x-y-z reason.
Querying DNS ensures the actual service is tested, not just IP availability.

But I do have multiple inet egress points and I can use VRRP to check and failover based on this availability. That is definitely an improvement. :)
 
User avatar
baragoon
Member
Member
Posts: 365
Joined: Thu Jan 05, 2017 10:38 am
Location: Kyiv, UA
Contact:

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

Tue Apr 04, 2023 3:06 pm

keepalived on raspi can use scripts for checks and lower the prio or transit to BACKUP state
 
Luckysh0t
just joined
Posts: 2
Joined: Wed Apr 05, 2023 12:07 pm

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

Wed Apr 05, 2023 3:39 pm

Depending on lease time, DNS will not update instantly for all clients, but allows Pi-Hole to show what uses it:
Is it possible to tell the dhcp server in the router os to renew all leases ? If so, the change should be asap - regardless of lease time or im wrong ?

Nasty way would be, to disable the dhcp server for seconds and enable it again.. xD

Greetings

Lucky
 
pe1chl
Forum Guru
Forum Guru
Posts: 10512
Joined: Mon Jun 08, 2015 12:09 pm

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

Thu Apr 06, 2023 11:14 am

Depending on lease time, DNS will not update instantly for all clients, but allows Pi-Hole to show what uses it:
Is it possible to tell the dhcp server in the router os to renew all leases ? If so, the change should be asap - regardless of lease time or im wrong ?

Nasty way would be, to disable the dhcp server for seconds and enable it again.. xD
No. DHCP has no "push" function and there is nothing you can do in the DHCP server.
It could work to disconnect all clients (shut down the WiFi and all the ethernet ports on the router and/or switches and bring it back up).
But even that is not guaranteed, not all clients re-request a DHCP lease when the network is down/up. But nowadays, most of them do.
 
zilexa
just joined
Posts: 16
Joined: Tue Apr 10, 2018 6:05 pm

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

Tue Apr 18, 2023 3:55 pm

I have this running for 2 years now, works very well. Never had to look back and when my server reboots, I can see the first 2 NAT rules being disabled and the 3rd one enabled, ensuring DNS goes via router configured DNS servers.
 
chinmi
just joined
Posts: 1
Joined: Tue Oct 17, 2023 10:01 am

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

Tue Oct 17, 2023 10:12 am

Hi all,

Thought I'd share my version of this script.

It's essentially the same, but it uses arrays. And this way you can have multiple pihole and backup DNS servers.
It also excludes DHCP networks that have "Exclude" as comment.
It will not update anything if there is no change.
Remove comments to get verbose output.
    :local currentDNS [/ip dns get server]
    :local dnsup [ :toarray "" ];
    :local piholeDNS {"192.168.x.15";"192.168.x.26"}
    :local backupDNS {"192.168.x.1";"192.168.x.254"}
    :local testDomain "www.google.com"

    :foreach i in $piholeDNS do={
        # :put $i
        :do {
            :resolve $testDomain server $i
            :set dnsup ( dnsup, $i );
        } on-error={
            # :put "$i error"
        }
    }
    :if ([:len $dnsup] > 0) do={
            # :put "$dnsup"
            if ($currentDNS=$dnsup) do={
                # put ("DNS no change")
            } else {
                /ip dns set servers $dnsup
                /ip dhcp-server network set [ find comment!="Exclude" ] dns-server=$dnsup;
            }
        } else={
            # :put "$dnsup"
            if ($currentDNS=$backupDNS) do={
                # put ("DNS no change")
            } else {
                /ip dns set servers $backupDNS
                /ip dhcp-server network set [ find comment!="Exclude" ] dns-server=$backupDNS;
            }
        }
    # :put "$currentDNS"
    # :put "$dnsup"
thank you, this is what i need since i also used 2 dns servers.
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Mon Nov 06, 2023 12:51 pm

I have been using this script science for two years without any issues:
:local piholeDown [/ip firewall nat print count-only where comment~"pihole_bypass" && disabled]
:local piholeDNS "192.168.188.25"
:local testDomain "www.google.com"

:if ($piholeDown > 0 ) do={
    :do {
        :resolve $testDomain server $piholeDNS
    } on-error={
        /ip firewall nat enable [find comment=pihole_bypass];
    }
} else={
    :do {
        :resolve $testDomain server $piholeDNS
        /ip firewall nat disable [find comment=pihole_bypass];
    } on-error={}
}
But, recently I have noticed that every few hours the script failed to resolve the dns using pihole, resulting ads being leaked. What I meant is that the script failed to resolve dns so it enables the nat rules (that bypasses the pihole) and on the next run (45sec intervals) its returns back to normal. So, to resolve that issue I took some help from chatgpt. Though, it didn't give me a full working script it gave me some nice ideas. Due to my little to no experience in scripting I couldn't make it work. Any help will be highly appreciated.
# Configuration Parameters
:local scriptVersion "1.0"
:local piholeDown [/ip firewall nat print count-only where comment~"pihole_bypass" && disabled]
:local piholeDNS "192.168.188.25"
:local testDomains {"www.google.com", "www.example.com", "www.example.org"}
:local retries 3
:local timeoutSeconds 3

# DNS Resolution Function
:local resolveDNS = {
    :local domain $1
    :local success false
    
    :do {
        :local attempt 0
        :while ($attempt < $retries && $success = false) do={
            :set attempt ($attempt + 1)
            
            :do {
                :resolve $domain server $piholeDNS timeout $timeoutSeconds
                :set success true
                :log info ("$scriptVersion: Successfully resolved $domain to $piholeDNS on attempt $attempt")
            } on-error={
                :log error ("$scriptVersion: Attempt $attempt: Failed to resolve $domain to $piholeDNS")
            }
        }
    }
    
    :if ($success = false) do={
        :log error ("$scriptVersion: All $retries attempts failed to resolve $domain to $piholeDNS. Enabling pihole_bypass.")
        :if ($piholeDown > 0) do={
            /ip firewall nat enable [find comment~"pihole_bypass"];
        } else={
            /ip firewall nat disable [find comment~"pihole_bypass"];
        }
    }
    
    :if ($success = true) do={
        :log info ("$scriptVersion: DNS resolution for $domain was successful")
    }
}

# Main Loop
:foreach testDomain in=$testDomains do={
    $resolveDNS($testDomain)
}
This script has configuration parameters so there is no need to change the whole script and has multiple servers to resolve.
Last edited by shafiqrahman on Mon Nov 06, 2023 3:16 pm, edited 1 time in total.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12444
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

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

Mon Nov 06, 2023 2:41 pm

So, to resolve that issue I took some help from help chatgpt.
Where is the help? I see only s–t.
 
shafiqrahman
Member Candidate
Member Candidate
Posts: 134
Joined: Wed Apr 12, 2017 1:42 am

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

Mon Nov 06, 2023 3:15 pm

:lol: yeah you are right. Back then don't have a computer. It's kinda entertaining but like the concept. Btw, how are you? Been a long time :D
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12444
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

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

Mon Nov 06, 2023 3:17 pm

I thank you sincerely, I'm fine, I hope you are too
 
Volui
just joined
Posts: 1
Joined: Wed Jun 28, 2023 1:22 pm

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

Fri Oct 25, 2024 1:53 pm

This script works for me like a charm for a 2 years without any issues:
: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={}
}
But unfortunately, not long ago my connection to the server "$piholeDNS" started to work unstable and because of this the script started to switch cyclically between "$piholeDNS" and "$backupDNS". I am an absolute zero in programming but still I tried to modify the script so that before changing the server (from the main to the backup and back) it would first make sure of its long-term availability (successful attempt of resolving at least 3 times in a row). I tried to add variables like ":local maxAttempts 3" and ":local successCount" ":local failureCount" and other similar things, but since I do not understand anything about programming (the maximum I can understand is not a very complex script, like the one suggested by the author of the topic) naturally nothing worked for me. Maybe someone already has a solution on how to modify the script so that it makes sure of the long-term availability (and vice versa, UNavailability) of the server before switching?

I'll answer myself. It turns out that RouterOS has such a wonderful thing as Netwatch! With it, you can set up host availability monitoring of almost any complexity!
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 4135
Joined: Sun May 01, 2016 7:12 pm
Location: California
Contact:

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

Fri Oct 25, 2024 10:21 pm

I'll answer myself. It turns out that RouterOS has such a wonderful thing as Netwatch! With it, you can set up host availability monitoring of almost any complexity!
Yup, also in 7.16 there is a direct netwatch for type=dns — which make this even simpler:
:global primary 172.17.0.2
:global backup 9.9.9.9
:global lookup www.mikrotik.com
/tool netwatch add type=dns dns-server=$primary record-type=A host=$lookup \
     down-script="/ip/dns/set server=$backup" \
     up-script="/ip/dns/set server=$primary"

Who is online

Users browsing this forum: No registered users and 15 guests