PowerDNS Recursor
Overview
PowerDNS Recursor is a high-performance, standards-compliant, open-source recursive DNS resolver developed by PowerDNS.COM BV. An authoritative server publishes the zones that you own. A recursor resolves names on behalf of your clients instead. It walks the DNS hierarchy from the root servers down, follows delegations, validates DNSSEC-signed answers, and caches results so that repeat lookups are answered instantly.
This guide covers the deployment and configuration of PowerDNS Recursor on Ubuntu 24.04 on Azure, using the SecureAnyCloud Azure Marketplace image.
The image installs PowerDNS Recursor 5.3 from the official PowerDNS packages (the repo.powerdns.com rec 53 stable branch), pinned above the distribution package. Unattended security upgrades keep the resolver patched on your running VM.
Recursive, not authoritative. This server resolves names for your clients and does not publish zones. Point your workloads, containers and office networks at it instead of a public resolver, to keep your DNS traffic private and under your control.
Never an open resolver. An internet-facing resolver that answers anyone is a DNS amplification hazard. This image ships with recursion restricted to loopback and the RFC1918 private ranges only (incoming.allow_from). Queries from arbitrary internet sources are refused, so this instance can never be abused as a reflector. Opening the resolver to your own client subnets is a single documented change (Step 8).
No default credentials. The REST API key is the equivalent of an administrator password for the resolver, so this image never ships a fixed key. On the first boot of every VM, the image generates a fresh per-instance REST API key and a fresh webserver password. It writes the details to /root/powerdns-recursor-credentials.txt (mode 0600, root only). The REST API and status webserver are bound to 127.0.0.1 only, so the management surface is never exposed to the network, while DNS resolution answers on port 53 for your allowed clients.
What you get:
- PowerDNS Recursor 5.3 from the official PowerDNS packages, run under systemd as the unprivileged
pdnsuser (pdns-recursor.service) - Recursion restricted to loopback and RFC1918 private ranges by default (
incoming.allow_from), so the instance is never an open resolver - DNSSEC validation of signed answers, and the systemd-resolved stub listener disabled so that the Recursor owns port 53 cleanly
- The REST API enabled and bound to loopback (
127.0.0.1:8082), authenticated with a per-instanceX-API-Key, plus the status webserver - A per-instance REST API key and webserver password, generated on first boot and documented in
/root/powerdns-recursor-credentials.txt(0600) - YAML settings (the native PowerDNS Recursor 5.x format), with the SecureAnyCloud configuration split into a base drop-in and a per-VM secrets drop-in under /etc/powerdns/recursor.d/
Prerequisites
You need the following:
- An active Azure subscription, an SSH public key, and a virtual network and subnet in the target region
- A subscription to the PowerDNS Recursor listing on Azure Marketplace
- Network security group rules that allow TCP 22 (admin) and both UDP and TCP 53 (DNS) from the client networks that will use the resolver
- Recommended virtual machine size:
Standard_B2s(2 vCPU, 4 GB RAM) for a small resolver. A resolver that serves heavy query volumes needsStandard_D2s_v5or larger.
Deploy from the Azure Portal
Search for PowerDNS Recursor in the Marketplace, select the SecureAnyCloud publisher, and choose Create. Configure the network security group to allow UDP 53 and TCP 53 (DNS) from your client networks, and TCP 22 for administration. DNS uses UDP 53 for most queries and falls back to TCP 53 for large responses, so open both. The REST API stays on loopback and is never exposed.
Deploy from the Azure CLI
Create the resource group, accept the Marketplace terms, create the VM and open the ports:
RG="dns-prod"; LOCATION="eastus"; VM_NAME="resolver1" IMAGE_URN="sac1647283583153:powerdns-recursor-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:powerdns-recursor-ubuntu-24-04:default:latest
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$IMAGE_URN" \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values "$SSH_KEY" \
--public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 53 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002First boot
On first boot, the image generates a fresh per-instance REST API key and webserver password and starts pdns-recursor. It verifies that the API key round-trips and that a real recursive query resolves. It then writes /root/powerdns-recursor-credentials.txt. First boot completes within a minute. Connect over SSH as azureuser and read the details:
sudo cat /root/powerdns-recursor-credentials.txtConfirm the service is running
Confirm that pdns-recursor.service (the resolver daemon) is active. ss confirms that DNS listens on :53 (UDP and TCP, all interfaces) while the REST API is bound to 127.0.0.1:8082 only.
systemctl is-active pdns-recursor.service pdns_recursor --version 2>&1 | head -1 ss -tlnup | grep -E ':53 |:8082 'Resolve a name
The resolver answers recursive queries for allowed clients. Loopback is allowed by default, so a lookup works immediately on the VM. The Recursor caches answers, so it serves a repeated query instantly from the cache.
dig @127.0.0.1 A example.com +noall +answer dig @127.0.0.1 AAAA cloudflare.com +short dig @127.0.0.1 MX gmail.com +shortUse the REST API
The REST API exposes metrics and cache management, and automation tools use the same interface. Read your per-instance API key from the credentials file into a shell variable, then call the server info endpoint. The API is bound to loopback, so run these commands on the VM, or tunnel port 8082 over SSH.
API_KEY=$(sudo grep '^powerdns.api.key=' /root/powerdns-recursor-credentials.txt | cut -d= -f2-)
curl -s -H "X-API-Key: $API_KEY" http://127.0.0.1:8082/api/v1/servers/localhost | jq '{daemon_type, version}'
sudo rec_control get-all | grep -E '^(questions|cache-hits|cache-misses|cache-entries|all-outqueries)\b'A request without the key is rejected with HTTP 401, and a request with the key returns HTTP 200:
API_KEY=$(sudo grep '^powerdns.api.key=' /root/powerdns-recursor-credentials.txt | cut -d= -f2-)
echo -n 'with key : HTTP '; curl -s -o /dev/null -w '%{http_code}\n' -H "X-API-Key: $API_KEY" http://127.0.0.1:8082/api/v1/servers/localhost
echo -n 'wrong key : HTTP '; curl -s -o /dev/null -w '%{http_code}\n' -H 'X-API-Key: wrong-key' http://127.0.0.1:8082/api/v1/servers/localhostReview the secure-by-default configuration
No default or shared credentials ship in the image. The credentials file is 0600 root:root, and the API key and webserver password are unique to this VM. The resolver is not an open resolver, because incoming.allow_from is restricted to loopback and RFC1918 private ranges. The REST API is bound to loopback only.
sudo stat -c '%n perms: %a owner: %U:%G' /root/powerdns-recursor-credentials.txt
sudo grep -vE '^\s*#|^\s*$' /etc/powerdns/recursor.d/sac-recursor.yml
sudo stat -c '%n perms: %a owner: %U:%G' /etc/powerdns/recursor.d/sac-secrets.ymlAllow your own clients to resolve
By default, only loopback and RFC1918 ranges may query the resolver. To let a specific client subnet resolve, add the subnet as a new list item under incoming.allow_from in the base config and reload. Never add 0.0.0.0/0, because that would make this an open resolver that attackers can abuse for DNS amplification.
sudoedit /etc/powerdns/recursor.d/sac-recursor.yml
# under the allow_from: list, add a line for your client subnet, for example:
# - <your-mgmt-cidr>
sudo systemctl reload pdns-recursorThen, from a client inside that subnet, point its resolver at the IP address of this VM and test:
dig @<public-ip> A example.com +shortDNSSEC validation
The Recursor validates DNSSEC-signed zones. A query for a correctly signed name returns the ad (authenticated data) flag. A deliberately broken signature fails to resolve, which shows that the resolver protects your clients from tampered answers.
dig @127.0.0.1 A cloudflare.com +dnssec +multiline | grep -E 'flags:|status:' dig @127.0.0.1 A example.com +dnssec | grep -E 'flags:|status:'Forwarding and RPZ threat filtering
For split-horizon DNS or private domains, forward specific zones to a private authoritative server by adding a recursor.forward_zones entry (YAML). For DNS firewalling, load a Response Policy Zone (RPZ) so that the resolver blocks known malicious domains. Configure both as YAML drop-ins in /etc/powerdns/recursor.d/. See the PowerDNS Recursor documentation for the full schema. Here is an example forward zone drop-in:
recursor: forward_zones: - zone: internal.example forwarders: - 10.0.0.53Security recommendations
- Keep the resolver closed to the internet. Add to
incoming.allow_fromonly the specific client subnets that need resolution. Never add0.0.0.0/0. The network security group should also allow UDP and TCP 53 only from those networks. - Keep the REST API on loopback. The image binds the API and status webserver to
127.0.0.1and setswebservice.allow_fromto loopback. Do not expose the API directly. If you need it remotely, tunnel port 8082 over SSH. - Enable RPZ (Step 10) to block malicious and unwanted domains at the resolver.
- Restrict administration. Allow TCP 22 for administration only, from your management network.
- Keep the OS and PowerDNS patched. Unattended security upgrades remain enabled on the running VM, including the official PowerDNS repository for the rec 53 branch.
- Monitor cache and query rates. Use
rec_control get-allor the REST API metrics to watch query volume, cache hit ratio and servfail rates.
Support and Licensing
PowerDNS Recursor is developed by PowerDNS.COM BV and distributed under the GNU General Public License version 2 (GPL-2.0) with an OpenSSL linking exception (see the upstream NOTICE file). This SecureAnyCloud image bundles the unmodified official PowerDNS packages. SecureAnyCloud provides the packaging, the secure-by-default configuration, the per-instance credential automation, and 24/7 support with a 24-hour response SLA.
SecureAnyCloud is not affiliated with or endorsed by PowerDNS.COM BV. PowerDNS is a mark of its respective owner and is used here only to identify the software.
Deploy on Azure
Find PowerDNS Recursor on Ubuntu 24.04 LTS on the Azure Marketplace, published by SecureAnyCloud. Deploy from the portal or the Azure CLI as shown above.
Need Help?
Email sales@secureanycloud.com for deployment help, configuration questions, or licensing enquiries.
Deploy on Azure
Launch PowerDNS Recursor 5.3 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
PowerDNS Recursor is a high-performance, open-source recursive DNS resolver developed by PowerDNS.COM BV. An authoritative server publishes the zones that you own. A recursor resolves names on behalf of your clients instead. It walks the DNS hierarchy from the root servers down, follows delegations, validates answers, and caches the results so that repeat lookups are answered instantly from memory.
This guide covers the deployment and configuration of PowerDNS Recursor on AWS, using the SecureAnyCloud AWS Marketplace image. The image installs PowerDNS Recursor 5.3 from the official PowerDNS packages (the repo.powerdns.com rec-53 stable branch), pinned above the distribution package. Point your workloads, containers and office networks at it instead of a public resolver, to keep your DNS traffic private and under your control.
Recursive, not authoritative. This server resolves the whole internet for your clients. It has no zone database and no relational backend, and it is a standalone caching resolver. The sibling SecureAnyCloud product, PowerDNS Authoritative Server, hosts your own zones. This product resolves everything else for the clients that you allow.
Never an open resolver. The shipped configuration restricts recursion with allow_from to loopback and the RFC1918 private ranges only (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), plus link-local and unique-local IPv6 ranges. Queries from arbitrary internet sources are refused, so this instance can never be abused as a DNS amplification reflector. Opening the resolver to your own client subnets is a single documented configuration change (Step 8).
No default credentials. The REST API key is the equivalent of an administrator password for the resolver, so this image never ships a fixed key. On the first boot of every instance, the image generates a fresh per-instance REST API key and a fresh webserver password and starts the resolver. It writes the details to /root/powerdns-recursor-credentials.txt (mode 0600, root only). The REST API and status webserver are bound to 127.0.0.1 only, so the management surface is never exposed to the network, while DNS itself answers on port 53.
What you get:
- PowerDNS Recursor 5.3 from the official PowerDNS packages, run under systemd as the unprivileged
pdnsuser (pdns-recursor.service) - A YAML configuration that restricts recursion to loopback and the RFC1918 private ranges (
allow_from), so the resolver is never an open resolver - The REST API and status webserver enabled and bound to loopback (
127.0.0.1:8082), authenticated with a per-instanceX-API-Keyand webserver password - In-memory caching, DNSSEC validation of signed answers, packet cache and rate limiting, Lua scripting hooks, and RPZ (Response Policy Zone) support for DNS firewalling
- A per-instance REST API key and webserver password, generated on first boot and documented in
/root/powerdns-recursor-credentials.txt(0600) - The systemd-resolved stub listener disabled so that PowerDNS Recursor owns port 53 cleanly, while the OS keeps resolving names through the upstream resolver list
Connecting to your instance
Connect over SSH on port 22 as the default login user for the AMI variant that you launched. First boot generates the per-instance REST API key and webserver password and writes them to a root-only file.
For the Ubuntu 24.04 LTS variant, the SSH login user is ubuntu. The service is pdns-recursor.service, and the config drop-ins are in /etc/powerdns/recursor.d/.
ssh -i /path/to/key.pem ubuntu@<public-ip>Prerequisites
You need the following:
- An active AWS account and an EC2 key pair in the target region
- A subscription to the PowerDNS Recursor listing on AWS Marketplace
- A security group that allows TCP 22 (admin) and both UDP and TCP 53 (DNS) from the clients that will query the resolver
- Recommended instance type:
m5.large(2 vCPU, 8 GB RAM) for a small to medium resolver. A resolver that answers heavy query volumes needs a larger instance type.
Deploy from the AWS Console
In the AWS Marketplace console, search for PowerDNS Recursor, select the SecureAnyCloud listing, and choose Continue to Subscribe, then Continue to Launch. Choose the m5.large instance type, your key pair, and a security group that allows UDP 53 and TCP 53 (DNS) from your client networks and TCP 22 for administration. DNS uses UDP 53 for most queries and falls back to TCP 53 for large or truncated responses, so open both. The REST API stays on loopback and is never exposed.
Deploy from the AWS CLI
Launch the instance:
aws ec2 run-instances \
--image-id ami-<powerdns-recursor-ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <security-group-id> \
--subnet-id <subnet-id> \
--associate-public-ip-address \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=resolver1}]'The security group in this command must open TCP 22 and both UDP and TCP 53.
First boot
On first boot, the image generates a fresh per-instance REST API key and webserver password and starts pdns-recursor. It verifies that the API key round-trips (a wrong key returns 401 and the right key returns 200) and that a real recursive query resolves. It then writes /root/powerdns-recursor-credentials.txt. First boot completes within a minute. Connect over SSH as ubuntu and read the details:
sudo cat /root/powerdns-recursor-credentials.txtConfirm the service is running
Confirm that pdns-recursor.service is active. ss confirms that DNS listens on :53 (UDP and TCP, all interfaces) while the REST API and status webserver are bound to 127.0.0.1:8082 only.
systemctl is-active pdns-recursor.service pdns_recursor --version ss -tlnup | grep -E ':53 |:8082 'Resolve a name recursively
The resolver answers recursive queries for allowed clients. Loopback is always allowed, so a DNS round trip works immediately from the instance itself. The resolver walks the DNS hierarchy from the root servers, follows delegations, and caches the answer. A second identical query is answered instantly from the in-memory cache.
dig @127.0.0.1 A example.com dig @127.0.0.1 AAAA cloudflare.com +short dig @127.0.0.1 A example.com +noall +stats | grep 'Query time'Use the REST API
Monitoring and automation tools use the REST API to read metrics and manage the cache. Read your per-instance API key from the credentials file into a shell variable, then call the server info endpoint. The API is bound to loopback, so run these commands on the instance, or tunnel port 8082 over SSH.
API_KEY=$(sudo grep '^powerdns.api.key=' /root/powerdns-recursor-credentials.txt | cut -d= -f2-)
curl -s -H "X-API-Key: $API_KEY" http://127.0.0.1:8082/api/v1/servers/localhost | jq .A request without the key is rejected with HTTP 401, and a request with the key returns HTTP 200:
API_KEY=$(sudo grep '^powerdns.api.key=' /root/powerdns-recursor-credentials.txt | cut -d= -f2-)
echo -n 'with key : HTTP '; curl -s -o /dev/null -w '%{http_code}\n' -H "X-API-Key: $API_KEY" http://127.0.0.1:8082/api/v1/servers/localhost
echo -n 'without key : HTTP '; curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8082/api/v1/servers/localhostReview the secure-by-default configuration
No default or shared credentials ship in the image. The credentials file is 0600 root:root, the secrets drop-in is 0640 root:pdns, and the API key and webserver password are unique to this instance. allow_from restricts recursion to loopback and the RFC1918 private ranges with no 0.0.0.0/0, so the instance can never be an open reflector.
sudo stat -c '%n %a %U:%G' /root/powerdns-recursor-credentials.txt /etc/powerdns/recursor.d/sac-secrets.yml grep -A9 'allow_from' /etc/powerdns/recursor.d/sac-recursor.ymlLet your own clients resolve
By default, only loopback and the RFC1918 private ranges may query the resolver. To let a specific client subnet resolve, add the subnet as a new list item under incoming.allow_from in the base config /etc/powerdns/recursor.d/sac-recursor.yml, then restart the resolver. The pdns-recursor unit has no reload verb, so you apply configuration changes with restart. Never add 0.0.0.0/0, because that turns this into an open resolver that attackers can abuse for DNS amplification.
Edit the config with sudoedit /etc/powerdns/recursor.d/sac-recursor.yml and add your subnet under the existing allow_from: list, for example:
incoming: allow_from: - 127.0.0.0/8 - 10.0.0.0/8 - 172.16.0.0/12 - 192.168.0.0/16 - 203.0.113.0/24
# <-- your client subnetApply the change by restarting the resolver, then confirm that it is healthy and still resolving:
sudo systemctl restart pdns-recursor.service systemctl is-active pdns-recursor.service dig +short @127.0.0.1 A example.comFrom a machine in that subnet, point its resolver at the private IP address of the instance and confirm resolution:
dig @<public-ip> A example.com +shortThen point your workloads, containers and networks at this instance for DNS. On a Linux client, set the instance as the system resolver by editing /etc/resolv.conf or your network manager to use the address of this instance.
DNSSEC validation
PowerDNS Recursor validates DNSSEC-signed answers. A signed domain returns the ad (authenticated data) flag. A domain with a deliberately broken signature fails to resolve (SERVFAIL), which is the correct secure behaviour.
dig @127.0.0.1 A dnssec-failed.org dig @127.0.0.1 A internetsociety.org +dnssec | grep -E 'flags:|status:'DNS firewalling with RPZ (optional)
Response Policy Zones let the resolver block or rewrite answers for known malicious domains, which turns the resolver into a DNS firewall. Configure an RPZ source under recursor.rpzs in a YAML drop-in in /etc/powerdns/recursor.d/ and reload. See the PowerDNS Recursor documentation for the full RPZ syntax and feed options.
Tune the cache and forwarding (optional)
- Cache sizing.
recursor.max_cache_entriesandrecursor.max_packetcache_entriescontrol the in-memory record and packet caches. Raise them on busy resolvers. - Forwarding zones. To forward specific domains to a downstream server, add entries under
recursor.forward_zonesin a YAML drop-in and reload. An example is a privatecorp.examplezone hosted on your authoritative server. - Rate limiting. The resolver applies per-client rate limits to mitigate abuse. Review the
incomingsettings for your query profile.
Security recommendations
- Restrict the security group. Allow UDP and TCP 53 only from the client networks that need to resolve, and TCP 22 for administration only. The REST API stays on loopback. If you need it remotely, tunnel port 8082 over SSH.
- Never make it an open resolver. Keep
allow_fromscoped to your own client subnets. Do not add0.0.0.0/0under any circumstances. - Keep the REST API on loopback. The image binds the API and status webserver to
127.0.0.1and setswebserver-allow-fromto loopback. Do not expose the API directly. If you need remote API access, front it with a reverse proxy and TLS. - Keep DNSSEC validation enabled (it is on by default) so that your clients receive only cryptographically validated answers.
- Consider RPZ to block known malicious domains at the resolver.
- Keep the OS and PowerDNS patched, including the official PowerDNS repository for the rec-53 branch.
Support and Licensing
PowerDNS Recursor is developed by PowerDNS.COM BV and distributed under the GNU General Public License version 2 (GPL-2.0) with an OpenSSL linking exception (see the upstream NOTICE file). This SecureAnyCloud image bundles the unmodified official PowerDNS packages. SecureAnyCloud provides the packaging, the secure-by-default allow_from configuration, the per-instance credential automation, and 24/7 support.
SecureAnyCloud is not affiliated with or endorsed by PowerDNS.COM BV. PowerDNS is a mark of its respective owner and is used here only to identify the software.
Deploy on AWS
Find PowerDNS Recursor on the AWS Marketplace, published by SecureAnyCloud. Deploy from the console or the AWS CLI as shown above.
Need Help?
Email sales@secureanycloud.com for deployment help, configuration questions, or licensing enquiries.
Deploy on AWS
Launch PowerDNS Recursor with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com