# PowerDNS DNS Provider
This is a drop-in provider for ApisCP to enable DNS support using PowerDNS. This module may use PostgreSQL or MySQL as a backend driver.
CentOS 8 is restricted to PowerDNS 4.3 from EPEL due to library dependencies when MySQL is used as a backend. Use PostgreSQL to avoid this restriction.
cpcmd scope:set cp.bootstrapper powerdns_driver pgsql upcp -sb software/powerdns
or at install time,
-s dns_default_provider='powerdns' -s powerdns_driver='pgsql'
# Nameserver installation
Installation can be chosen at install time or after setup. Installation is only necessary if you intend on running a PowerDNS instance on the server. This section covers installation; skip down to ApisCP DNS provider setup for information on configuring a server to use PowerDNS as a DNS provider.
cpcmd scope:set cp.bootstrapper powerdns_enabled true cpcmd scope:set cp.bootstrapper powerdns_driver mysql # Or specify "pgsql" to use PostgreSQL upcp -sb software/powerdns # Optionally set all accounts to use PowerDNS cpcmd scope:set dns.default-provider powerdns
ApisCP provides a DNS-only license class that allows ApisCP to run on a server without the capability to host sites. These licenses are free and may be requested via my.apiscp.com.
# Listening for requests
Firewall access is automatically opened inbound for 53/TCP and 53/UDP when PowerDNS is enabled. On CentOS 8+ machines, to avoid a potential service conflict with systemd-resolved, PowerDNS will bind only to the primary IP address. This can be changed by setting
powerdns_dns_bind_address to a comma-separated string of IPv4 and IPv6 addresses. Prior to PowerDNS 4.3, this value may only accept a list of IPv4 addresses.
# Listen on 192.168.0.1 and all IPv6 interfaces on pdns v4.3 cpcmd scope:set cp.bootstrapper powerdns_dns_bind_address '192.168.0.1, ::' upcp -sb software/powerdns
# Local PowerDNS
In Local mode, PowerDNS only accepts API calls that originate locally from the server. This allows you to place PowerDNS' API behind a reverse proxy, such as Apache. Local-only is enabled by default.
PowerDNS is setup to accept requests on port 8081 (
powerdns_api_port setting). Requests require an authorization key that can be found in
# Install jq if not already installed yum install -y jq # This is your API key grep '^api-key=' /etc/pdns/pdns.conf | cut -d= -f2 curl -v -H 'X-API-Key: APIKEYABOVE' http://127.0.0.1:8081/api/v1/servers/localhost | jq .
# Idempotently changing configuration
PowerDNS may be configured via files in
/etc/pdns/local.d. In addition to this location, Bootstrapper supports injecting settings via
powerdns_custom_config. For example,
cpcmd scope:set cp.bootstrapper 'powerdns_custom_config' '["allow-axfr-ips":126.96.36.199,"also-notify":188.8.131.52]' cd /usr/local/apnscp/resources/playbooks ansible-playbook addin.yml --extra-vars=addin=apnscp-powerdns
also-notify directives will be set whenever the addin plays are run.
# Enabling ALIAS support
ALIAS is a synthetic record that allows CNAME records to be set on the zone apex. ALIAS records require
powerdns_enable_recursion to be enabled as well as an optional
powerdns_recursive_ns to be set otherwise it will default to the system in
cpcmd scope:set cp.bootstrapper powerdns_enable_recursion true cpcmd scope:set cp.bootstrapper powerdns_recursive_ns '[184.108.40.206,220.127.116.11]' # Then re-run the addin... cd /usr/local/apnscp/resources/playbooks ansible-playbook addin.yml --extra-vars=addin=apnscp-powerdns
# Remote API access
In the above example, only local requests may submit DNS modifications to the server. None of the below examples affect querying; DNS queries occur over 53/UDP typically (or 53/TCP if packet size exceeds UDP limits). Depending upon infrastructure, there are a few options to securely accept record submission, all of which require an API key for submission.
# SSL + Apache
ProxyPass directive send requests to the backend. Brute-force attempts are protected by mod_evasive bundled with ApisCP. Requests over this medium are protected by SSL, without HTTP/2 to ameliorate handshake overhead. In all but the very high volume API request environments, this will be acceptable.
In this situation, the endpoint is https://myserver.apiscp.com/dns. Changes are made to
/etc/httpd/conf/httpd-custom.conf within the
<VirtualHost ... :443> bracket (with
SSLEngine On!). After adding the below changes,
systemctl restart httpd.
<Location /dns> ProxyPass http://127.0.0.1:8081 ProxyPassReverse http://127.0.0.1:8081 </Location>
Downsides: minor SSL overhead. Dependent upon Apache. Upsides: easy to setup. Protected by threat deterrence. PowerDNS accessible remotely via an easily controlled URI.
In the above example, API requests can be made via https://myserver.apiscp.com/dns, e.g.
curl -q -H 'X-API-Key: SOMEKEY' https://myserver.apiscp.com/dns/api/v1/servers/localhost
# Disabling brute-force throttling
As hinted above, placing PowerDNS behind Apache confers brute-force protection by mod_evasive. By default, 10 of the same requests in 2 seconds can trigger a brute-force block. Two solutions exist, either raise the same-page request threshold or disable mod_evasive.
Working off the example above <Location /dns> ...
<Location /dns> # Raise threshold to 30 same-page requests in 2 seconds DOSPageCount 30 DOSPageInterval 2 # Or disable entirely DOSEnabled off </Location>
# Standalone server
PowerDNS can also run by itself on a different port. In this situation, the network is configured to block all external requests to port 8081 except those whitelisted. For example, if the entire 18.104.22.168-22.214.171.124 network can be trusted and under your control, then whitelist the IP range:
cpcmd rampart:whitelist 126.96.36.199/24
Additionally, PowerDNS' whitelist must be updated as well. This can be quickly accomplished using the cp.bootstrapper Scope:
cpcmd scope:set cp.bootstrapper powerdns_localonly false cd /usr/local/apnscp/resources/playbooks ansible-playbook addin.yml --extra-vars=addin=apnscp-powerdns
Downsides: requires whitelisting IP addresses for access to API server. Must run on port different than Apache. Upsides: operates independently from Apache.
The server may be accessed once the source IP has been whitelisted,
curl -q -H 'X-API-Key: SOMEKEY' http://myserver.apiscp.com/api/v1/servers/localhost
# ApisCP DNS provider setup
Every server that runs ApisCP may delegate DNS authority to PowerDNS. This is ideal in distributed infrastructures in which coordination allows for seamless server-to-server migrations.
Taking the API key from above and using the SSL + Apache approach above, let's configure
/usr/local/apnscp/config/auth.yaml. Configuration within this file is secret and is not exposed via ApisCP's API. Once set restart ApisCP to compile configuration,
systemctl restart apiscp.
pdns: # This url may be different if using running PowerDNS in standalone uri: https://myserver.apiscp.com/dns/api/v1 key: your_api_key_here type: native # Optional SOA formatting, accepts "domain" format argument for current domain soa: "hostmaster@%(domain)s" ns: - ns1.yourdomain.com - ns2.yourdomain.com recursion: false ## Optional additional nameservers
urivalue is the hostname of your master PowerDNS server running the HTTP API webserver (without a trailing slash)
keyvalue is the API Key in
pdns.confon the master nameserver.
typevalue defines domain type for replication. It's usually set to
nativewhen using DB replication, and to
masterwhen using master-slave pdns replication (in such cluster the slaves should set this value to
slave, while superslaves will do it automatically when creating ingested zones).
soavalue overrides default SOA contact format (hostmaster@DOMAIN). An optional format specifier
domainreplaces the format string with the current domain.
nsvalue is a list of nameservers as in the example above. Put nameservers on their own lines prefixed with a hyphen and indented accordingly. There is not currently a limit for the number of nameservers you may use, 2-5 is typical and should be geographically distributed per RFC 2182.
recursioncontrols ALIAS records, which are CNAMEs on apex (RFC 1034). Enabling requires configuration of
# Setting as default
PowerDNS may be configured as the default provider for all sites using the
dns.default-provider Scope. When adding a site in Nexus or AddDomain the key will be replaced with "DEFAULT". This is substituted automatically on account creation.
cpcmd scope:set dns.default-provider powerdns
Do not set dns.default-provider-key. API key is configured via
- Module- overrides Dns_Module behavior
- Validator- service validator, checks input with AddDomain/EditDomain helpers
# Minimal module methods
All module methods can be overwritten. The following are the bare minimum that are overwritten for this DNS provider to work:
atomicUpdate()attempts a record modification, which must retain the original record if it fails
zoneAxfr()returns all DNS records
add_record()add a DNS record
remove_record()removes a DNS record
get_hosting_nameservers()returns nameservers for the DNS provider
add_zone_backend()creates DNS zone
remove_zone_backend()removes a DNS zone
See also: Creating a provider (hq.apiscp.com)
Submit a PR and have fun!