Networking AWS

PowerDNS Recursor on AWS User Guide

| Product: PowerDNS Recursor

Overview

This guide covers the deployment and configuration of PowerDNS Recursor on AWS using cloudimg AWS Marketplace images. PowerDNS Recursor is a high performance open source recursive DNS resolver developed by PowerDNS.COM BV. Unlike an authoritative server, which publishes the zones you own, a recursor resolves names on behalf of your clients: it walks the DNS hierarchy from the root servers down, follows delegations, validates answers, and caches the results so repeat lookups are answered instantly from memory.

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. It is the resolver you point your workloads, containers and office networks at instead of a public resolver, keeping 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; it is a standalone caching resolver. The sibling cloudimg product, PowerDNS Authoritative Server, hosts your own zones; this product resolves everything else for the clients you allow.

Secure by default, 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).

Security by design, 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 very first boot of every instance a fresh per instance REST API key and a fresh webserver password are generated, the resolver is started, and the details are written 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 is included:

  • PowerDNS Recursor 5.3 from the official PowerDNS packages, run under systemd as the unprivileged pdns user (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 instance X-API-Key and 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, documented in /root/powerdns-recursor-credentials.txt (0600)

  • The systemd-resolved stub listener disabled so 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 you launched. The per instance REST API key and webserver password are generated on first boot and written to a root only file.

OS variant SSH login user Notes
Ubuntu 24.04 LTS ubuntu pdns-recursor.service; config drop-ins in /etc/powerdns/recursor.d/
ssh -i /path/to/key.pem ubuntu@<public-ip>

Prerequisites

  • 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 allowing 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. Resolvers answering heavy query volumes should use a larger instance type.

Step 1: Deploy from the AWS Console

In the AWS Marketplace console, search PowerDNS Recursor, select the cloudimg listing, and click 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.

Step 2: Deploy from the AWS CLI

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 referenced above should open TCP 22 and both UDP and TCP 53.

Step 3: First boot

On first boot the image generates a fresh per instance REST API key and webserver password, starts pdns-recursor, verifies the API key round trips (a wrong key returns 401, the right key returns 200) and that a real recursive query resolves, then writes /root/powerdns-recursor-credentials.txt. This completes within a minute. SSH in as ubuntu and read the details:

sudo cat /root/powerdns-recursor-credentials.txt

Step 4: Confirm the service is running

pdns-recursor.service is active. ss confirms DNS is listening 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 '

pdns-recursor.service active, pdns_recursor reports PowerDNS Recursor 5.3.9, and ss shows DNS listening on port 53 udp and tcp on all interfaces while the REST API is bound to 127.0.0.1 port 8082 loopback only

Step 5: 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 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'

a dig query for example.com against 127.0.0.1 returns an A record resolved recursively from the root servers, an AAAA lookup for cloudflare.com returns IPv6 addresses, and a repeat query is answered from the in memory cache with a low query time

Step 6: Use the REST API

The REST API is the same interface used by monitoring and automation tools 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. It is bound to loopback, so run these 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/localhost

the REST API server info endpoint returns JSON with daemon_type recursor and version 5.3.9 when called with the per instance X-API-Key, an authenticated request returns HTTP 200 while a request without a key returns HTTP 401

Step 7: Review 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, the API key and webserver password are unique to this instance, and 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/cloudimg-secrets.yml
grep -A9 'allow_from' /etc/powerdns/recursor.d/cloudimg-recursor.yml

the credentials file is 0600 root root and the secrets drop-in is 0640 root pdns, and the recursor configuration shows allow_from restricted to loopback and the RFC1918 private ranges with no 0.0.0.0/0

Step 8: Let 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 it as a new list item under incoming.allow_from in the base config /etc/powerdns/recursor.d/cloudimg-recursor.yml, then restart the resolver. The pdns-recursor unit has no reload verb, so a restart is how you apply configuration changes. Never add 0.0.0.0/0; that turns this into an open resolver abusable for DNS amplification.

Edit the config with sudoedit /etc/powerdns/recursor.d/cloudimg-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 subnet

Then apply the change by restarting the resolver and confirm 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.com

From a machine in that subnet, point its resolver at the instance's private IP and confirm resolution:

dig @<public-ip> A example.com +short

Then point your workloads, containers and networks at this instance for DNS. On a Linux client you can set it as the system resolver by editing /etc/resolv.conf or your network manager to use this instance's address.

Step 9: DNSSEC validation

PowerDNS Recursor validates DNSSEC-signed answers. A signed domain returns the ad (authenticated data) flag, and 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:'

Step 10: DNS firewalling with RPZ (optional)

Response Policy Zones let the resolver block or rewrite answers for known-malicious domains, turning 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.

Step 11: Tune the cache and forwarding (optional)

  • Cache sizing. recursor.max_cache_entries and recursor.max_packetcache_entries control the in memory record and packet caches; raise them on busy resolvers.

  • Forwarding zones. To forward specific domains (for example an internal corp.example zone hosted on your authoritative server) to a downstream server, add entries under recursor.forward_zones in a YAML drop-in and reload.

  • Rate limiting. The resolver applies per client rate limits to mitigate abuse; review incoming settings for your query profile.

Step 12: 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; tunnel port 8082 over SSH if you need it remotely.

  • Never make it an open resolver. Keep allow_from scoped to your own client subnets. Do not add 0.0.0.0/0 under any circumstances.

  • Keep the REST API on loopback. The image binds the API and status webserver to 127.0.0.1 and sets webserver-allow-from to loopback. Do not expose it directly; front it with a reverse proxy and TLS if remote API access is required.

  • Enable DNSSEC validation (on by default) so 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.

Step 13: 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 cloudimg image bundles the unmodified official PowerDNS packages. cloudimg provides the packaging, the secure by default allow_from configuration, the per instance credential automation, and 24/7 support.

cloudimg 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 cloudimg. Deploy from the Console or the AWS CLI as shown above.

Need Help?

Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.