Before you start
This is a native Go plugin compiled into CoreDNS. A stock CoreDNS image cannot load it by adding a directive. You need a running Blockinator service and either a binary built with this plugin or Git and Go to build it.
Start Blockinator first. Use an enabled policy API key from Access & Security, not the administrator password. Use a reachable final HTTPS URL when crossing an untrusted network; these integrations reject redirects. Inside separate containers, localhost refers to each container. Keep the policy hostname resolvable independently of the resolver being integrated to avoid a DNS/policy loop.
Build a CoreDNS binary
The documented build uses Go 1.27.1, the CI-tested version, and CoreDNS v1.14.7. The plugin module minimum is Go 1.25. Run:
git clone https://github.com/StealthCat/blockinator-coredns.git
cd blockinator-coredns
bash tools/build.sh
./build/coredns -pluginsConfirm blockinator appears in the plugin list. The script creates build/coredns and retains upstream source in build/coredns-source. It will not overwrite an existing generated checkout on a later build.
Alternative: download a tested build
Open a successful Build CoreDNS with Blockinator Actions run and choose Linux AMD64 or ARM64. No releases were listed when this guide was reviewed; use Releases when a release with assets is available. A downloaded binary needs no Go compiler.
Extract GitHub’s outer artifact ZIP first. For a v1.0.0 AMD64 archive, verify and extract:
sha256sum -c blockinator-coredns_v1.0.0_linux_amd64.tar.gz.sha256
tar -xzf blockinator-coredns_v1.0.0_linux_amd64.tar.gz
cd blockinator-coredns_v1.0.0_linux_amd64
./coredns -pluginsSubstitute the version and architecture you actually downloaded. This bundle is a complete CoreDNS binary with the standard upstream plugins and Blockinator. Keep the host CA certificates installed. Retain other custom plugins by building your own binary.
Configure the Corefile
Save this as Corefile in your chosen working directory. The loopback listener on port 1053 makes the first test local. The example assumes Blockinator is reachable on the same host at port 8080:
.:1053 {
bind 127.0.0.1
errors
blockinator http://127.0.0.1:8080/api/v1/decision {
api_key_env POLICY_API_KEY
server_id coredns-1
timeout 250ms
fail_mode open
max_concurrent 128
}
cache 30
loop
forward . 1.1.1.1 9.9.9.9
}Choose upstream resolvers appropriate for your network. Configure the final HTTPS endpoint when needed; private CAs belong in the CoreDNS host/container trust store. There is no TLS verification bypass.
Supply the key and start
From a source checkout containing your Corefile, read the enabled key without putting it in shell history, then run the built binary:
read -rsp 'Blockinator policy API key: ' POLICY_API_KEY; echo
export POLICY_API_KEY
./build/coredns -conf CorefileFor an extracted bundle, use ./coredns -conf Corefile instead. For systemd, supply the key through a root-owned environment file with mode 0600; for containers, inject it into that CoreDNS process. Restart after changing the key. Deploy through your existing service/container process once the local test works.
Verify and serve clients
In Blockinator, add blocked.example to a block list and assign it to the testing client’s target, or apply it globally. Run the blocked and allowed queries below, then check Query Log for the correct client, server ID, and matching list. Repeat from a client outside the blocking scope if using scoped rules.
dig @127.0.0.1 -p 1053 blocked.example A
dig @127.0.0.1 -p 1053 blocked.example AAAA
dig +tcp @127.0.0.1 -p 1053 blocked.example A
dig @127.0.0.1 -p 1053 example.com ATo serve LAN clients, change the listener address and port and restrict clients with your firewall or CoreDNS ACLs. Check Query Log for coredns-1. Never expose unrestricted recursive DNS to the internet.
Failure modes and caching
fail_mode open continues normal resolution on policy errors. fail_mode closed returns SERVFAIL; timeouts, invalid replies, and concurrency overload also take that failure path. Each query reaching the plugin gets a fresh policy check, even when its allowed DNS answer is cached. There is no policy-decision cache. Client-side caches can retain older answers.
A Blockinator allow does not override another CoreDNS plugin’s denial. To disable the integration, remove its directive and restart. To update it, rebuild or obtain the intended binary, repeat the checks, and replace it through your service restart process.