Claude
Skills
Sign in
Back

dns

Included with Lifetime
$97 forever

DNS concepts, record types, and management skill: Cloudflare, Route 53, DNSSEC, debugging with dig/nslookup, TTL strategy, and split-horizon DNS. USE WHEN: - Adding or modifying DNS records for a web application, mail system, or API - Configuring Cloudflare proxy (orange cloud) or DNS-only mode - Setting up Route 53 hosted zones, health checks, and routing policies - Debugging DNS propagation, CNAME loops, MX failures, or SPF/DKIM issues - Planning a migration with minimal downtime (TTL strategy) - Configuring DNSSEC, CAA records, or reverse DNS (PTR) - Setting up split-horizon DNS for internal vs external resolution DO NOT USE FOR: - SSL/TLS certificate issuance (use ssl-tls skill) - Nginx or application-level routing (use nginx or api-gateway skill) - Service mesh internal DNS (use kubernetes or service-mesh skill) - Email server configuration beyond DNS records (use a dedicated email skill)

Backend & APIs

What this skill does


# DNS — Concepts, Records, and Management

## Record Type Reference

| Type | Format | Example value | Use case | Key notes |
|---|---|---|---|---|
| **A** | IPv4 address | `93.184.216.34` | Map hostname to IPv4 | Most common record; can have multiple values for round-robin |
| **AAAA** | IPv6 address | `2606:2800:220:1:248:1893:25c8:1946` | Map hostname to IPv6 | Dual-stack: both A and AAAA on same name |
| **CNAME** | Fully-qualified hostname | `myapp.netlify.app.` | Alias one name to another | Cannot be used at zone apex; trailing dot = absolute FQDN |
| **MX** | Priority + hostname | `10 mail.example.com.` | Mail server routing | Lower priority number = higher preference; hostname must resolve via A/AAAA |
| **TXT** | Quoted string | `"v=spf1 include:_spf.google.com ~all"` | SPF, DKIM, DMARC, domain ownership verification | Multiple TXT records on same name are valid |
| **SRV** | Priority Weight Port Target | `10 5 5060 sip.example.com.` | Service discovery (SIP, XMPP, game servers) | Format: `_service._proto.name` e.g. `_sip._tcp.example.com` |
| **CAA** | Flags Tag Value | `0 issue "letsencrypt.org"` | Restrict which CAs can issue certs for domain | Protects against misissued certificates |
| **PTR** | Fully-qualified hostname | `host.example.com.` | Reverse DNS (IP → hostname) | Managed in `in-addr.arpa` zone; controlled by IP owner (ISP/cloud provider) |
| **NS** | Nameserver hostname | `ns1.cloudflare.com.` | Authoritative nameservers for zone | Set at registrar; changes propagate slowly (24-48h) |
| **SOA** | Serial Refresh Retry Expire Minimum | (auto-managed) | Zone metadata; used in AXFR transfers | Serial must increment on every change for NOTIFY to work |
| **ALIAS / ANAME** | Hostname | `myapp.netlify.app.` | Apex CNAME equivalent | Cloudflare: CNAME Flattening; Route 53: ALIAS record; resolves at zone apex |
| **DS** | Key tag Algorithm Digest type Digest | `12345 13 2 ABC123...` | DNSSEC — links parent zone to child zone signing key | Created in parent zone; references KSK in child |

---

## TTL Strategy

TTL (Time to Live, in seconds) controls how long resolvers cache a record. Higher TTL = fewer queries to your nameservers; lower TTL = faster propagation of changes.

### Standard TTL Values

| TTL | Seconds | Use case |
|---|---|---|
| 1 minute | 60 | Active incident response / testing |
| 5 minutes | 300 | Pre-migration staging |
| 1 hour | 3600 | Default for most records |
| 1 day | 86400 | Stable records (MX, NS) |
| 1 week | 604800 | Static infrastructure |

### Migration TTL Strategy (Zero-Downtime Record Change)

```
Day -7:   Lower TTL of the record from 86400 to 300 (5 minutes)
          Wait for caches to expire (1 full day at old TTL = 86400s)

Day 0:    Change the record to the new value
          Old value expires from caches within 300s (5 minutes)
          New value takes effect almost immediately

Day +1:   Restore TTL to 86400 once confident in new value
```

This pattern ensures no resolver is caching the old value when you make the switch.

---

## Cloudflare Setup for a Typical Web App

```
# Step-by-step zone configuration sequence

1. Add site to Cloudflare (free plan works for most apps)
   → Cloudflare scans existing records (import them)

2. Update NS records at your registrar to point to Cloudflare nameservers:
   ns1.cloudflare.com
   ns2.cloudflare.com
   (NS propagation: 24-48h)

3. Configure records in Cloudflare dashboard:

   Type  Name    Content              Proxy status   TTL
   A     @       93.184.216.34        Proxied (🟠)   Auto
   A     www     93.184.216.34        Proxied (🟠)   Auto
   CNAME api     backend.example.com  Proxied (🟠)   Auto
   MX    @       10 mail.example.com  DNS only (⬜)  Auto
   TXT   @       v=spf1 ...           DNS only (⬜)  Auto
   TXT   _dmarc  v=DMARC1; ...        DNS only (⬜)  Auto

4. SSL/TLS mode: Full (strict) — requires valid cert on origin
   Security > Settings: Enable HSTS (after app is stable)
   Speed > Optimization: Enable Brotli compression

5. Page rules (legacy) or Rules > Redirect rules:
   http://example.com/* → https://example.com/$1 (301)
```

### Cloudflare Proxy (Orange Cloud) vs DNS-Only (Grey Cloud)

| Setting | IP exposed | DDoS protection | Cloudflare CDN/cache | WebSockets | Use when |
|---|---|---|---|---|---|
| **Proxied** (orange) | Cloudflare IPs shown | Yes | Yes | Supported | Public web, APIs, static sites |
| **DNS-only** (grey) | Origin IP exposed | No | No | N/A | Mail (MX targets must be DNS-only), non-HTTP services, internal servers |

**Important:** A record being proxied hides your origin IP, but only if you never expose your origin IP elsewhere (e.g., in certificate transparency logs, email headers, or old DNS records).

---

## Route 53 — Key Concepts

```bash
# Install AWS CLI v2
pip install awscli --upgrade
aws configure  # Set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, region

# List all hosted zones
aws route53 list-hosted-zones --output table

# Get hosted zone ID for example.com
ZONE_ID=$(aws route53 list-hosted-zones-by-name \
    --dns-name example.com \
    --query 'HostedZones[0].Id' \
    --output text | cut -d/ -f3)

# Upsert a record using change batch JSON
aws route53 change-resource-record-sets \
    --hosted-zone-id "$ZONE_ID" \
    --change-batch '{
        "Changes": [{
            "Action": "UPSERT",
            "ResourceRecordSet": {
                "Name": "api.example.com",
                "Type": "A",
                "TTL": 300,
                "ResourceRecords": [{"Value": "93.184.216.34"}]
            }
        }]
    }'

# Create an ALIAS record (apex CNAME equivalent) pointing to an ALB
aws route53 change-resource-record-sets \
    --hosted-zone-id "$ZONE_ID" \
    --change-batch '{
        "Changes": [{
            "Action": "UPSERT",
            "ResourceRecordSet": {
                "Name": "example.com",
                "Type": "A",
                "AliasTarget": {
                    "HostedZoneId": "Z35SXDOTRQ7X7K",
                    "DNSName": "my-alb-123.us-east-1.elb.amazonaws.com.",
                    "EvaluateTargetHealth": true
                }
            }
        }]
    }'
```

### Route 53 Routing Policies

| Policy | Use case | Notes |
|---|---|---|
| **Simple** | Single resource | Default; no health checks |
| **Weighted** | A/B testing, canary deployments | Set weights 0-255; 0 = no traffic |
| **Latency** | Multi-region lowest-latency routing | AWS measures latency between client and region |
| **Failover** | Active-passive HA | Requires health check on primary record |
| **Geolocation** | Serve different content by country/continent | Falls back to default if no match |
| **Multivalue Answer** | Poor-man's load balancing with health checks | Returns up to 8 healthy records |

---

## dig — Complete Command Reference

```bash
# Basic query (A record)
dig example.com

# Short output (just the answer)
dig +short example.com
dig +short example.com A

# Query a specific record type
dig example.com MX
dig example.com TXT
dig example.com AAAA
dig example.com NS
dig example.com SOA
dig example.com CAA
dig example.com SRV

# Query a specific nameserver (bypass system resolver)
dig @8.8.8.8 example.com A         # Google Public DNS
dig @1.1.1.1 example.com A         # Cloudflare
dig @ns1.cloudflare.com example.com A  # Query authoritative NS directly

# Trace the full delegation chain from root servers
dig +trace example.com

# Check TXT records (SPF, DKIM, DMARC)
dig +short example.com TXT
dig +short _dmarc.example.com TXT
dig +short mail._domainkey.example.com TXT

# Reverse DNS lookup (PTR)
dig -x 93.184.216.34
dig +short -x 93.184.216.34

# Check DNSSEC chain
dig +dnssec example.com
dig +sigchase example.com A  # Validate DNSSEC chain (requires dig ≥ 9.9)

# Show all sections (answer, authority, additional)
dig +all example.com

# Check propagation against multiple resolvers
for ns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
    echo "--- $ns ---"
    dig @$ns +short example

Related in Backend & APIs