Pihole Local DNS Records synchronized from Active Directory
If you use Pi-hole in your home network, and you should, the local DNS provided by Pi-hole is a great way to house DNS services for your home network. However, do you have a home lab environment running Microsoft Windows Server DNS servers? This is what I am running in the home lab for domain services, internal name resolution for the lab side of my network, and other Microsoft-oriented services. While the Pi-hole DNS features provide great functionality, it is still fairly basic for some of my other integrations using Microsoft Windows Server DNS. Have you ever wished you could synchronize your Pihole local DNS with your Active Directory DNS server? I want to show you guys a way to get Pinhole local DNS records synchronized from Active Directory and why you may want to do this.
Pihole local DNS capabilities
Pi-hole provides a good range of DNS capabilities, including a Local DNS server that provides the ability to create local records and serve these records to clients for name resolution. Why do this? This serves the purpose of allowing you to create custom DNS records that you want to resolve in your home network, or if you are running a home lab network (home network on steroids) that you want to serve out DNS.
Pi-hole has what is known as a Conditional Forwarder that allows forwarding DNS requests to a custom DNS server value outside of your upstream. How does this work?
Let’s say you have a domain called mydomain.com that you want to resolve internally or externally with a specific nameserver that holds the records for that domain. With the Pi-hole conditional forwarder value, it will send requests for that specific domain to a specific DNS server, instead of the usual forwarding DNS servers, such as Cloudflare, Google, etc.
On the Pi-hole DNS settings page, if you scroll down under the Advanced Settings, you will see the conditional forwarding option to specify the DNS server and the domain name you want to conditionally forward to.
This is a great feature that allows forwarding requests in the situation I laid out in the outset, where you may have another DNS server that is a primary home lab DNS server and you want to forward your DNS requests to mylab.local or whatever the domain is to your internal Windows DNS Server.
But in my case, I wanted to do something a little bit different. I want to synchronize the DNS records within the Windows Server DNS server database, stored in Active Directory to the local DNS database on my Pi-hole server. What is the use case for doing this?
Pihole Local DNS Records synchronized from Active Directory
First, you may want to know why I want to do this, or maybe you have searched for this same topic and hopefully landed on this blog post. For me, it is for resiliency purposes to have an extra set of my DNS records stored outside my virtual environment. Synchronizing from Active Directory to my Pi-hole server(s) accomplishes the following:
- It gets all the records stored in my Active Directory Domain Controller database outside of my virtual environment
- It allows me to still utilize the Dynamic DNS registration capabilities of Windows Server DNS to allow clients/servers to register their records automatically in Windows Server DNS stored in Active Directory
- It provides a proxy if you will of DNS requests from my “insecure” LAN side from hitting my lab-side Windows DNS server – Clients will instead be hitting Pi-hole to resolve internal resources
- If my virtual environment goes down I have a physical Pi-hole outside my virtual environment that is still up and running and providing DNS
- It is, well, cool to do – maybe the most important reason ๐
Overview of resilient homelab architecture
Below is a high-level overview of what I have designed for my home lab environment to ensure that DNS is resilient. So, what is pictured below?
- VMware vSphere lab – 3 node vSAN cluster running various workloads, including Active Directory Domain Services (AD DS) DNS server
- Ubuntu 20.04 Virtual Machine – Running Pihole
- Various other server and client virtual machines
- Client computer – physical client accessing both homelab resources and normal home network services (Internet, video streaming, etc.
- Physical Raspberry Pi4 – Running Secondary Pihole server
I wanted to expand having all my eggs in one basket with DNS resources in the home lab infrastructure. There have been a couple of times when I had a hardware failure or some other issue that took down my vSAN cluster. There have also been a couple of instances where I had my domain controller (running DNS) go down.
While it is best practice to run multiple domain controllers, I don’t do this in the home lab. Why? To save resources, I limit core services to the bare minimum. Also, I backup my domain controller using a backup solution that I can restore in the worst-case scenario, which actually is made easier by having only one (no complexities of AD replication to deal with when restoring).
By bringing a physical Raspberry Pi outside the virtual cluster, it provides a great option to maintain DNS records in case of a failure of the virtual infrastructure, taking down the Window Server DNS server and the virtual Pihole instance. It also gives me the option to add the physical Pihole server as a secondary DNS server for continuing DNS resolution until the Windows Server is back online.
But, as mentioned earlier, the problem I saw was that I could only conditionally forward to the Windows Server, not the other direction. However, I wanted the ability to have the records from Active Directory DNS available on my Pihole machines.
Script to dump the Active Directory DNS records and copy to Pihole
So, what I have done to solve the issue in my home network is a simple PowerShell script that does the following:
- Dumps the DNS entries from the Active Directory database to a file
- Strip the file of any blank lines
- The file is SCPed by PowerShell to my primary Pihole server
- A cron job runs and copies entires from the uploaded file to the custom.list file in etc/pihole/ directory
- It restarts the DNS server in Pihole (a quick process)
- GravitySync synchronizes the DNS entries between the primary Pihole server and the secondary Pihole server.
There is a lot of room to clean up the script, make it better, and improve and streamline the process. However, the first part of the process is the PowerShell script. Below note the following:
- Variables are set defining the file name, domain name, password (SCP purposes), and the connection string. Note dnscopy is a nonsudo, underprivileged user I created, since I have the password embedded in the file
- The PowerShell Get-DnsServerResourceRecord cmdlet dumps the DNS entries to the file specified
- The file is then copied over to the Pihole server
You can clone the code below from Github:
$filename = "c:\custom.list"
$domain = 'mydomain.local'
$scppw = 'password'
$piholeconnect = '[email protected]:/home/dnscopy/'
#Run the DNS command to export entries to a file
Get-DnsServerResourceRecord -ZoneName $domain | where-object {$_.HostName -like "*.$domain" -and $_.Hostname -notlike "_*"} | select @{n='IP';E={$_.recorddata.IPV4Address}}, hostname | ft -HideTableHeaders | Out-File $filename
#Trim blank lines from the resulting file
(gc $filename) | ? {$_.trim() -ne "" } | set-content $filename
#Copy the exported DNS entries to Pihole
Start-Process 'C:\Program Files\PuTTY\pscp.exe' -ArgumentList ("-scp -pw $scppw $filename $piholeconnect")
Then on the Pihole server, the simple shell script copies the contents of the uploaded custom.list file to the same file in the /etc/pihole directory. It restarts the Pihole DNS server to make the entries active. This can be scheduled with a CRON job to coincide with the upload of the DNS entries from Windows Server DNS.
#!/bin/sh
#Overwriting the custom.list file with imported Windows DNS entries
cat /home/dnscopy/custom.list > /etc/pihole/custom.list
#Restart the Pihole DNS service
pihole restartdns
Room for improvement
This is a very crude implementation and there is much room for improvement. Realistically, the script from the Windows Server DNS server could drive the whole process, without the need for the CRON job. However, in my rush to bang out the script, I didn’t want a high-level permissions account to exist in my script file need to write files to /etc/. My plan is to pull this eventually from Hashicorp Vault and I can do everything in one fell swoop from the first script.
In the meantime, the low permissions account just uploads the file to the home directory, then the root account picks up the file from the CRON job and overwrites the entry in the custom.list file used for custom DNS entries and restarts Pihole DNS.
***Note*** – Using this approach, the custom.list entries do not show up in the GUI of Pihole. However, it does honor the entries in the file in my testing by simply adding DNS entries to the custom.list.
Video showing the process and how it works
Final Thoughts
Let me know what you guys think? I am thinking there may be others out there who want to do what I am doing in the homelab and can benefit from the script. What are you guys doing to make your home network/homelab DNS resilient? Hopefully, this will spark an interesting discussion in the comments section below. I am hoping as well to put together a video describing the details soon, so stay tuned.