Cyber Defense

Windows DNS Server Sinkhole Domains Tool

This article shows you how to use a free PowerShell script to manage sinkhole DNS domains using Microsoft's Windows Server DNS. The script is easy to use and can handle tens of thousands sinkhole DNS domains on local or remote Windows DNS servers. This is a script we use in the Securing Windows and PowerShell Automation course (SEC505) at SANS conferences. To get the script, download the SEC505 scripts zip file and look in the \Day6-Servers\DNS folder of that zip file.

Note: And here is a different PowerShell script to manage sinkhole names in the HOSTS file instead.


DNS servers resolve names, like "", to IP addresses. But there are fully-qualified domain names (FQDNs) which we do not want our users to successfully resolve, e.g., the names used for malware, spyware, phishing, scams, pornography, hate groups, bandwidth-wasting video sites, social networking sites unrelated to work, etc.

Most organizations have a "split DNS" architecture where the organization's internal DNS servers forward all their Internet name resolution requests to one or a few of their external DNS servers. The external DNS servers are usually located in the DMZ of the firewall. Only the external DNS servers can communicate with the outside world. The internal DNS servers must forward the requests they can't resolve themselves to the external DNS servers.

On the external DNS servers you can create primary zones for the domain names and FQDNs you do not want your users to resolve correctly. These DNS zones will all return an incorrect IP address, such as "" or the address of an internal server, not the real address. Because the organization's internal DNS servers are configured to forward their requests to these external DNS servers in the DMZ, the internal DNS servers will cache these incorrect addresses too when the external DNS servers respond. So, when an internal client tries to resolve an unwanted DNS name, it will receive a response, but the IP address returned will be incorrect. Because an IP address of "" is unreachable, these unwanted zones created on the external DNS servers are said to be "blackholed", "sinklisted" or "blocklisted".

What to block? You can obtain lists of FQDNs and domain names to sinkhole for free. Some lists are only for malware, others might be just for pornography, but be aware that they are never 100% complete or accurate (you get what you pay for, so don't be surprised to find gaps a small number of false positives).

Some of the more popular sinkhole lists include (in no particular order):

From sites like the above you can download lists of FQDNs and simple domain names which can be fed into the PowerShell script for this article in order to create sinkhole zones on Windows DNS servers. If you have DNS servers running BIND, perhaps on Linux or BSD, then the sites above will also help you import sinkhole domains on those DNS servers too (scripts for sinkholing on BIND are common).


To use the PowerShell DNS sinkhole script (download it here), you must:

  • Have PowerShell 2.0 or later on the computer where the script will be run, which may be the DNS server itself or another management workstation.
  • Use Windows Server 2003 with SP2 or later for the DNS server.
  • Allow network access to the RPC ports of the Windows Management Instrumentation (WMI) service from the workstation where the script will be run.
  • Be a member of the local Administrators group on the DNS server.

Example Uses

To see the script's command-line options (don't forget the ".&#92" before the script name):

Sinkhole-DNS.ps1 /?

get-help -full Sinkhole-DNS.ps1

To sinkhole "" by making it resolve to "":

Sinkhole-DNS.ps1 -Domain ""

To sinkhole all the FQDNs and domain names listed in file.txt, removing any "www." leading strings, plus add a wildcard (*) record for each domain, all resolving to "":

Sinkhole-DNS.ps1 -InputFile file.txt -IncludeWildCard -RemoveLeadingWWW

To create sinkholed domains from file.txt on a remote DNS server named "" with explicit credentials (you will be prompted for the passphrase):

Sinkhole-DNS.ps1 -InputFile file.txt -DnsServerName "" -Credential "server7&#92administrator"

To delete all sinkhole domains (and only the sinkhole domains this script created, nothing else):

Sinkhole-DNS.ps1 -DeleteSinkHoleDomains

Frequently Asked Questions (FAQ)

Q: Are the DNS zones replicated through Active Directory?
A: No, these are standard primary zones using a text file.

Q: If I sinkhole 10,000 domains, will the script create 10,000 zone files?
A: No, one zone file named "000-sinkholed-domain.local.dns" is used by all of them.

Q: If I'm not sitting at the DNS server, because it's remote, does that DNS server need PowerShell installed?
A: No, the local PowerShell script only talks to the WMI service on the remote DNS server.

Q: Does the DNS server need to be a member of an Active Directory domain?
A: No, it can be a stand-alone or a domain member.

Q: What if I have other primary or AD-integrated zones on my DNS server?
A: That's fine, the script will add more primary zones to whatever zones you already have.

Q: Will the script delete or modify any of my other previously-existing zones?
A: No, the script only touches the zones or domains that it created itself, your other DNS domains won't be changed.

Intrusion Detection & Forensics

By default, the script will create sinkhole zones which resolve to "", but there is a command-line parameter named "-SinkholeIP" with which you can set a different IP address for all your sinkholed zones. You might consider using the IP address of an internal server set up specifically for this purpose.

Your internal sinkhole IDS server, let's call it, should listen on all the likely ports which malware or attack tools might use, especially TCP 80 (HTTP) and 21 (FTP). Enable maximum logging on it. Run a packet capture tool (like WinDump, WireShark or Network Monitor) to capture full packet payloads 24×7 using circular logging, with a large maximum capture size before wrapping, of all traffic to/from the sinkhole server itself. You can install full servers for the listening ports, such as IIS for HTTP and FTP, but be careful of unintended infections. You might instead install honeypot services, or maybe something as simple as HoneyBOT, but we need to interact enough with the client so that the details of any requests can be logged. Your perimeter firewall should block and log all traffic for your sinkhole server to/from the Internet too.

The idea is that you can examine the various logs and packet captures on your sinkhole server to help identify infected machines or those users who are attempting to violate your acceptable use policies. For example, when a workstation becomes infected, that malware may attempt to resolve a known FQDN in order to download via HTTP another piece of malware; often, you can identify the type of malware simply by the URL of the file it tried to download. You might also set a default HTML page which reminds users of your acceptable use policies (and have it mention that all Internet access is logged for the sake of HR). Don't forget that you can enable debug logging on the DNS server too.

Caveats & Legal Disclaimers

The script is fast when creating new sinkhole domains, even tens of thousands of them, but the script is slow when deleting (-DeleteSinkHoleDomains) or reloading (-ReloadSinkHoleDomains) these domains. These two operations will also run up a core of the CPU to over 90% while executing. How slow is "slow"? For example, in my testing, deleting or reloading 20,000 sinkhole domains on a 2.7GHz Core i7 CPU box with Server 2008-R2 required just over nine minutes. The poor performance is due to the WMI queries required.

The script is free and in the public domain, you may use it for any purpose whatsoever without restriction. However, that being said...


Please test the script on non-production servers first, then test on a production server only during off-peak hours and only after having made a full backup.

The SANS Institute hopes you will find the script useful, so best wishes and good luck!

[Version History]
31.Aug.2010 : Initial release.
17.Jun.2012 : Renamed the script.


Posted September 23, 2011 at 6:10 PM | Permalink | Reply


Seems to me we could actually download the files from one or more resources (if they have a newer time stamp than the previously downloaded ones), and "automatically" add them to our server. So, I'm wondering if there was some cautionary tale that resulted in your script avoiding doing that.

Posted September 24, 2011 at 5:43 AM | Permalink | Reply

Jason Fossen

Nope, no cautionary tale, but time stamp checking could be done in a wrapper script before running the DNS script.

Posted October 23, 2011 at 3:50 PM | Permalink | Reply


On windows servers, an auto-updating and parsing mechanism that retrieves bad domains from all these places is already built into software like DNS Redirector

Posted November 3, 2011 at 5:50 PM | Permalink | Reply


@Mark ''" many of us block http/https traffic to/from our DNS servers since they do not need such functionality to provide their core function, DNS service. Running Jason's script from an administrative system allows the DNS servers to be more limited in their access, which I think is a good thing.

Posted March 7, 2012 at 8:17 PM | Permalink | Reply

David Boucher

I looked through the script and tested it out. Very nice, thanks for sharing it! I like that way you put the script together taking care to build objects based on the blackhole zone file you specify.
I have two questions for anyone that may feel like commenting:
1) Is there any way that you know of to separate or split forward lookup zones into multiple folders in microsoft DNS (2008R2)? Importing tens of thousands of domains makes it a pain to scroll down in the GUI to your integrated domain zone. It just makes it look messy, and is confusing for someone when they first look at it.
2) Thoughts on using conditional forwarders for the same purpose? If DNS was configured to forward those domains to a bogus IP, it would effectively black hole it as well. You would obviously lose the ability to re-direct clients to a targeted wildcard forwarder entry for purposes of IDS, etc'' Aside from that, would there be any other pros/cons to doing this?

Posted March 7, 2012 at 9:16 PM | Permalink | Reply

Jason Fossen

Hi David:
Unfortunately, as far as I know, it's not possible organize the zones into folders like that. I agree it looks messy with thousands of domains, but we might be stuck.
Using conditional forwarders is an interesting idea, but I bet the DNS service would complain if tens of thousands were configured. I'll think about it some more too.

Posted February 5, 2013 at 5:57 PM | Permalink | Reply


Is there a way to enable these zones for active directory integration in the script?

Posted February 6, 2013 at 1:36 AM | Permalink | Reply

Jason Fossen

Hi Juba: The script could be rewritten to use AD integration, but I think 99% of admins would prefer to use the standard zone file, so that's how I wrote it. Feel free to change it though! Cheers, J.

Posted July 3, 2013 at 7:23 AM | Permalink | Reply


Hi Jason, is there any way to sinkhole everything except certain defined domain? Thanks

Posted July 3, 2013 at 12:39 PM | Permalink | Reply

Jason Fossen

Hi Frank:
Sorry, not possible with sinkholing per se, but you could create the domain(s) and records you need, then disable forwarding to other DNS servers and disable recursion. You can also do conditional forwarding for just the domain(s) you need, if your server won't be authoritative for those domains.

Posted May 14, 2014 at 2:43 PM | Permalink | Reply


Do you have any suggestion for how to allow access to a single subdomain of one of the domains blocked (and wildcarded) by this script?

Posted May 19, 2014 at 8:52 PM | Permalink | Reply

Jason Fossen

Hi Daniel: The script is not designed for this, but you could manually add the subdomain or records by hand, then ensure these point towards the correct IP addresses (and not the default sinkhole address of Note that these records might get deleted the next time the script is used since the script automatically deletes sinkholed names before refreshing/renewing them. Hope this helps! ''"Jason

Posted July 9, 2016 at 9:01 PM | Permalink | Reply


Hi, thanks for this great script it worked perfectly on my server 2012R2
Where does the script store the blackholed domains?

Posted July 9, 2016 at 10:34 PM | Permalink | Reply


Forgot to mention that i had two do a couple things to get the script ruinning on 2012 R2
First using windows explorer i had to right click on the script, click properties and in the General tab i had to click on

Posted March 23, 2017 at 6:37 PM | Permalink | Reply


Sweet Script. Just a thought ''" if you wanna keep your domains for sinkholing defanged in the text file (safer handling) ''" e.g. subdomain[.]sans[.]org or sans[.]org ''" adding a switch ([Switch] $refang) with the following should work:
If ($refang) { 0..$([Int] $Domains.Count ''" 1) | ForEach { $Domains[$_] = $Domains[$_] -Replace

Posted July 4, 2017 at 7:49 PM | Permalink | Reply


I noticed in the sinkhole dns script there are things like invokewmimethod -objectpath, getwmi. Are those valid cmdlets and parameters? Tried running them independently and encountered an error. Should they be invoke-wmimethod and get-wmiobject? Also, after the sinkhole zone is created, where are the A records? I don't see them in the sinkhole zone in the DNS console or the dns text file. Finally, do I need to create a separate sinkhole zone for each dns server or can I create it on one DNS server and then configure zone transfer to other DNS servers in active directory? Thanks.

Posted July 5, 2017 at 1:17 PM | Permalink | Reply

Jason Fossen

Hi John:
Unfortunately, the blog app here sometimes deletes hyphens or other characters from the code displayed, so it's best to download the script file itself and run the script that way.
All sinkholed domains share one zone file on the drive for standard (not AD-integrated) zones. Nothing is replicated by default, either through AD or regular zone transfers, but you could add replication if you wanted to. The typical use is to sinkhole unwanted names on your forwarding DNS servers in your DMZ, most likely on each forwarder independently, not using any replication to keep things simpler.

Posted February 1, 2019 at 3:23 PM | Permalink | Reply

Sean OBriant

Great script concept, but when I run it, it creates multiple forward lookup zones, not just the 000-sinkholed-domain.local, as expected. Is this the expected behavior? Am I running the script using the wrong settings/commands? The FAQ seems to say otherwise:
Q: If I sinkhole 10,000 domains, will the script create 10,000 zone files?
A: No, one zone file named "000-sinkholed-domain.local.dns" is used by all of them.
Any feedback is appreciated!

Posted February 1, 2019 at 3:39 PM | Permalink | Reply

Jason Fossen

Hi Sean:
Yes, the sinkholed domains must be cached in memory (that's what you see in the GUI management tool), but only one zone file is created on the drive.

Posted February 1, 2019 at 5:39 PM | Permalink | Reply

Sean OBriant

Does that mean I can delete the records that appear in the GUI and leave the single zone file untouched? Sorry if I'm asking a dumb question, but I really can't deal with 15,000 forward lookup zones in my internal DNS, unless maybe I setup an additional DNS server and create it as a forwarder from my two primary DNS servers''I'll have to think about this. We want the functionality of a sinkhole, but we also have 15 business related forward lookup zones we have to manage and I don't want the rest of the IT staff coming for my head after I hide them among thousands of other records.

Posted February 1, 2019 at 5:48 PM | Permalink | Reply

Jason Fossen

Hi Sean:
Unfortunately, this is a limitation of the DNS management tool, you can't filter or hide the sinkholed domains in the GUI (I've looked for good ways to get around this problem too, but no luck).

Post a Comment


* Indicates a required field.