mcpField
D
dns-management

dns-management

github.com/bagelholeクラウド・DevOps1.2k370 回インストール23 週間前に更新
リポジトリ

dns-management について

dns-managementは、本番インフラのDNSを設定・診断するエンジニア向けのスキルです。プロバイダー別の例、Terraform設定、名前解決の確認、メールセキュリティ用レコードを扱います。

主な機能

  1. 01DNSゾーンとレコードの管理
  2. 02Route 53とCloudflareの設定例
  3. 03TerraformによるDNS設定
  4. 04digとnslookupを使った診断
  5. 05DNSSECとメールセキュリティレコードの設定

活用シーン

  1. 01アプリ、API、メール用ドメインの設定
  2. 02DNSプロバイダーの移行やゾーン統合
  3. 03名前解決失敗や伝播遅延の調査
  4. 04SPF、DKIM、DMARCの設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill dns-management

インストール後、Claude Code で/dns-managementを入力して読み込まれたか確認します。

詳細

DNS 管理

本番環境のインフラストラクチャ向けに、DNS ゾーン、レコード、名前解決を設定および管理します。

使用するタイミング

  • Web アプリケーション、API、メール用のドメインを設定するとき。
  • DNS プロバイダーを移行する、またはゾーンを統合するとき。
  • CDN、ロードバランサー、クラウドサービス向けに DNS を設定するとき。
  • 名前解決の失敗、伝播の遅延、設定ミスをトラブルシューティングするとき。
  • メールセキュリティのために DNSSEC、SPF、DKIM、DMARC を導入するとき。

前提条件

  • レジストラ(Namecheap、Route53、Google Domains、Cloudflare)で登録済みのドメイン。
  • DNS プロバイダーのダッシュボードまたは API へのアクセス権。
  • 設定済みの AWS CLI(Route53 の例で使用)。
  • ローカル環境で利用できる dig と nslookup(ほとんどの OS に標準で含まれています)。

DNS レコードタイプのリファレンス

タイプ目的値の例
AIPv4 アドレス93.184.216.34
AAAAIPv6 アドレス2606:2800:220:1:248:1893:25c8:1946
CNAME別のドメインへのエイリアスwww.example.com -> example.com
MX優先度付きメールサーバー10 mail.example.com
TXT任意のテキスト(SPF、DKIM、検証)v=spf1 include:_spf.google.com ~all
NS権威ネームサーバーns1.example.com
SRVサービスの場所(ホスト、ポート、優先度)10 5 5060 sip.example.com
CAA認証局の承認0 issue "letsencrypt.org"
PTR逆引き DNS34.216.184.93.in-addr.arpa

AWS Route 53

ホストゾーンの管理
# Create a hosted zone
aws route53 create-hosted-zone \
  --name example.com \
  --caller-reference "$(date +%s)"

# List hosted zones
aws route53 list-hosted-zones

# Get name servers for a zone (update at your registrar)
aws route53 get-hosted-zone --id Z1234567890ABC \
  --query 'DelegationSet.NameServers'
レコードの作成と管理
# Create an A record
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "app.example.com",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [{"Value": "93.184.216.34"}]
      }
    }]
  }'

# Create a CNAME record
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "www.example.com",
        "Type": "CNAME",
        "TTL": 300,
        "ResourceRecords": [{"Value": "example.com"}]
      }
    }]
  }'

# Create an alias record (no TTL, Route53-specific)
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "example.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z2FDTNDATAQYW2",
          "DNSName": "d1234567890.cloudfront.net",
          "EvaluateTargetHealth": false
        }
      }
    }]
  }'

# List records in a zone
aws route53 list-resource-record-sets --hosted-zone-id Z1234567890ABC

# Delete a record (Action: DELETE with exact match)
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "DELETE",
      "ResourceRecordSet": {
        "Name": "old.example.com",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [{"Value": "1.2.3.4"}]
      }
    }]
  }'
Route 53 のヘルスチェック
# Create a health check
aws route53 create-health-check --caller-reference "$(date +%s)" \
  --health-check-config '{
    "IPAddress": "93.184.216.34",
    "Port": 443,
    "Type": "HTTPS",
    "ResourcePath": "/health",
    "RequestInterval": 30,
    "FailureThreshold": 3
  }'

Cloudflare DNS

API でレコードを管理する
# Get zone ID
ZONE_ID=$(curl -s "https://api.cloudflare.com/client/v4/zones?name=example.com" \
  -H "Authorization: Bearer $CF_API_TOKEN" | jq -r '.result[0].id')

# Create an A record (proxied through Cloudflare)
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"A","name":"app","content":"93.184.216.34","proxied":true,"ttl":1}'

# Create a CNAME record (DNS only, not proxied)
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -d '{"type":"CNAME","name":"docs","content":"docs.readthedocs.io","proxied":false,"ttl":3600}'

# List all records
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[] | {name, type, content, proxied}'

# Delete a record
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
  -H "Authorization: Bearer $CF_API_TOKEN"

Terraform による DNS 管理

Terraform で Route 53 を管理する
# dns.tf
resource "aws_route53_zone" "main" {
  name = "example.com"
}

resource "aws_route53_record" "app" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "A"
  ttl     = 300
  records = ["93.184.216.34"]
}

resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.example.com"
  type    = "CNAME"
  ttl     = 300
  records = ["example.com"]
}

# Alias record for CloudFront
resource "aws_route53_record" "cdn" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "A"

  alias {
    name                   = aws_cloudfront_distribution.main.domain_name
    zone_id                = aws_cloudfront_distribution.main.hosted_zone_id
    evaluate_target_health = false
  }
}

# Email records
resource "aws_route53_record" "mx" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "MX"
  ttl     = 3600
  records = [
    "1 aspmx.l.google.com",
    "5 alt1.aspmx.l.google.com",
    "5 alt2.aspmx.l.google.com",
  ]
}

resource "aws_route53_record" "spf" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "TXT"
  ttl     = 3600
  records = ["v=spf1 include:_spf.google.com ~all"]
}

resource "aws_route53_record" "dmarc" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "_dmarc.example.com"
  type    = "TXT"
  ttl     = 3600
  records = ["v=DMARC1; p=quarantine; rua=mailto:[email protected]; pct=100"]
}
Terraform で Cloudflare を管理する
resource "cloudflare_record" "app" {
  zone_id = var.cloudflare_zone_id
  name    = "app"
  content = "93.184.216.34"
  type    = "A"
  proxied = true
}

resource "cloudflare_record" "mail" {
  zone_id  = var.cloudflare_zone_id
  name     = "@"
  content  = "aspmx.l.google.com"
  type     = "MX"
  priority = 1
}

DNS トラブルシューティングコマンド

dig
# Query A record
dig app.example.com A +short

# Query from a specific DNS server
dig @8.8.8.8 app.example.com A

# Show full answer with TTL
dig app.example.com A +noall +answer

# Query MX records
dig example.com MX +short

# Trace the full resolution path
dig app.example.com +trace

# Check DNSSEC validation
dig example.com +dnssec +short

# Query TXT records (SPF, DKIM)
dig example.com TXT +short
dig default._domainkey.example.com TXT +short
nslookup
# Basic lookup
nslookup app.example.com

# Specify DNS server
nslookup app.example.com 8.8.8.8

# Query specific record type
nslookup -type=MX example.com
nslookup -type=TXT example.com
DNS の伝播を確認する
# Query multiple public resolvers
for dns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
  echo "=== $dns ==="
  dig @$dns app.example.com A +short
done

メールセキュリティレコード

# SPF — authorize sending servers
# TXT record on example.com
"v=spf1 include:_spf.google.com include:sendgrid.net -all"

# DKIM — email signing verification
# TXT record on google._domainkey.example.com
# (value provided by your email provider)

# DMARC — policy for failed SPF/DKIM
# TXT record on _dmarc.example.com
"v=DMARC1; p=reject; rua=mailto:[email protected]; pct=100"

TTL の戦略

シナリオ推奨 TTL理由
安定した本番レコード3600-86400(1 時間~24 時間)DNS クエリを減らし、名前解決を高速化します
移行前の準備期間60-300(1~5 分)移行の数日前に TTL を短縮します
移行中/フェイルオーバー中60変更をすばやく伝播させます
移行後のクールダウン徐々に 3600 以上に増やす安定性を確認した後、通常の値に戻します
負荷分散されたレコード60-300ヘルスチェックに基づくフェイルオーバーを可能にします

トラブルシューティング

症状原因対処方法
DNS の変更が反映されない再帰リゾルバーで TTL が切れていない古い TTL が切れるまで待ちます。次回の変更前に TTL を短縮します
SERVFAIL 応答DNSSEC の検証失敗、または委任の破損レジストラの NS レコードを確認し、DNSSEC 署名を検証します
有効なレコードに対して NXDOMAIN が返るホストゾーンの誤り、またはレコードの欠落dig @<authoritative-ns> domain でレコードの存在を確認します
ゾーンの頂点で CNAME を設定するとエラーになるRFC により、ゾーンの頂点では CNAME を使用できないALIAS(Route53)またはプロキシされた A レコード(Cloudflare)を使用します
メールが迷惑メールに振り分けられるSPF/DKIM/DMARC がない、または壊れているdig example.com TXT で TXT レコードを確認し、mail-tester.com でテストします
名前解決が遅い再帰リゾルバーが権威 NS から遠いAnycast DNS プロバイダー(Cloudflare、Route53)を使用します
リゾルバーによって結果が異なる伝播が不完全、またはキャッシュポイズニング権威 NS に直接問い合わせ、競合するレコードがないか確認します

関連スキル

コメント