Skip to content

chrisss404/powerdns

Repository files navigation

Introduction

Get your own secure nameserver up and running within minutes, using this dockerized installation of the PowerDNS nameserver.

Source code of PowerDNS here: https://github.com/PowerDNS/pdns

Private Recursor

Simple example of an ad blocking private recursor that is listening for DNSCrypt and DNS-over-TLS (DoT) queries. Easy setup for any desktop OS using dnscrypt-proxy and Android 9 has native support for DoT.

Create private-recursor.yml like this:

version: '2.1'

services:

  gateway:
    image: jwilder/nginx-proxy:alpine
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock:ro"
      - "/etc/nginx/vhost.d"
      - "/usr/share/nginx/html"
      - "/etc/nginx/certs"
    ports:
      - "80:80"

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion:latest
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    volumes_from:
      - gateway

  dnsdist:
    image: chrisss404/powerdns:latest-dnsdist
    environment:
      - VIRTUAL_HOST=dot.example.com
      - VIRTUAL_PORT=9999
      - LETSENCRYPT_EMAIL=you@example.com
      - LETSENCRYPT_HOST=dot.example.com
      - DNSDIST_DNSCRYPT=yes
      - DNSDIST_DNS_OVER_TLS=yes
      - DNSDIST_DNS_OVER_TLS_DOMAIN=dot.example.com
    volumes:
      - "./blocklist.txt:/etc/dnsdist/blocklist.txt:ro"
    volumes_from:
      - gateway:ro
    networks:
      - recursor
    ports:
      - "853:853/tcp"
      - "8443:8443/udp"
      - "8443:8443/tcp"

  recursor:
    image: chrisss404/powerdns:latest-recursor
    sysctls:
      - net.ipv6.route.max_size=16384
    networks:
      recursor:
        ipv4_address: 172.31.117.117

networks:
  recursor:
    ipam:
      driver: default
      config:
        - subnet: "172.31.117.0/24"

Create blocklist.txt like this:

googleadservices.com
...

Then you can do the following:

# start secure recursor (restart dnsdist after the let's encrypt certificate is created)
docker-compose -f private-recursor.yml up

# get DNSCrypt provider public key fingerprint
docker-compose -f private-recursor.yml exec dnsdist dnsdist -e 'printDNSCryptProviderFingerprint("/var/lib/dnsdist/providerPublic.key")'

# create DNS stamp using python dnsstamps library or visit https://dnscrypt.info/stamps
dnsstamp.py dnscrypt -s -a 1.2.3.4:8443 -n 2.dnscrypt-cert.example.com -k 2251:468C:FE4C:C39F:9DF3:C2BA:7C95:ED8F:94F6:06BC:7A24:0493:D168:DE9E:7682:E8AD

Connect using DNSCrypt Proxy

  • Install dnscrypt proxy as described here.
  • Configure dnscrypt proxy to use previously created dnsstamp, e.g.: vim /etc/dnscrypt-proxy/dnscrypt-proxy.toml
-server_names = ['cisco', 'cloudflare']
+server_names = ['example']

[static]
+  [static.'example']
+  stamp = 'sdns://AQEAAAAAAAAADDEuMi4zLjQ6ODQ0MyAiUUaM_kzDn53zwrp8le2PlPYGvHokBJPRaN6edoLorRsyLmRuc2NyeXB0LWNlcnQuZXhhbXBsZS5jb20'

Connect using Android

  • Go to Settings > Network & Internet > Advanced > Private DNS > Private DNS provider hostname
  • Enter DoT hostname: dot.example.com

Private Authoritative Server

Simple example of full powerdns stack including private authoritative nameserver and admin interface for editing DNS records.

Create private-authoritative.yml like this:

version: '2.1'

services:

  admin:
    image: chrisss404/powerdns:latest-admin
    depends_on:
      - admin-db
      - authoritative
    environment:
      - ADMIN_PDNS_API_KEY=api-secret-authoritative
      - ADMIN_USER_PASSWORD=very-secret
    networks:
      - admin-db
      - authoritative
    ports:
      - "80:3031"

  admin-db:
    image: postgres:12.1-alpine
    environment:
      - POSTGRES_DB=pda
      - POSTGRES_INITDB_ARGS=--data-checksums
      - POSTGRES_PASSWORD=pda
      - POSTGRES_USER=pda
    networks:
      - admin-db

  authoritative:
    image: chrisss404/powerdns:latest-authoritative
    depends_on:
      - authoritative-db
    environment:
      - AUTHORITATIVE_API=yes
      - AUTHORITATIVE_API_KEY=api-secret-authoritative
      - AUTHORITATIVE_WEBSERVER=yes
      - AUTHORITATIVE_WEBSERVER_PASSWORD=web-secret-authoritative
    networks:
      authoritative:
        ipv4_address: 172.31.118.118
      authoritative-db:
    ports:
      - "8081:8081/tcp"

  authoritative-db:
    image: postgres:12.1-alpine
    environment:
      - POSTGRES_DB=pdns
      - POSTGRES_INITDB_ARGS=--data-checksums
      - POSTGRES_PASSWORD=pdns
      - POSTGRES_USER=pdns
    networks:
      - authoritative-db

  dnsdist:
    image: chrisss404/powerdns:latest-dnsdist
    environment:
      - DNSDIST_API_KEY=api-secret-dnsdist
      - DNSDIST_PLAIN=yes
      - DNSDIST_QUIET=no
      - DNSDIST_WEBSERVER=yes
      - DNSDIST_WEBSERVER_PASSWORD=web-secret-dnsdist
    networks:
      - recursor
    ports:
      - "1053:53/tcp"
      - "1053:53/udp"
      - "8083:8083/tcp"

  recursor:
    image: chrisss404/powerdns:latest-recursor
    environment:
      - RECURSOR_API_KEY=api-secret-recursor
      - RECURSOR_DNSSEC=validate
      - RECURSOR_FORWARD_ZONES=sys=172.31.118.118
      - RECURSOR_QUIET=no
      - RECURSOR_TRUST_ANCHORS=sys=54970 13 1 27efe1c1a790c3cbb43b947d6d6dfac62507097e
      - RECURSOR_WEBSERVER=yes
      - RECURSOR_WEBSERVER_PASSWORD=web-secret-recursor
    sysctls:
      - net.ipv6.route.max_size=16384
    networks:
      recursor:
        ipv4_address: 172.31.117.117
      authoritative:
    ports:
      - "8082:8082/tcp"

networks:
  admin-db:
  authoritative:
    ipam:
      driver: default
      config:
        - subnet: "172.31.118.0/24"
  authoritative-db:
  recursor:
    ipam:
      driver: default
      config:
        - subnet: "172.31.117.0/24"

Then you can do the following:

# start powerdns stack
docker-compose -f private-authoritative.yml up

# send DNS queries
dig -p 1053 example.com

# PowerDNS admin interface
http://localhost:80

# PowerDNS authoritative stats
http://localhost:8081

# PowerDNS recursor stats
http://localhost:8082

# PowerDNS dnsdist stats
http://localhost:8083

Settings

Admin

Env-Variable Description
ADMIN_DB_HOST Postgres host (default: admin-db)
ADMIN_DB_NAME Postgres database (default: pda)
ADMIN_DB_PASS Postgres password (default: pda)
ADMIN_DB_PORT Postgres port (default: 5432)
ADMIN_DB_USER Postgres username (default: pda)
ADMIN_PDNS_API_KEY PowerDNS API key (default: pdns)
ADMIN_PDNS_API_URL PowerDNS API URL (default: http://authoritative:8081/)
ADMIN_PDNS_VERSION PowerDNS version number (default: 4.2.1)
ADMIN_SIGNUP_ENABLED Allow users to sign up (default: no)
ADMIN_USER_EMAIL Email address of admin user (default: admin@example.org)
ADMIN_USER_FIRSTNAME First name of admin user (default: Administrator)
ADMIN_USER_LASTNAME Last name of admin user (default: User)
ADMIN_USER_PASSWORD Password of admin user (default: admin)

Authoritative

Env-Variable Description
AUTHORITATIVE_ALLOW_AXFR_IPS Allow zonetransfers only to these subnets (default: 127.0.0.0/8,::1)
AUTHORITATIVE_ALLOW_NOTIFY_FROM Allow AXFR NOTIFY from these IP ranges (default: 0.0.0.0/0,::/0)
AUTHORITATIVE_API Enable/disable the REST API (default: no)
AUTHORITATIVE_API_KEY Static pre-shared authentication key for access to the REST API (default: pdns)
AUTHORITATIVE_DB_HOST Postgres host (default: authoritative-db)
AUTHORITATIVE_DB_NAME Postgres database (default: pdns)
AUTHORITATIVE_DB_PASS Postgres password (default: pdns)
AUTHORITATIVE_DB_PORT Postgres port (default: 5432)
AUTHORITATIVE_DB_USER Postgres username (default: pdns)
AUTHORITATIVE_DEFAULT_KSK_ALGORITHM Default KSK algorithm (default: ecdsa256)
AUTHORITATIVE_DEFAULT_KSK_SIZE Default KSK size (default: 0)
AUTHORITATIVE_DEFAULT_PUBLISH_CDNSKEY Default value for PUBLISH-CDNSKEY (default: )
AUTHORITATIVE_DEFAULT_PUBLISH_CDS Default value for PUBLISH-CDS (default: )
AUTHORITATIVE_DEFAULT_ZSK_ALGORITHM Default ZSK algorithm (default: )
AUTHORITATIVE_DEFAULT_ZSK_SIZE Default ZSK size (default: 0)
AUTHORITATIVE_DIRECT_DNSKEY Fetch DNSKEY, CDS and CDNSKEY RRs from backend during DNSKEY or CDS/CDNSKEY synthesis (default: no)
AUTHORITATIVE_DISABLE_AXFR Disable zonetransfers but do allow TCP queries (default: yes)
AUTHORITATIVE_DNAME_PROCESSING If we should support DNAME records (default: no)
AUTHORITATIVE_EXPAND_ALIAS Expand ALIAS records (default: no)
AUTHORITATIVE_LOG_DNS_DETAILS If PDNS should log DNS non-erroneous details (default: no)
AUTHORITATIVE_LOG_DNS_QUERIES If PDNS should log all incoming DNS queries (default: no)
AUTHORITATIVE_LOGLEVEL Amount of logging. Higher is more. Do not set below 3 (default: 4)
AUTHORITATIVE_MASTER Act as a master (default: no)
AUTHORITATIVE_MAX_TCP_CONNECTION_DURATION Maximum time in seconds that a TCP DNS connection is allowed to stay open (default: 0)
AUTHORITATIVE_MAX_TCP_CONNECTIONS Maximum number of TCP connections (default: 20)
AUTHORITATIVE_QUERY_LOGGING Hint backends that queries should be logged (default: no)
AUTHORITATIVE_RECEIVER_THREADS Default number of receiver threads to start (default: 1)
AUTHORITATIVE_RESOLVER Use this resolver for ALIAS and the internal stub resolver (default: no)
AUTHORITATIVE_RETRIEVAL_THREADS Number of AXFR-retrieval threads for slave operation (default: 2)
AUTHORITATIVE_REUSEPORT Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket (default: no)
AUTHORITATIVE_SECURITY_POLL_SUFFIX Domain name from which to query security update notifications (default: secpoll.powerdns.com.)
AUTHORITATIVE_SLAVE Act as a slave (default: no)
AUTHORITATIVE_SIGNING_THREADS Default number of signer threads to start (default: 3)
AUTHORITATIVE_TCP_FAST_OPEN Enable TCP Fast Open support on the listening sockets (default: 0)
AUTHORITATIVE_WEBSERVER Start a webserver for monitoring on port 8081 (default: no)
AUTHORITATIVE_WEBSERVER_PASSWORD Password required for accessing the webserver (default: pdns)

Dnsdist

Env-Variable Description
DNSDIST_API_KEY Static pre-shared authentication key for access to the REST API (default: pdns)
DNSDIST_DNSCRYPT Listen for DNSCrypt queries on port 8443 (default: no)
DNSDIST_DNSCRYPT_PROVIDER_NAME DNSCrypt provider name (default: 2.dnscrypt-cert.example.com)
DNSDIST_DNS_OVER_HTTPS Listen for DNS-over-HTTPS queries on port 443 (default: no)
DNSDIST_DNS_OVER_HTTPS_DOMAIN Domain name of DNS server.
DNSDIST_DNS_OVER_HTTPS_PATH The absolute URI path. (default: /dns-query)
DNSDIST_DNS_OVER_TLS Listen for DNS-over-TLS queries on port 853 (default: no)
DNSDIST_DNS_OVER_TLS_DOMAIN Domain name of DNS server.
DNSDIST_PLAIN Listen for plain DNS queries on port 53 (default: no)
DNSDIST_QUIET Suppress logging of questions and answers (default: no)
DNSDIST_WEBSERVER Start a webserver for REST API on port 8083 (default: no)
DNSDIST_WEBSERVER_PASSWORD Password required for accessing the webserver (default: pdns)

Recursor

Env-Variable Description
RECURSOR_ALLOW_FROM If set, only allow these comma separated netmasks to recurse
RECURSOR_API_KEY Static pre-shared authentication key for access to the REST API (default: pdns)
RECURSOR_DNSSEC DNSSEC mode: off / process-no-validate (default) / process / log-fail / validate
RECURSOR_FORWARD_ZONES Zones for which we forward queries, comma separated domain=ip pairs
RECURSOR_FORWARD_ZONES_RECURSE Zones for which we forward queries with recursion bit, comma separated domain=ip pairs
RECURSOR_LOGLEVEL Amount of logging. Higher is more. Do not set below 3 (default: 3)
RECURSOR_QUIET Suppress logging of questions and answers (default: no)
RECURSOR_SECURITY_POLL_SUFFIX Domain name from which to query security update notifications (default: secpoll.powerdns.com.)
RECURSOR_TCP_FAST_OPEN Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size
RECURSOR_THREADS Launch this number of threads
RECURSOR_TRUST_ANCHORS Trust anchors for private zones when using DNSSEC validation, comma separated domain=ds-key pairs
RECURSOR_WEBSERVER Start a webserver for REST API on port 8082 (default: no)
RECURSOR_WEBSERVER_PASSWORD Password required for accessing the webserver (default: pdns)