CoreDNS
Overview
CoreDNS is a fast, flexible, plugin-based DNS server and a CNCF graduated project, best known as the default DNS server for Kubernetes. It is a single self-contained Go binary whose behaviour is defined by a plain-text Corefile. You compose the DNS pipeline you need from a chain of plugins instead of wiring together several daemons.
This SecureAnyCloud image runs CoreDNS 1.14.6 on Ubuntu 24.04 on Azure, installed from the official prebuilt release tarball. It runs under systemd as an unprivileged coredns user with only the CAP_NET_BIND_SERVICE capability, so that it can bind the standard privileged DNS port. CoreDNS answers DNS on port 53 over both UDP and TCP, publishes Prometheus metrics on port 9153, and exposes a loopback health endpoint on port 8080. There is no web interface and no database: the Corefile (/etc/coredns/Corefile) and a zone file are the whole configuration.
Secure by default, and not an open resolver. A naively deployed public resolver can be abused for DNS amplification attacks. This image avoids that. The shipped Corefile has two server blocks. An authoritative block serves the demonstration zone sac.internal with the authoritative answer flag on all interfaces. A recursive cache and forward block uses the acl plugin to allow recursion only from the local host and answer every other source with REFUSED.
On the first boot of every VM, the instance IP is baked into the demonstration zone, so DNS answers immediately. CoreDNS has no login, so no shared or default credential of any kind ships in the image.
What you get:
- CoreDNS 1.14.6 from the official prebuilt release binary, run under systemd as the unprivileged
corednsuser (coredns.service) - A DNS endpoint on
0.0.0.0:53(UDP and TCP), a Prometheus metrics endpoint on:9153, and a health endpoint on:8080 - An authoritative demonstration zone
sac.internal, served with the AA flag on all interfaces, whose records point at this instance's IP (baked in on first boot) - A recursive cache and forward resolver restricted by the
aclplugin to loopback only, so the image is not an open resolver until you deliberately open it to your trusted subnets - The whole configuration in one readable file,
/etc/coredns/Corefile, that you can keep under version control and reload with a single command - The systemd-resolved stub listener disabled so that CoreDNS owns port 53, while the OS keeps resolving names through the upstream resolver list
Prerequisites
Before you deploy, make sure you have:
- An active Azure subscription, an SSH public key, and a VNet with a subnet in the target region
- A subscription to the CoreDNS listing on Azure Marketplace
- Network security group (NSG) rules that allow TCP 22 (administration), and UDP 53 and TCP 53 (DNS) from the clients that will query the server, and optionally TCP 9153 from your monitoring network for metrics
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a small authoritative server or a departmental resolver. CoreDNS is extremely light, so you need a larger size only for very high query volumes.
Deploy from the Azure Portal
Search the Azure Marketplace for CoreDNS, select the SecureAnyCloud publisher, and click Create.
Configure the NSG to allow UDP 53 and TCP 53 from the clients that will query the server, and TCP 22 for administration. If you host public authoritative zones, port 53 must be reachable from the internet. If you run a recursive resolver for your own networks, restrict port 53 to your internal subnets.
Deploy from the Azure CLI
RG="dns-prod"; LOCATION="eastus"; VM_NAME="coredns1" IMAGE_URN="sac1647283583153:coredns-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:coredns-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 resolves the VM's IP address and renders the demonstration zone /etc/coredns/zones/db.sac.internal from the shipped template. It bakes the IP into the demo, www and ns1 records and sets a fresh SOA serial. It then writes the informational note /root/coredns-info.txt and starts coredns.
This completes within seconds. SSH in as azureuser and read the note:
sudo cat /root/coredns-info.txtThe note records the demonstration zone name, the demo record, this VM's IP, the metrics URL, and the paths to the Corefile and zone file. CoreDNS has no password, so the note holds no secret.
Confirm the service is running
Confirm that coredns.service is active and that coredns -version reports 1.14.6. Then use ss to confirm that CoreDNS listens on :53 for DNS (UDP and TCP), :9153 for metrics and :8080 for health.
systemctl is-active coredns.service /opt/coredns/coredns -version sudo ss -tulnp | grep -E ':53 |:9153 |:8080 'Query the authoritative demo zone
CoreDNS serves the demonstration zone sac.internal authoritatively. Query its SOA and the demo A record on the loopback address. The answer carries the aa (authoritative answer) flag, and demo.sac.internal resolves to this VM's IP. DNS over TCP also works, and zone transfers and large responses use it.
dig +noall +answer @127.0.0.1 SOA sac.internal dig @127.0.0.1 A demo.sac.internal dig +tcp +short @127.0.0.1 A www.sac.internalIn the header of the second command, look for flags: qr aa rd. The aa flag confirms that CoreDNS answers authoritatively for this zone instead of recursing.
Prometheus metrics and health
CoreDNS exposes a Prometheus metrics endpoint on port 9153, where every server, plugin and response code is a labelled series. It also exposes a plain health endpoint on port 8080 that returns OK while the server is up.
Point your Prometheus scraper at :9153 and your load balancer or uptime monitor at :8080/health.
curl -s http://127.0.0.1:9153/metrics | grep '^coredns_' | head
curl -s http://127.0.0.1:8080/health; echoConfirm the image is not an open resolver
This is the key security property of a public DNS server. The default .:53 block forwards and caches recursive queries, but its acl plugin allows recursion only from loopback and answers every other source with REFUSED.
Read the acl block, then send a recursive query from this VM's own non-loopback address and confirm that it is refused.
sudo grep -A3 'acl {' /etc/coredns/Corefile
IP=$(hostname -I | awk '{print $1}') dig @"$IP" A probe.invalid | grep -E 'status:'The recursive query from the non-loopback source returns status: REFUSED, which shows that the image cannot be abused for DNS amplification out of the box. Authoritative answers for sac.internal are still served to everyone (Step 5), and only recursion is restricted.
Serve your own authoritative zone
To add an authoritative zone, put a zone file in /etc/coredns/zones and add a matching server block to the Corefile. In the example below, replace <your-domain> with a domain you own. Create the zone file, add the block, and reload.
# 1) create a zone file for <your-domain> in /etc/coredns/zones/db.<your-domain>
# (use the shipped db.sac.internal.template as a starting point)
# 2) add a server block to /etc/coredns/Corefile:
# <your-domain>:53 {
# file /etc/coredns/zones/db.<your-domain>
# log
# errors
# }
# 3) apply the change:
sudo systemctl reload corednsCoreDNS validates the Corefile on reload. If there is a syntax error, it keeps serving the previous configuration. To publish the zone on the internet, point your registrar's NS records at this instance's public IP.
Open recursion to your trusted networks
To let your own clients use the VM as a recursive resolver, add their subnets to the acl allow net line in the default .:53 block, then restart. Limit the list to networks you control, and never open recursion to the whole internet.
# edit /etc/coredns/Corefile and extend the acl allow line in the .:53 block, e.g.
# allow net 127.0.0.0/8 ::1/128 10.0.0.0/8 192.168.0.0/16
sudo systemctl restart corednsForwarding uses Quad9 (9.9.9.9) and its secondary (149.112.112.112) as upstreams. To use different resolvers or DNS over TLS upstreams, change the forward line in the Corefile.
Review the configuration and info note
The Corefile defines everything CoreDNS does, and the info note holds the per-instance details. Read both with sudo.
sudo cat /etc/coredns/Corefile
sudo cat /root/coredns-info.txtThe info note is 0600 root:root and holds no secret, because CoreDNS has no login. It records the demonstration zone, this VM's IP and the metrics URL for convenience.
Security recommendations
Restrict the NSG to your use case. For an internal recursive resolver, allow UDP 53 and TCP 53 only from your client subnets. For public authoritative zones, port 53 must be reachable from the internet, but keep recursion limited to loopback (or scoped by the acl) so that the server is never an open resolver.
Keep the acl tight. Add only subnets you control to the allow net line. An overly broad allow list turns the server back into an open resolver.
Restrict the metrics port. Port 9153 exposes query statistics. Open TCP 9153 only to your monitoring network, never to the public internet.
Enable DNSSEC or DNS over TLS as needed. CoreDNS ships the dnssec, tls and forward tls:// plugins. Enable them in the Corefile for signed zones and encrypted upstreams.
Keep the OS patched. Unattended security upgrades remain enabled on the running VM.
Support and Licensing
CoreDNS is an open-source project distributed under the Apache License 2.0. This SecureAnyCloud image bundles the unmodified official CoreDNS release binary.
SecureAnyCloud provides the packaging, the systemd hardening, the secure-by-default Corefile and acl configuration, the per-instance demonstration zone automation, the paired deployment guide, and 24/7 support with a guaranteed 24-hour response SLA.
SecureAnyCloud is not affiliated with or endorsed by the CoreDNS project or the CNCF. CoreDNS is a mark of its respective owner and is used here only to identify the software.
Deploy on Azure
Find CoreDNS on Ubuntu 24.04 LTS in the Azure Marketplace, published by SecureAnyCloud. Deploy from the Azure 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 CoreDNS 1.14.6 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
CoreDNS is a fast, flexible, plugin-based DNS server and a CNCF graduated project, best known as the default DNS server for Kubernetes. It is a single self-contained Go binary whose behaviour is defined by a plain-text Corefile. You compose the DNS pipeline you need from a chain of plugins instead of wiring together several daemons.
This SecureAnyCloud image runs CoreDNS 1.14.6 on AWS, installed from the official prebuilt release tarball. It runs under systemd as an unprivileged coredns user with only the CAP_NET_BIND_SERVICE capability, so that it can bind the standard privileged DNS port. CoreDNS answers DNS on port 53 over both UDP and TCP, publishes Prometheus metrics on port 9153, and exposes a loopback health endpoint on port 8080. There is no web interface and no database: the Corefile (/etc/coredns/Corefile) and a zone file are the whole configuration.
Secure by default, and not an open resolver. A naively deployed public resolver can be abused for DNS amplification attacks. This image avoids that. The shipped Corefile has two server blocks. An authoritative block serves the demonstration zone sac.internal with the authoritative answer flag on all interfaces. A recursive cache and forward block uses the acl plugin to allow recursion only from the local host and answer every other source with REFUSED.
On the first boot of every instance, the instance IP is baked into the demonstration zone, so DNS answers immediately. CoreDNS has no login, so no shared or default credential of any kind ships in the image.
What you get:
- CoreDNS 1.14.6 from the official prebuilt release binary, run under systemd as the unprivileged
corednsuser (coredns.service) - A DNS endpoint on
0.0.0.0:53(UDP and TCP), a Prometheus metrics endpoint on:9153, and a health endpoint on:8080 - An authoritative demonstration zone
sac.internal, served with the AA flag on all interfaces, whose records point at this instance's IP (baked in on first boot via EC2 instance metadata) - A recursive cache and forward resolver restricted by the
aclplugin to loopback only, so the image is not an open resolver until you deliberately open it to your trusted subnets - The whole configuration in one readable file,
/etc/coredns/Corefile, that you can keep under version control and reload with a single command - The systemd-resolved stub listener disabled so that CoreDNS owns port 53, 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. CoreDNS has no login or password of its own, so nothing secret ships in the image.
OS variant SSH login user Notes
Ubuntu 24.04 LTS ubuntu coredns.service; config at /etc/coredns/Corefile
ssh -i /path/to/key.pem ubuntu@<public-ip>Prerequisites
Before you deploy, make sure you have:
- An AWS account and a key pair in the target region
- A subscription to the CoreDNS listing on AWS Marketplace
- A security group that allows TCP 22 (administration) from your address, UDP 53 and TCP 53 (DNS) from the clients that will query the server, and optionally TCP 9153 from your monitoring network for metrics
Recommended instance type: m5.large (2 vCPU, 8 GB RAM) is ample for a small authoritative server or a departmental resolver. CoreDNS is extremely light, so you need a larger size only for very high query volumes.
Launch from AWS Marketplace
Search AWS Marketplace for CoreDNS and select the SecureAnyCloud listing. Click Continue to Subscribe, then Continue to Configuration, then Continue to Launch.
Choose the m5.large instance type, your key pair and a security group. Configure the security group to allow UDP 53 and TCP 53 from the clients that will query the server, and TCP 22 for administration. If you host public authoritative zones, port 53 must be reachable from the internet. If you run a recursive resolver for your own networks, restrict port 53 to your internal subnets.
Launch from the AWS CLI
AWS_REGION="us-east-1" aws ec2 run-instances \
--region "$AWS_REGION" \
--image-id <coredns-ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <your-sg-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=coredns1}]'Open UDP 53, TCP 53 and TCP 22 in <your-sg-id>, scoped to the sources that need them.
First boot
On first boot, the image resolves the instance's IP address through EC2 instance metadata (IMDSv2) and renders the demonstration zone /etc/coredns/zones/db.sac.internal from the shipped template. It bakes the IP into the demo, www and ns1 records and sets a fresh SOA serial. It then writes the informational note /root/coredns-aws-info.txt and starts coredns.
This completes within seconds. SSH in as ubuntu and read the note:
sudo cat /root/coredns-aws-info.txtThe note records the demonstration zone name, the demo record, this instance's IP, the metrics URL, and the paths to the Corefile and zone file. CoreDNS has no password, so the note holds no secret.
Confirm the service is running
Confirm that coredns.service is active and that coredns -version reports 1.14.6. Then use ss to confirm that CoreDNS listens on :53 for DNS (UDP and TCP), :9153 for metrics and :8080 for health.
systemctl is-active coredns.service /opt/coredns/coredns -version sudo ss -tulnp | grep -E ':53 |:9153 |:8080 'Query the authoritative demo zone
CoreDNS serves the demonstration zone sac.internal authoritatively. Query its SOA and the demo A record on the loopback address. The answer carries the aa (authoritative answer) flag, and demo.sac.internal resolves to this instance's IP. DNS over TCP also works, and zone transfers and large responses use it.
dig +noall +answer @127.0.0.1 SOA sac.internal dig @127.0.0.1 A demo.sac.internal dig +tcp +short @127.0.0.1 A www.sac.internalIn the header of the second command, look for flags: qr aa rd. The aa flag confirms that CoreDNS answers authoritatively for this zone instead of recursing.
Prometheus metrics and health
CoreDNS exposes a Prometheus metrics endpoint on port 9153, where every server, plugin and response code is a labelled series. It also exposes a plain health endpoint on port 8080 that returns OK while the server is up.
Point your Prometheus scraper at :9153 and your load balancer or uptime monitor at :8080/health.
curl -s http://127.0.0.1:9153/metrics | grep '^coredns_' | head
curl -s http://127.0.0.1:8080/health; echoConfirm the image is not an open resolver
This is the key security property of a public DNS server. The default .:53 block forwards and caches recursive queries, but its acl plugin allows recursion only from loopback and answers every other source with REFUSED.
Read the acl block, then send a recursive query from this instance's own non-loopback address and confirm that it is refused.
sudo grep -A3 'acl {' /etc/coredns/Corefile
IP=$(hostname -I | awk '{print $1}') dig @"$IP" A probe.invalid | grep -E 'status:'The recursive query from the non-loopback source returns status: REFUSED, which shows that the image cannot be abused for DNS amplification out of the box. Authoritative answers for sac.internal are still served to everyone (Step 5), and only recursion is restricted.
Serve your own authoritative zone
To add an authoritative zone, put a zone file in /etc/coredns/zones and add a matching server block to the Corefile. In the example below, replace <your-domain> with a domain you own. Create the zone file, add the block, and reload.
# 1) create a zone file for <your-domain> in /etc/coredns/zones/db.<your-domain>
# (use the shipped db.sac.internal.template as a starting point)
# 2) add a server block to /etc/coredns/Corefile:
# <your-domain>:53 {
# file /etc/coredns/zones/db.<your-domain>
# log
# errors
# }
# 3) apply the change:
sudo systemctl reload corednsCoreDNS validates the Corefile on reload. If there is a syntax error, it keeps serving the previous configuration. To publish the zone on the internet, point your registrar's NS records at this instance's public IP.
Open recursion to your trusted networks
To let your own clients use the instance as a recursive resolver, add their subnets to the acl allow net line in the default .:53 block, then restart. Limit the list to networks you control, and never open recursion to the whole internet.
# edit /etc/coredns/Corefile and extend the acl allow line in the .:53 block, e.g.
# allow net 127.0.0.0/8 ::1/128 10.0.0.0/8 192.168.0.0/16
sudo systemctl restart corednsForwarding uses Quad9 (9.9.9.9) and its secondary (149.112.112.112) as upstreams. To use different resolvers or DNS over TLS upstreams, change the forward line in the Corefile.
Review the configuration and info note
The Corefile defines everything CoreDNS does, and the info note holds the per-instance details. Read both with sudo.
sudo cat /etc/coredns/Corefile
sudo cat /root/coredns-aws-info.txtThe info note is 0600 root:root and holds no secret, because CoreDNS has no login. It records the demonstration zone, this instance's IP and the metrics URL for convenience.
Security recommendations
Restrict the security group to your use case. For an internal recursive resolver, allow UDP 53 and TCP 53 only from your client subnets. For public authoritative zones, port 53 must be reachable from the internet, but keep recursion limited to loopback (or scoped by the acl) so that the server is never an open resolver.
Keep the acl tight. Add only subnets you control to the allow net line. An overly broad allow list turns the server back into an open resolver.
Restrict the metrics port. Port 9153 exposes query statistics. Open TCP 9153 only to your monitoring network, never to the public internet.
Enable DNSSEC or DNS over TLS as needed. CoreDNS ships the dnssec, tls and forward tls:// plugins. Enable them in the Corefile for signed zones and encrypted upstreams.
Keep the OS patched. Unattended security upgrades remain enabled on the running instance.
Support and Licensing
CoreDNS is an open-source project distributed under the Apache License 2.0. This SecureAnyCloud image bundles the unmodified official CoreDNS release binary.
SecureAnyCloud provides the packaging, the systemd hardening, the secure-by-default Corefile and acl configuration, the per-instance demonstration zone automation, the paired deployment guide, and 24/7 support with a guaranteed 24-hour response SLA.
SecureAnyCloud is not affiliated with or endorsed by the CoreDNS project or the CNCF. CoreDNS is a mark of its respective owner and is used here only to identify the software.
Deploy on AWS
Find CoreDNS in AWS Marketplace, published by SecureAnyCloud. Launch from the AWS 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 CoreDNS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com