Why Enable DNSSEC?

The Domain Name Service (or DNS) has been apart of the internet since the 1980’s by combinging names to IP addresses together. Though there have been a few blog posts about DNS, we never discussed how to provide authentication to the responses you receive. Providing DNS services without authentication could lead someone to a rogue or spoofed internet site. This is where DNSSEC comes in.

A common attack vector against DNS servers is known as DNS Cache Poisoning. This happens when an attacker is allowed to send updates to zone files which do not belong to them. For instance, if I were allowed to send updates to a DNS server that belongs to Google, I could then point destination traffic to a host in my possession. I would then be able to set up sites which look identical to those of Google and steal your username and password, or capture what you look up online.

What DNSSEC Is Not

The activation of DNSSEC on your domain provides authenticity of the zone records, it does not provide confidentiality. DNSSEC does not encrypt your DNS traffic to and from the resolver. To provide encryption you must use the DNS over HTTPS (DOH), or DNS over TLS (DOT) protocol. These protocols protect your online privacy by encrypting DNS traffic to the resolver. This prevents Internet Service Providers (ISP) from sniffing your traffic.

You can also combine DOH/DOT and DNSSEC which will provide privacy and authenticity of the resolver. This is a new concept and only a few DNS providers are performing this type of service.

Getting Started

First you need to check if your Top Level Domain (TLD) supports DNSSEC.

If you own a .com domain, you are able to activate DNSSEC. For other TLD’s, please check the ICANN website.

Creating the KMS Key and Policy

The following is a template which can be used to create the KMS key and JSON policy. This will create an ECDSA P256 asymmetric key with sign and verify capabilities. Remember, DNSSEC does not provide privacy so all we need is to sign and verify the domain.

resource "aws_kms_key" "domaindnssec" {
  customer_master_key_spec = "ECC_NIST_P256"
  deletion_window_in_days  = 7
  key_usage                = "SIGN_VERIFY"
  policy = jsonencode({
    Statement = [
      {
        Action = [
          "kms:DescribeKey",
          "kms:GetPublicKey",
          "kms:Sign",
        ],
        Effect = "Allow"
        Principal = {
          Service = "dnssec-route53.amazonaws.com"
        }
        Sid      = "Allow Route 53 DNSSEC Service",
        Resource = "*"
      },
      {
        Action = "kms:CreateGrant",
        Effect = "Allow"
        Principal = {
          Service = "dnssec-route53.amazonaws.com"
        }
        Sid      = "Allow Route 53 DNSSEC Service to CreateGrant",
        Resource = "*"
        Condition = {
          Bool = {
            "kms:GrantIsForAWSResource" = "true"
          }
        }
      },
      {
        Action = "kms:*"
        Effect = "Allow"
        Principal = {
          AWS = "*"
        }
        Resource = "*"
        Sid      = "IAM User Permissions"
      },
    ]
    Version = "2012-10-17"
  })
}

Next, we define the zone and tie the keys to the zone for signature and verification.

data "aws_route53_zone" "example" {
  name = "example.com"
}

resource "aws_route53_key_signing_key" "dnssecksk" {
  name = "example.com"
  hosted_zone_id = data.aws_route53_zone.example.id
  key_management_service_arn = aws_kms_key.dnssecksk.arn
}

resource "aws_route53_hosted_zone_dnssec" "example" {
  depends_on = [
    aws_route53_key_signing_key.dnssecksk
  ]
  hosted_zone_id = aws_route53_key_signing_key.dnssecksk.hosted_zone_id
}

Verify That DNSSEC Is Working

Use dig to verify that DNSSEC is working on the domain. To get started use the following command:

dig +short +dnssec example.com

Note that the resolver being used must be capable of providing DNSSEC look ups. To verify, run the dig command against a known DNSSEC service provider like Cloudflare.

$ dig +short +dnssec cloudflare.com. @1.1.1.1
104.16.133.229
104.16.132.229
A 13 2 300 20220104184526 20220102164526 34505 cloudflare.com. T+hHkJPzWpqYHlh9qkTz9/YUzdOdOlmj5WhDytndJTEqqd9v3KJDz+Qx L1iV2ZhgvSUnV/YhPC4ccIJitS2y8A==

Now commit your code and you are all set.