Linux ns1.utparral.edu.mx 6.8.0-79-generic #79~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 15 16:54:53 UTC 2 x86_64
Apache/2.4.58 (Unix) OpenSSL/1.1.1w PHP/8.2.12 mod_perl/2.0.12 Perl/v5.34.1
: 10.10.1.9 | : 10.10.1.254
Cant Read [ /etc/named.conf ]
daemon
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
README
+ Create Folder
+ Create File
/
usr /
share /
doc /
bind9-doc /
arm /
[ HOME SHELL ]
Name
Size
Permission
Action
_static
[ DIR ]
drwxr-xr-x
chapter10.html
22.05
KB
-rw-r--r--
chapter1.html
34.51
KB
-rw-r--r--
chapter2.html
15.73
KB
-rw-r--r--
chapter3.html
131.95
KB
-rw-r--r--
chapter4.html
48.77
KB
-rw-r--r--
chapter5.html
81.82
KB
-rw-r--r--
chapter6.html
145.29
KB
-rw-r--r--
chapter7.html
52.45
KB
-rw-r--r--
chapter9.html
18.56
KB
-rw-r--r--
dnssec-guide.html
436.46
KB
-rw-r--r--
general.html
46.95
KB
-rw-r--r--
genindex.html
203.17
KB
-rw-r--r--
history.html
9.97
KB
-rw-r--r--
index.html
28.49
KB
-rw-r--r--
manpages.html
803.05
KB
-rw-r--r--
notes.html
238.02
KB
-rw-r--r--
reference.html
1.4
MB
-rw-r--r--
search.html
5.21
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : dnssec-guide.html
<!DOCTYPE html> <html class="writer-html5" lang="en" > <head> <meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>DNSSEC Guide — BIND 9 9.18.39-0ubuntu0.22.04.2-Ubuntu documentation</title> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="_static/css/theme.css" type="text/css" /> <link rel="stylesheet" href="_static/custom.css" type="text/css" /> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script src="_static/jquery.js"></script> <script src="_static/underscore.js"></script> <script src="_static/doctools.js"></script> <script src="_static/js/theme.js"></script> <link rel="index" title="Index" href="genindex.html" /> <link rel="search" title="Search" href="search.html" /> <link rel="next" title="A Brief History of the DNS and BIND" href="history.html" /> <link rel="prev" title="Changelog" href="changelog.html" /> </head> <body class="wy-body-for-nav"> <div class="wy-grid-for-nav"> <nav data-toggle="wy-nav-shift" class="wy-nav-side"> <div class="wy-side-scroll"> <div class="wy-side-nav-search" > <a href="index.html" class="icon icon-home"> BIND 9 </a> <div class="version"> 9.18.39-0ubuntu0.22.04.2-Ubuntu </div> <div role="search"> <form id="rtd-search-form" class="wy-form" action="search.html" method="get"> <input type="text" name="q" placeholder="Search docs" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> </div> </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu"> <ul> <li class="toctree-l1"><a class="reference internal" href="chapter1.html">1. Introduction to DNS and BIND 9</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter2.html">2. Resource Requirements</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter3.html">3. Configurations and Zone Files</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter4.html">4. Name Server Operations</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter5.html">5. DNSSEC</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter6.html">6. Advanced Configurations</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter7.html">7. Security Configurations</a></li> <li class="toctree-l1"><a class="reference internal" href="reference.html">8. Configuration Reference</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter9.html">9. Troubleshooting</a></li> <li class="toctree-l1"><a class="reference internal" href="chapter10.html">10. Building BIND 9</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Appendices</span></p> <ul class="current"> <li class="toctree-l1"><a class="reference internal" href="notes.html">Release Notes</a></li> <li class="toctree-l1"><a class="reference internal" href="changelog.html">Changelog</a></li> <li class="toctree-l1 current"><a class="current reference internal" href="#">DNSSEC Guide</a><ul> <li class="toctree-l2"><a class="reference internal" href="#preface">Preface</a><ul> <li class="toctree-l3"><a class="reference internal" href="#organization">Organization</a></li> <li class="toctree-l3"><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#introduction">Introduction</a><ul> <li class="toctree-l3"><a class="reference internal" href="#who-should-read-this-guide">Who Should Read this Guide?</a></li> <li class="toctree-l3"><a class="reference internal" href="#who-may-not-want-to-read-this-guide">Who May Not Want to Read this Guide?</a></li> <li class="toctree-l3"><a class="reference internal" href="#what-is-dnssec">What is DNSSEC?</a></li> <li class="toctree-l3"><a class="reference internal" href="#what-does-dnssec-add-to-dns">What Does DNSSEC Add to DNS?</a></li> <li class="toctree-l3"><a class="reference internal" href="#how-does-dnssec-change-dns-lookup">How Does DNSSEC Change DNS Lookup?</a></li> <li class="toctree-l3"><a class="reference internal" href="#the-12-step-dnssec-validation-process-simplified">The 12-Step DNSSEC Validation Process (Simplified)</a></li> <li class="toctree-l3"><a class="reference internal" href="#chain-of-trust">Chain of Trust</a></li> <li class="toctree-l3"><a class="reference internal" href="#why-is-dnssec-important-why-should-i-care">Why is DNSSEC Important? (Why Should I Care?)</a></li> <li class="toctree-l3"><a class="reference internal" href="#how-does-dnssec-change-my-job-as-a-dns-administrator">How Does DNSSEC Change My Job as a DNS Administrator?</a></li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#getting-started">Getting Started</a><ul> <li class="toctree-l3"><a class="reference internal" href="#software-requirements">Software Requirements</a></li> <li class="toctree-l3"><a class="reference internal" href="#hardware-requirements">Hardware Requirements</a><ul> <li class="toctree-l4"><a class="reference internal" href="#recursive-server-hardware">Recursive Server Hardware</a></li> <li class="toctree-l4"><a class="reference internal" href="#authoritative-server-hardware">Authoritative Server Hardware</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#network-requirements">Network Requirements</a></li> <li class="toctree-l3"><a class="reference internal" href="#operational-requirements">Operational Requirements</a><ul> <li class="toctree-l4"><a class="reference internal" href="#parent-zone">Parent Zone</a></li> <li class="toctree-l4"><a class="reference internal" href="#security-requirements">Security Requirements</a></li> </ul> </li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#validation">Validation</a><ul> <li class="toctree-l3"><a class="reference internal" href="#easy-start-guide-for-recursive-servers">Easy-Start Guide for Recursive Servers</a><ul> <li class="toctree-l4"><a class="reference internal" href="#enabling-dnssec-validation">Enabling DNSSEC Validation</a></li> <li class="toctree-l4"><a class="reference internal" href="#effects-of-enabling-dnssec-validation">Effects of Enabling DNSSEC Validation</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#so-you-think-you-are-validating-how-to-test-a-recursive-server">So You Think You Are Validating (How To Test A Recursive Server)</a><ul> <li class="toctree-l4"><a class="reference internal" href="#using-web-based-tools-to-verify">Using Web-Based Tools to Verify</a></li> <li class="toctree-l4"><a class="reference internal" href="#using-dig-to-verify">Using <code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code> to Verify</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#verifying-protection-from-bad-domain-names">Verifying Protection From Bad Domain Names</a><ul> <li class="toctree-l4"><a class="reference internal" href="#how-do-i-know-i-have-a-validation-problem">How Do I Know I Have a Validation Problem?</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#validation-easy-start-explained">Validation Easy Start Explained</a><ul> <li class="toctree-l4"><a class="reference internal" href="#dnssec-validation-explained"><code class="xref any docutils literal notranslate"><span class="pre">dnssec-validation</span></code></a></li> <li class="toctree-l4"><a class="reference internal" href="#how-does-dnssec-change-dns-lookup-revisited">How Does DNSSEC Change DNS Lookup (Revisited)?</a></li> <li class="toctree-l4"><a class="reference internal" href="#how-are-answers-verified">How Are Answers Verified?</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#trust-anchors">Trust Anchors</a></li> <li class="toctree-l3"><a class="reference internal" href="#how-trust-anchors-are-used">How Trust Anchors are Used</a><ul> <li class="toctree-l4"><a class="reference internal" href="#trusted-keys-and-managed-keys">Trusted Keys and Managed Keys</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#what-s-edns-all-about-and-why-should-i-care">What’s EDNS All About (And Why Should I Care)?</a><ul> <li class="toctree-l4"><a class="reference internal" href="#edns-overview">EDNS Overview</a></li> <li class="toctree-l4"><a class="reference internal" href="#edns-on-dns-servers">EDNS on DNS Servers</a></li> <li class="toctree-l4"><a class="reference internal" href="#support-for-large-packets-on-network-equipment">Support for Large Packets on Network Equipment</a></li> <li class="toctree-l4"><a class="reference internal" href="#wait-dns-uses-tcp">Wait… DNS Uses TCP?</a></li> </ul> </li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#signing">Signing</a><ul> <li class="toctree-l3"><a class="reference internal" href="#easy-start-guide-for-signing-authoritative-zones">Easy-Start Guide for Signing Authoritative Zones</a><ul> <li class="toctree-l4"><a class="reference internal" href="#enabling-automated-dnssec-zone-maintenance-and-key-generation">Enabling Automated DNSSEC Zone Maintenance and Key Generation</a></li> <li class="toctree-l4"><a class="reference internal" href="#verification">Verification</a></li> <li class="toctree-l4"><a class="reference internal" href="#uploading-information-to-the-parent-zone">Uploading Information to the Parent Zone</a></li> <li class="toctree-l4"><a class="reference internal" href="#so-what-now">So… What Now?</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#your-zone-before-and-after-dnssec">Your Zone, Before and After DNSSEC</a></li> <li class="toctree-l3"><a class="reference internal" href="#how-to-test-authoritative-zones">How To Test Authoritative Zones</a><ul> <li class="toctree-l4"><a class="reference internal" href="#look-for-key-data-in-your-zone">Look for Key Data in Your Zone</a></li> <li class="toctree-l4"><a class="reference internal" href="#look-for-signatures-in-your-zone">Look for Signatures in Your Zone</a></li> <li class="toctree-l4"><a class="reference internal" href="#examine-the-zone-file">Examine the Zone File</a></li> <li class="toctree-l4"><a class="reference internal" href="#check-the-parent">Check the Parent</a></li> <li class="toctree-l4"><a class="reference internal" href="#external-testing-tools">External Testing Tools</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#signing-easy-start-explained">Signing Easy Start Explained</a><ul> <li class="toctree-l4"><a class="reference internal" href="#enable-automatic-dnssec-maintenance-explained">Enable Automatic DNSSEC Maintenance Explained</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#working-with-the-parent-zone">Working With the Parent Zone</a><ul> <li class="toctree-l4"><a class="reference internal" href="#ds-record-format">DS Record Format</a></li> <li class="toctree-l4"><a class="reference internal" href="#dnskey-format">DNSKEY Format</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#creating-a-custom-dnssec-policy">Creating a Custom DNSSEC Policy</a></li> <li class="toctree-l3"><a class="reference internal" href="#maintenance-tasks">Maintenance Tasks</a><ul> <li class="toctree-l4"><a class="reference internal" href="#the-cds-and-cdnskey-resource-records">The CDS and CDNSKEY Resource Records</a></li> <li class="toctree-l4"><a class="reference internal" href="#working-with-the-parent-zone-2">Working with the Parent Zone (2)</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#alternate-ways-of-signing-a-zone">Alternate Ways of Signing a Zone</a><ul> <li class="toctree-l4"><a class="reference internal" href="#semi-automatic-signing">Semi-Automatic Signing</a></li> <li class="toctree-l4"><a class="reference internal" href="#fully-automatic-signing-with-dnssec-policy">Fully Automatic Signing With <code class="xref any docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a></li> <li class="toctree-l4"><a class="reference internal" href="#manual-signing">Manual Signing</a></li> </ul> </li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#basic-dnssec-troubleshooting">Basic DNSSEC Troubleshooting</a><ul> <li class="toctree-l3"><a class="reference internal" href="#query-path">Query Path</a></li> <li class="toctree-l3"><a class="reference internal" href="#visible-dnssec-validation-symptoms">Visible DNSSEC Validation Symptoms</a></li> <li class="toctree-l3"><a class="reference internal" href="#basic-logging">Basic Logging</a></li> <li class="toctree-l3"><a class="reference internal" href="#bind-dnssec-debug-logging">BIND DNSSEC Debug Logging</a></li> <li class="toctree-l3"><a class="reference internal" href="#common-problems">Common Problems</a><ul> <li class="toctree-l4"><a class="reference internal" href="#security-lameness">Security Lameness</a></li> <li class="toctree-l4"><a class="reference internal" href="#incorrect-time">Incorrect Time</a></li> <li class="toctree-l4"><a class="reference internal" href="#unable-to-load-keys">Unable to Load Keys</a></li> <li class="toctree-l4"><a class="reference internal" href="#invalid-trust-anchors">Invalid Trust Anchors</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#negative-trust-anchors">Negative Trust Anchors</a></li> <li class="toctree-l3"><a class="reference internal" href="#nsec3-troubleshooting">NSEC3 Troubleshooting</a></li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#advanced-discussions">Advanced Discussions</a><ul> <li class="toctree-l3"><a class="reference internal" href="#signature-validity-periods-and-zone-re-signing-intervals">Signature Validity Periods and Zone Re-Signing Intervals</a></li> <li class="toctree-l3"><a class="reference internal" href="#proof-of-non-existence-nsec-and-nsec3">Proof of Non-Existence (NSEC and NSEC3)</a><ul> <li class="toctree-l4"><a class="reference internal" href="#nsec">NSEC</a></li> <li class="toctree-l4"><a class="reference internal" href="#nsec3">NSEC3</a></li> <li class="toctree-l4"><a class="reference internal" href="#nsec-or-nsec3">NSEC or NSEC3?</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#dnssec-keys">DNSSEC Keys</a><ul> <li class="toctree-l4"><a class="reference internal" href="#types-of-keys">Types of Keys</a></li> <li class="toctree-l4"><a class="reference internal" href="#which-algorithm">Which Algorithm?</a></li> <li class="toctree-l4"><a class="reference internal" href="#key-sizes">Key Sizes</a></li> <li class="toctree-l4"><a class="reference internal" href="#key-storage">Key Storage</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#rollovers">Rollovers</a><ul> <li class="toctree-l4"><a class="reference internal" href="#key-rollovers">Key Rollovers</a></li> <li class="toctree-l4"><a class="reference internal" href="#emergency-key-rollovers">Emergency Key Rollovers</a></li> <li class="toctree-l4"><a class="reference internal" href="#algorithm-rollovers">Algorithm Rollovers</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#other-topics">Other Topics</a><ul> <li class="toctree-l4"><a class="reference internal" href="#dnssec-and-dynamic-updates">DNSSEC and Dynamic Updates</a></li> <li class="toctree-l4"><a class="reference internal" href="#dnssec-on-private-networks">DNSSEC on Private Networks</a></li> <li class="toctree-l4"><a class="reference internal" href="#introduction-to-dane">Introduction to DANE</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#disadvantages-of-dnssec">Disadvantages of DNSSEC</a></li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#recipes">Recipes</a><ul> <li class="toctree-l3"><a class="reference internal" href="#recipes-inline-signing">DNSSEC Signing</a><ul> <li class="toctree-l4"><a class="reference internal" href="#primary-server-dnssec-signing">Primary Server DNSSEC Signing</a></li> <li class="toctree-l4"><a class="reference internal" href="#bump-in-the-wire-signing">“Bump in the Wire” Signing</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#recipes-rollovers">Rollovers</a><ul> <li class="toctree-l4"><a class="reference internal" href="#zsk-rollover">ZSK Rollover</a></li> <li class="toctree-l4"><a class="reference internal" href="#ksk-rollover">KSK Rollover</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#nsec-and-nsec3">NSEC and NSEC3</a><ul> <li class="toctree-l4"><a class="reference internal" href="#migrating-from-nsec-to-nsec3">Migrating from NSEC to NSEC3</a></li> <li class="toctree-l4"><a class="reference internal" href="#migrating-from-nsec3-to-nsec">Migrating from NSEC3 to NSEC</a></li> <li class="toctree-l4"><a class="reference internal" href="#recipes-nsec3-optout">NSEC3 Opt-Out</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="#reverting-to-unsigned">Reverting to Unsigned</a></li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#commonly-asked-questions">Commonly Asked Questions</a></li> </ul> </li> <li class="toctree-l1"><a class="reference internal" href="history.html">A Brief History of the DNS and BIND</a></li> <li class="toctree-l1"><a class="reference internal" href="general.html">General DNS Reference Information</a></li> <li class="toctree-l1"><a class="reference internal" href="manpages.html">Manual Pages</a></li> </ul> </div> </div> </nav> <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" > <i data-toggle="wy-nav-top" class="fa fa-bars"></i> <a href="index.html">BIND 9</a> </nav> <div class="wy-nav-content"> <div class="rst-content"> <div role="navigation" aria-label="Page navigation"> <ul class="wy-breadcrumbs"> <li><a href="index.html" class="icon icon-home"></a> »</li> <li>DNSSEC Guide</li> <li class="wy-breadcrumbs-aside"> <a href="_sources/dnssec-guide.rst.txt" rel="nofollow"> View page source</a> </li> </ul> <hr/> </div> <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> <div itemprop="articleBody"> <section id="dnssec-guide"> <span id="id1"></span><h1>DNSSEC Guide<a class="headerlink" href="#dnssec-guide" title="Permalink to this headline"></a></h1> <section id="preface"> <h2>Preface<a class="headerlink" href="#preface" title="Permalink to this headline"></a></h2> <section id="organization"> <span id="preface-organization"></span><h3>Organization<a class="headerlink" href="#organization" title="Permalink to this headline"></a></h3> <p>This document provides introductory information on how DNSSEC works, how to configure BIND 9 to support some common DNSSEC features, and some basic troubleshooting tips. The chapters are organized as follows:</p> <p><a class="reference internal" href="#dnssec-guide-introduction"><span class="std std-ref">Introduction</span></a> covers the intended audience for this document, assumed background knowledge, and a basic introduction to the topic of DNSSEC.</p> <p><a class="reference internal" href="#getting-started"><span class="std std-ref">Getting Started</span></a> covers various requirements before implementing DNSSEC, such as software versions, hardware capacity, network requirements, and security changes.</p> <p><a class="reference internal" href="#dnssec-validation"><span class="std std-ref">Validation</span></a> walks through setting up a validating resolver, and gives both more information on the validation process and some examples of tools to verify that the resolver is properly validating answers.</p> <p><a class="reference internal" href="#dnssec-signing"><span class="std std-ref">Signing</span></a> explains how to set up a basic signed authoritative zone, details the relationship between a child and a parent zone, and discusses ongoing maintenance tasks.</p> <p><a class="reference internal" href="#dnssec-troubleshooting"><span class="std std-ref">Basic DNSSEC Troubleshooting</span></a> provides some tips on how to analyze and diagnose DNSSEC-related problems.</p> <p><a class="reference internal" href="#dnssec-advanced-discussions"><span class="std std-ref">Advanced Discussions</span></a> covers several topics, including key generation, key storage, key management, NSEC and NSEC3, and some disadvantages of DNSSEC.</p> <p><a class="reference internal" href="#dnssec-recipes"><span class="std std-ref">Recipes</span></a> provides several working examples of common DNSSEC solutions, with step-by-step details.</p> <p><a class="reference internal" href="#dnssec-commonly-asked-questions"><span class="std std-ref">Commonly Asked Questions</span></a> lists some commonly asked questions and answers about DNSSEC.</p> </section> <section id="acknowledgements"> <span id="preface-acknowledgement"></span><h3>Acknowledgements<a class="headerlink" href="#acknowledgements" title="Permalink to this headline"></a></h3> <p>This document was originally authored by Josh Kuo of <a class="reference external" href="https://www.deepdivenetworking.com/">DeepDive Networking</a>. He can be reached at <a class="reference external" href="mailto:josh.kuo%40gmail.com">josh<span>.</span>kuo<span>@</span>gmail<span>.</span>com</a>.</p> <p>Thanks to the following individuals (in no particular order) who have helped in completing this document: Jeremy C. Reed, Heidi Schempf, Stephen Morris, Jeff Osborn, Vicky Risk, Jim Martin, Evan Hunt, Mark Andrews, Michael McNally, Kelli Blucher, Chuck Aurora, Francis Dupont, Rob Nagy, Ray Bellis, Matthijs Mekking, and Suzanne Goldlust.</p> <p>Special thanks goes to Cricket Liu and Matt Larson for their selflessness in knowledge sharing.</p> <p>Thanks to all the reviewers and contributors, including John Allen, Jim Young, Tony Finch, Timothe Litt, and Dr. Jeffry A. Spain.</p> <p>The sections on key rollover and key timing metadata borrowed heavily from the Internet Engineering Task Force draft titled “DNSSEC Key Timing Considerations” by S. Morris, J. Ihren, J. Dickinson, and W. Mekking, subsequently published as <span class="target" id="index-0"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7583.html"><strong>RFC 7583</strong></a>.</p> <p>Icons made by <a class="reference external" href="https://www.freepik.com/">Freepik</a> and <a class="reference external" href="https://simpleicon.com/">SimpleIcon</a> from <a class="reference external" href="https://www.flaticon.com/">Flaticon</a>, licensed under <a class="reference external" href="https://creativecommons.org/licenses/by/3.0/">Creative Commons BY 3.0</a>.</p> </section> </section> <section id="introduction"> <span id="dnssec-guide-introduction"></span><h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2> <section id="who-should-read-this-guide"> <span id="who-should-read"></span><h3>Who Should Read this Guide?<a class="headerlink" href="#who-should-read-this-guide" title="Permalink to this headline"></a></h3> <p>This guide is intended as an introduction to DNSSEC for the DNS administrator who is already comfortable working with the existing BIND and DNS infrastructure. He or she might be curious about DNSSEC, but may not have had the time to investigate DNSSEC, to learn whether DNSSEC should be a part of his or her environment, and understand what it means to deploy it in the field.</p> <p>This guide provides basic information on how to configure DNSSEC using BIND 9.16.9 or later. Most of the information and examples in this guide also apply to versions of BIND later than 9.9.0, but some of the key features described here were only introduced in version 9.16.9. Readers are assumed to have basic working knowledge of the Domain Name System (DNS) and related network infrastructure, such as concepts of TCP/IP. In-depth knowledge of DNS and TCP/IP is not required. The guide assumes no prior knowledge of DNSSEC or related technology such as public key cryptography.</p> </section> <section id="who-may-not-want-to-read-this-guide"> <span id="who-should-not-read"></span><h3>Who May Not Want to Read this Guide?<a class="headerlink" href="#who-may-not-want-to-read-this-guide" title="Permalink to this headline"></a></h3> <p>If you are already operating a DNSSEC-signed zone, you may not learn much from the first half of this document, and you may want to start with <a class="reference internal" href="#dnssec-advanced-discussions"><span class="std std-ref">Advanced Discussions</span></a>. If you want to learn about details of the protocol extension, such as data fields and flags, or the new record types, this document can help you get started but it does not include all the technical details.</p> <p>If you are experienced in DNSSEC, you may find some of the concepts in this document to be overly simplified for your taste, and some details are intentionally omitted at times for ease of illustration.</p> <p>If you administer a large or complex BIND environment, this guide may not provide enough information for you, as it is intended to provide only basic, generic working examples.</p> <p>If you are a top-level domain (TLD) operator, or administer zones under signed TLDs, this guide can help you get started, but it does not provide enough details to serve all of your needs.</p> <p>If your DNS environment uses DNS products other than (or in addition to) BIND, this document may provide some background or overlapping information, but you should check each product’s vendor documentation for specifics.</p> <p>Finally, deploying DNSSEC on internal or private networks is not covered in this document, with the exception of a brief discussion in <a class="reference internal" href="#dnssec-on-private-networks"><span class="std std-ref">DNSSEC on Private Networks</span></a>.</p> </section> <section id="what-is-dnssec"> <span id="id2"></span><h3>What is DNSSEC?<a class="headerlink" href="#what-is-dnssec" title="Permalink to this headline"></a></h3> <p>The Domain Name System (DNS) was designed in a day and age when the Internet was a friendly and trusting place. The protocol itself provides little protection against malicious or forged answers. DNS Security Extensions (DNSSEC) addresses this need, by adding digital signatures into DNS data so that each DNS response can be verified for integrity (the answer did not change during transit) and authenticity (the data came from the true source, not an impostor). In the ideal world, when DNSSEC is fully deployed, every single DNS answer can be validated and trusted.</p> <p>DNSSEC does not provide a secure tunnel; it does not encrypt or hide DNS data. It operates independently of an existing Public Key Infrastructure (PKI). It does not need SSL certificates or shared secrets. It was designed with backwards compatibility in mind, and can be deployed without impacting “old” unsecured domain names.</p> <p>DNSSEC is deployed on the three major components of the DNS infrastructure:</p> <ul class="simple"> <li><p><em>Recursive Servers</em>: People use recursive servers to lookup external domain names such as <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code>. Operators of recursive servers need to enable DNSSEC validation. With validation enabled, recursive servers carry out additional tasks on each DNS response they receive to ensure its authenticity.</p></li> <li><p><em>Authoritative Servers</em>: People who publish DNS data on their name servers need to sign that data. This entails creating additional resource records, and publishing them to parent domains where necessary. With DNSSEC enabled, authoritative servers respond to queries with additional DNS data, such as digital signatures and keys, in addition to the standard answers.</p></li> <li><p><em>Applications</em>: This component lives on every client machine, from web servers to smart phones. This includes resolver libraries on different operating systems, and applications such as web browsers.</p></li> </ul> <p>In this guide, we focus on the first two components, Recursive Servers and Authoritative Servers, and only lightly touch on the third component. We look at how DNSSEC works, how to configure a validating resolver, how to sign DNS zone data, and other operational tasks and considerations.</p> </section> <section id="what-does-dnssec-add-to-dns"> <span id="id3"></span><h3>What Does DNSSEC Add to DNS?<a class="headerlink" href="#what-does-dnssec-add-to-dns" title="Permalink to this headline"></a></h3> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Public Key Cryptography works on the concept of a pair of keys: one made available to the world publicly, and one kept in secrecy privately. Not surprisingly, they are known as a public key and a private key. If you are not familiar with the concept, think of it as a cleverly designed lock, where one key locks and one key unlocks. In DNSSEC, we give out the unlocking public key to the rest of the world, while keeping the locking key private. To learn how this is used to secure DNS messages, see <a class="reference internal" href="#how-are-answers-verified"><span class="std std-ref">How Are Answers Verified?</span></a>.</p> </div> <p>DNSSEC introduces eight new resource record types:</p> <ul class="simple"> <li><p>RRSIG (digital resource record signature)</p></li> <li><p>DNSKEY (public key)</p></li> <li><p>DS (parent-child)</p></li> <li><p>NSEC (proof of nonexistence)</p></li> <li><p>NSEC3 (proof of nonexistence)</p></li> <li><p>NSEC3PARAM (proof of nonexistence)</p></li> <li><p>CDS (child-parent signaling)</p></li> <li><p>CDNSKEY (child-parent signaling)</p></li> </ul> <p>This guide does not go deep into the anatomy of each resource record type; the details are left for the reader to research and explore. Below is a short introduction on each of the new record types:</p> <ul> <li><p><em>RRSIG</em>: With DNSSEC enabled, just about every DNS answer (A, PTR, MX, SOA, DNSKEY, etc.) comes with at least one resource record signature, or RRSIG. These signatures are used by recursive name servers, also known as validating resolvers, to verify the answers received. To learn how digital signatures are generated and used, see <a class="reference internal" href="#how-are-answers-verified"><span class="std std-ref">How Are Answers Verified?</span></a>.</p></li> <li><p><em>DNSKEY</em>: DNSSEC relies on public-key cryptography for data authenticity and integrity. There are several keys used in DNSSEC, some private, some public. The public keys are published to the world as part of the zone data, and they are stored in the DNSKEY record type.</p> <p>In general, keys in DNSSEC are used for one or both of the following roles: as a Zone Signing Key (ZSK), used to protect all zone data; or as a Key Signing Key (KSK), used to protect the zone’s keys. A key that is used for both roles is referred to as a Combined Signing Key (CSK). We talk about keys in more detail in <a class="reference internal" href="#advanced-discussions-key-generation"><span class="std std-ref">DNSSEC Keys</span></a>.</p> </li> <li><p><em>DS</em>: One of the critical components of DNSSEC is that the parent zone can “vouch” for its child zone. The DS record is verifiable information (generated from one of the child’s public keys) that a parent zone publishes about its child as part of the chain of trust. To learn more about the Chain of Trust, see <a class="reference internal" href="#chain-of-trust"><span class="std std-ref">Chain of Trust</span></a>.</p></li> <li><p><em>NSEC, NSEC3, NSEC3PARAM</em>: These resource records all deal with a very interesting problem: proving that something does not exist. We look at these record types in more detail in <a class="reference internal" href="#advanced-discussions-proof-of-nonexistence"><span class="std std-ref">Proof of Non-Existence (NSEC and NSEC3)</span></a>.</p></li> <li><p><em>CDS, CDNSKEY</em>: The CDS and CDNSKEY resource records apply to operational matters and are a way to signal to the parent zone that the DS records it holds for the child zone should be updated. This is covered in more detail in <a class="reference internal" href="#cds-cdnskey"><span class="std std-ref">The CDS and CDNSKEY Resource Records</span></a>.</p></li> </ul> </section> <section id="how-does-dnssec-change-dns-lookup"> <span id="id4"></span><h3>How Does DNSSEC Change DNS Lookup?<a class="headerlink" href="#how-does-dnssec-change-dns-lookup" title="Permalink to this headline"></a></h3> <p>Traditional (insecure) DNS lookup is simple: a recursive name server receives a query from a client to lookup a name like <code class="docutils literal notranslate"><span class="pre">www.isc.org</span></code>. The recursive name server tracks down the authoritative name server(s) responsible, sends the query to one of the authoritative name servers, and waits for it to respond with the answer.</p> <p>With DNSSEC validation enabled, a validating recursive name server (a.k.a. a <em>validating resolver</em>) asks for additional resource records in its query, hoping the remote authoritative name servers respond with more than just the answer to the query, but some proof to go along with the answer as well. If DNSSEC responses are received, the validating resolver performs cryptographic computation to verify the authenticity (the origin of the data) and integrity (that the data was not altered during transit) of the answers, and even asks the parent zone as part of the verification. It repeats this process of get-key, validate, ask-parent, and its parent, and its parent, all the way until the validating resolver reaches a key that it trusts. In the ideal, fully deployed world of DNSSEC, all validating resolvers only need to trust one key: the root key.</p> </section> <section id="the-12-step-dnssec-validation-process-simplified"> <span id="dnssec-12-steps"></span><h3>The 12-Step DNSSEC Validation Process (Simplified)<a class="headerlink" href="#the-12-step-dnssec-validation-process-simplified" title="Permalink to this headline"></a></h3> <p>The following example shows the 12 steps of the DNSSEC validating process at a very high level, looking up the name <code class="docutils literal notranslate"><span class="pre">www.isc.org</span></code> :</p> <figure class="align-default"> <img alt="DNSSEC Validation 12 Steps" src="_images/dnssec-12-steps.png" /> </figure> <ol class="arabic"> <li><p>Upon receiving a DNS query from a client to resolve <code class="docutils literal notranslate"><span class="pre">www.isc.org</span></code>, the validating resolver follows standard DNS protocol to track down the name server for <code class="docutils literal notranslate"><span class="pre">isc.org</span></code>, and sends it a DNS query to ask for the A record of <code class="docutils literal notranslate"><span class="pre">www.isc.org</span></code>. But since this is a DNSSEC-enabled resolver, the outgoing query has a bit set indicating it wants DNSSEC answers, hoping the name server that receives it is DNSSEC-enabled and can honor this secure request.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> name server is DNSSEC-enabled, so it responds with both the answer (in this case, an A record) and a digital signature for verification purposes.</p></li> <li><p>The validating resolver requires cryptographic keys to be able to verify the digital signature, so it asks the <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> name server for those keys.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> name server responds with the cryptographic keys (and digital signatures of the keys) used to generate the digital signature that was sent in #2. At this point, the validating resolver can use this information to verify the answers received in #2.</p> <p>Let’s take a quick break here and look at what we’ve got so far… how can our server trust this answer? If a clever attacker had taken over the <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> name server(s), of course she would send matching keys and signatures. We need to ask someone else to have confidence that we are really talking to the real <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> name server. This is a critical part of DNSSEC: at some point, the DNS administrators at <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> uploaded some cryptographic information to its parent, <code class="docutils literal notranslate"><span class="pre">.org</span></code>, maybe through a secure web form, maybe through an email exchange, or perhaps in person. In any event, at some point some verifiable information about the child (<code class="docutils literal notranslate"><span class="pre">isc.org</span></code>) was sent to the parent (<code class="docutils literal notranslate"><span class="pre">.org</span></code>) for safekeeping.</p> </li> <li><p>The validating resolver asks the parent (<code class="docutils literal notranslate"><span class="pre">.org</span></code>) for the verifiable information it keeps on its child, <code class="docutils literal notranslate"><span class="pre">isc.org</span></code>.</p></li> <li><p>Verifiable information is sent from the <code class="docutils literal notranslate"><span class="pre">.org</span></code> server. At this point, the validating resolver compares this to the answer it received in #4; if the two of them match, it proves the authenticity of <code class="docutils literal notranslate"><span class="pre">isc.org</span></code>.</p> <p>Let’s examine this process. You might be thinking to yourself, what if the clever attacker that took over <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> also compromised the <code class="docutils literal notranslate"><span class="pre">.org</span></code> servers? Of course all this information would match! That’s why we turn our attention now to the <code class="docutils literal notranslate"><span class="pre">.org</span></code> server, interrogate it for its cryptographic keys, and move one level up to <code class="docutils literal notranslate"><span class="pre">.org</span></code>’s parent, root.</p> </li> <li><p>The validating resolver asks the <code class="docutils literal notranslate"><span class="pre">.org</span></code> authoritative name server for its cryptographic keys, to verify the answers received in #6.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">.org</span></code> name server responds with the answer (in this case, keys and signatures). At this point, the validating resolver can verify the answers received in #6.</p></li> <li><p>The validating resolver asks root (<code class="docutils literal notranslate"><span class="pre">.org</span></code>’s parent) for the verifiable information it keeps on its child, <code class="docutils literal notranslate"><span class="pre">.org</span></code>.</p></li> <li><p>The root name server sends back the verifiable information it keeps on <code class="docutils literal notranslate"><span class="pre">.org</span></code>. The validating resolver uses this information to verify the answers received in #8.</p> <p>So at this point, both <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> and <code class="docutils literal notranslate"><span class="pre">.org</span></code> check out. But what about root? What if this attacker is really clever and somehow tricked us into thinking she’s the root name server? Of course she would send us all matching information! So we repeat the interrogation process and ask for the keys from the root name server.</p> </li> <li><p>The validating resolver asks the root name server for its cryptographic keys to verify the answer(s) received in #10.</p></li> <li><p>The root name server sends its keys; at this point, the validating resolver can verify the answer(s) received in #10.</p></li> </ol> </section> <section id="chain-of-trust"> <span id="id5"></span><h3>Chain of Trust<a class="headerlink" href="#chain-of-trust" title="Permalink to this headline"></a></h3> <p>But what about the root server itself? Who do we go to verify root’s keys? There’s no parent zone for root. In security, you have to trust someone, and in the perfectly protected world of DNSSEC (we talk later about the current imperfect state and ways to work around it), each validating resolver would only have to trust one entity, that is, the root name server. The validating resolver already has the root key on file (we discuss later how we got the root key file). So after the answer in #12 is received, the validating resolver compares it to the key it already has on file. Providing one of the keys in the answer matches the one on file, we can trust the answer from root. Thus we can trust <code class="docutils literal notranslate"><span class="pre">.org</span></code>, and thus we can trust <code class="docutils literal notranslate"><span class="pre">isc.org</span></code>. This is known as the “chain of trust” in DNSSEC.</p> <p>We revisit this 12-step process again later in <a class="reference internal" href="#how-does-dnssec-change-dns-lookup-revisited"><span class="std std-ref">How Does DNSSEC Change DNS Lookup (Revisited)?</span></a> with more technical details.</p> </section> <section id="why-is-dnssec-important-why-should-i-care"> <span id="why-is-dnssec-important"></span><h3>Why is DNSSEC Important? (Why Should I Care?)<a class="headerlink" href="#why-is-dnssec-important-why-should-i-care" title="Permalink to this headline"></a></h3> <p>You might be thinking to yourself: all this DNSSEC stuff sounds wonderful, but why should I care? Below are some reasons why you may want to consider deploying DNSSEC:</p> <ol class="arabic simple"> <li><p><em>Being a good netizen</em>: By enabling DNSSEC validation (as described in <a class="reference internal" href="#dnssec-validation"><span class="std std-ref">Validation</span></a>) on your DNS servers, you’re protecting your users and yourself a little more by checking answers returned to you; by signing your zones (as described in <a class="reference internal" href="#dnssec-signing"><span class="std std-ref">Signing</span></a>), you are making it possible for other people to verify your zone data. As more people adopt DNSSEC, the Internet as a whole becomes more secure for everyone.</p></li> <li><p><em>Compliance</em>: You may not even get a say in implementing DNSSEC, if your organization is subject to compliance standards that mandate it. For example, the US government set a deadline in 2008 to have all <code class="docutils literal notranslate"><span class="pre">.gov</span></code> subdomains signed by December 2009. <a class="footnote-reference brackets" href="#omb-memo" id="id6">1</a> So if you operate a subdomain in <code class="docutils literal notranslate"><span class="pre">.gov</span></code>, you must implement DNSSEC to be compliant. ICANN also requires that all new top-level domains support DNSSEC.</p></li> <li><p><em>Enhanced Security</em>: Okay, so the big lofty goal of “let’s be good” doesn’t appeal to you, and you don’t have any compliance standards to worry about. Here is a more practical reason why you should consider DNSSEC: in the event of a DNS-based security breach, such as cache poisoning or domain hijacking, after all the financial and brand damage done to your domain name, you might be placed under scrutiny for any preventive measure that could have been put in place. Think of this like having your website only available via HTTP but not HTTPS.</p></li> <li><p><em>New Features</em>: DNSSEC brings not only enhanced security, but also a whole new suite of features. Once DNS can be trusted completely, it becomes possible to publish SSL certificates in DNS, or PGP keys for fully automatic cross-platform email encryption, or SSH fingerprints…. New features are still being developed, but they all rely on a trustworthy DNS infrastructure. To take a peek at these next-generation DNS features, check out <a class="reference internal" href="#introduction-to-dane"><span class="std std-ref">Introduction to DANE</span></a>.</p></li> </ol> <dl class="footnote brackets"> <dt class="label" id="omb-memo"><span class="brackets"><a class="fn-backref" href="#id6">1</a></span></dt> <dd><p>The Office of Management and Budget (OMB) for the US government published <a class="reference external" href="https://georgewbush-whitehouse.archives.gov/omb/memoranda/fy2008/m08-23.pdf">a memo in 2008</a>, requesting all <code class="docutils literal notranslate"><span class="pre">.gov</span></code> subdomains to be DNSSEC-signed by December 2009. This explains why <code class="docutils literal notranslate"><span class="pre">.gov</span></code> is the most-deployed DNSSEC domain currently, with <a class="reference external" href="https://usgv6-deploymon.nist.gov/cgi-bin/generate-gov">around 90% of subdomains signed.</a></p> </dd> </dl> </section> <section id="how-does-dnssec-change-my-job-as-a-dns-administrator"> <span id="how-does-dnssec-change-my-job"></span><h3>How Does DNSSEC Change My Job as a DNS Administrator?<a class="headerlink" href="#how-does-dnssec-change-my-job-as-a-dns-administrator" title="Permalink to this headline"></a></h3> <p>With this protocol extension, some of the things you were used to in DNS have changed. As the DNS administrator, you have new maintenance tasks to perform on a regular basis (as described in <a class="reference internal" href="#signing-maintenance-tasks"><span class="std std-ref">Maintenance Tasks</span></a>); when there is a DNS resolution problem, you have new troubleshooting techniques and tools to use (as described in <a class="reference internal" href="#dnssec-troubleshooting"><span class="std std-ref">Basic DNSSEC Troubleshooting</span></a>). BIND 9 tries its best to make these things as transparent and seamless as possible. In this guide, we try to use configuration examples that result in the least amount of work for BIND 9 DNS administrators.</p> </section> </section> <section id="getting-started"> <span id="id7"></span><h2>Getting Started<a class="headerlink" href="#getting-started" title="Permalink to this headline"></a></h2> <section id="software-requirements"> <span id="id8"></span><h3>Software Requirements<a class="headerlink" href="#software-requirements" title="Permalink to this headline"></a></h3> <p>This guide assumes BIND 9.18.0 or newer, although the more elaborate manual procedures do work with all versions of BIND later than 9.9.</p> <p>We recommend running the latest stable version to get the most complete DNSSEC configuration, as well as the latest security fixes.</p> </section> <section id="hardware-requirements"> <span id="id9"></span><h3>Hardware Requirements<a class="headerlink" href="#hardware-requirements" title="Permalink to this headline"></a></h3> <section id="recursive-server-hardware"> <span id="id10"></span><h4>Recursive Server Hardware<a class="headerlink" href="#recursive-server-hardware" title="Permalink to this headline"></a></h4> <p>Enabling DNSSEC validation on a recursive server makes it a <em>validating resolver</em>. The job of a validating resolver is to fetch additional information that can be used to computationally verify the answer set. Contrary to popular belief, the increase in resource consumption is very modest:</p> <ol class="arabic simple"> <li><p><em>CPU</em>: a validating resolver executes cryptographic functions on cache-miss answers, which leads to increased CPU usage. Thanks to standard DNS caching and contemporary CPUs, the increase in CPU-time consumption in a steady state is negligible - typically on the order of 5%. For a brief period (a few minutes) after the resolver starts, the increase might be as much as 20%, but it quickly decreases as the DNS cache fills in.</p></li> <li><p><em>System memory</em>: DNSSEC leads to larger answer sets and occupies more memory space. With typical ISP traffic and the state of the Internet as of mid-2022, memory consumption for the cache increases by roughly 20%.</p></li> <li><p><em>Network interfaces</em>: although DNSSEC does increase the amount of DNS traffic overall, in practice this increase is often within measurement error.</p></li> </ol> </section> <section id="authoritative-server-hardware"> <span id="id11"></span><h4>Authoritative Server Hardware<a class="headerlink" href="#authoritative-server-hardware" title="Permalink to this headline"></a></h4> <p>On the authoritative server side, DNSSEC is enabled on a zone-by-zone basis. When a zone is DNSSEC-enabled, it is also known as “signed.” Below are the expected changes to resource consumption caused by serving DNSSEC-signed zones:</p> <ol class="arabic simple"> <li><p><em>CPU</em>: a DNSSEC-signed zone requires periodic re-signing, which is a cryptographic function that is CPU-intensive. If your DNS zone is dynamic or changes frequently, that also adds to higher CPU loads.</p></li> <li><p><em>System storage</em>: A signed zone is definitely larger than an unsigned zone. How much larger? See <a class="reference internal" href="#your-zone-before-and-after-dnssec"><span class="std std-ref">Your Zone, Before and After DNSSEC</span></a> for a comparison example. The final size depends on the structure of the zone, the signing algorithm, the number of keys, the choice of NSEC or NSEC3, the ratio of signed delegations, the zone file format, etc. Usually, the size of a signed zone ranges from a negligible increase to as much as three times the size of the unsigned zone.</p></li> <li><p><em>System memory</em>: Larger DNS zone files take up not only more storage space on the file system, but also more space when they are loaded into system memory. The final memory consumption also depends on all the variables listed above: in the typical case the increase is around half of the unsigned zone memory consumption, but it can be as high as three times for some corner cases.</p></li> <li><p><em>Network interfaces</em>: While your authoritative name servers will begin sending back larger responses, it is unlikely that you need to upgrade your network interface card (NIC) on the name server unless you have some truly outdated hardware.</p></li> </ol> <p>One factor to consider, but over which you really have no control, is the number of users who query your domain name who themselves have DNSSEC enabled. As of mid-2022, measurements by <a class="reference external" href="https://stats.labs.apnic.net/dnssec">APNIC</a> show 41% of Internet users send DNSSEC-aware queries. This means that more DNS queries for your domain will take advantage of the additional security features, which will result in increased system load and possibly network traffic.</p> </section> </section> <section id="network-requirements"> <span id="id12"></span><h3>Network Requirements<a class="headerlink" href="#network-requirements" title="Permalink to this headline"></a></h3> <p>From a network perspective, DNS and DNSSEC packets are very similar; DNSSEC packets are just bigger, which means DNS is more likely to use TCP. You should test for the following two items to make sure your network is ready for DNSSEC:</p> <ol class="arabic simple"> <li><p><em>DNS over TCP</em>: Verify network connectivity over TCP port 53, which may mean updating firewall policies or Access Control Lists (ACL) on routers. See <a class="reference internal" href="#dns-uses-tcp"><span class="std std-ref">Wait… DNS Uses TCP?</span></a> for more details.</p></li> <li><p><em>Large UDP packets</em>: Some network equipment, such as firewalls, may make assumptions about the size of DNS UDP packets and incorrectly reject DNS traffic that appears “too big.” Verify that the responses your name server generates are being seen by the rest of the world: see <a class="reference internal" href="#whats-edns0-all-about"><span class="std std-ref">What’s EDNS All About (And Why Should I Care)?</span></a> for more details.</p></li> </ol> </section> <section id="operational-requirements"> <span id="id13"></span><h3>Operational Requirements<a class="headerlink" href="#operational-requirements" title="Permalink to this headline"></a></h3> <section id="parent-zone"> <span id="id14"></span><h4>Parent Zone<a class="headerlink" href="#parent-zone" title="Permalink to this headline"></a></h4> <p>Before starting your DNSSEC deployment, check with your parent zone administrators to make sure they support DNSSEC. This may or may not be the same entity as your registrar. As you will see later in <a class="reference internal" href="#working-with-parent-zone"><span class="std std-ref">Working With the Parent Zone</span></a>, a crucial step in DNSSEC deployment is establishing the parent-child trust relationship. If your parent zone does not yet support DNSSEC, contact that administrator to voice your concerns.</p> </section> <section id="security-requirements"> <span id="id15"></span><h4>Security Requirements<a class="headerlink" href="#security-requirements" title="Permalink to this headline"></a></h4> <p>Some organizations may be subject to stricter security requirements than others. Check to see if your organization requires stronger cryptographic keys be generated and stored, and how often keys need to be rotated. The examples presented in this document are not intended for high-value zones. We cover some of these security considerations in <a class="reference internal" href="#dnssec-advanced-discussions"><span class="std std-ref">Advanced Discussions</span></a>.</p> </section> </section> </section> <section id="validation"> <span id="dnssec-validation"></span><h2>Validation<a class="headerlink" href="#validation" title="Permalink to this headline"></a></h2> <section id="easy-start-guide-for-recursive-servers"> <span id="id16"></span><h3>Easy-Start Guide for Recursive Servers<a class="headerlink" href="#easy-start-guide-for-recursive-servers" title="Permalink to this headline"></a></h3> <p>This section provides the basic information needed to set up a working DNSSEC-aware recursive server, also known as a validating resolver. A validating resolver performs validation for each remote response received, following the chain of trust to verify that the answers it receives are legitimate, through the use of public key cryptography and hashing functions.</p> <section id="enabling-dnssec-validation"> <span id="enabling-validation"></span><h4>Enabling DNSSEC Validation<a class="headerlink" href="#enabling-dnssec-validation" title="Permalink to this headline"></a></h4> <p>So how do we turn on DNSSEC validation? It turns out that you may not need to reconfigure your name server at all, since the most recent versions of BIND 9 - including packages and distributions - have shipped with DNSSEC validation enabled by default. Before making any configuration changes, check whether you already have DNSSEC validation enabled by following the steps described in <a class="reference internal" href="#how-to-test-recursive-server"><span class="std std-ref">So You Think You Are Validating (How To Test A Recursive Server)</span></a>.</p> <p>In earlier versions of BIND, including 9.11-ESV, DNSSEC validation must be explicitly enabled. To do this, you only need to add one line to the <a class="reference internal" href="reference.html#namedconf-statement-options" title="namedconf-statement-options"><code class="xref namedconf namedconf-ref docutils literal notranslate"><span class="pre">options</span></code></a> section of your configuration file:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">options</span> <span class="p">{</span> <span class="o">...</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">validation</span> <span class="n">auto</span><span class="p">;</span> <span class="o">...</span> <span class="p">};</span> </pre></div> </div> <p>Restart <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> or run <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-reconfig"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">reconfig</span></code></a>, and your recursive server is now happily validating each DNS response. If this does not work for you, you may have some other network-related configurations that need to be adjusted. Take a look at <a class="reference internal" href="#network-requirements"><span class="std std-ref">Network Requirements</span></a> to make sure your network is ready for DNSSEC.</p> </section> <section id="effects-of-enabling-dnssec-validation"> <span id="effect-of-enabling-validation"></span><h4>Effects of Enabling DNSSEC Validation<a class="headerlink" href="#effects-of-enabling-dnssec-validation" title="Permalink to this headline"></a></h4> <p>Once DNSSEC validation is enabled, any DNS response that does not pass the validation checks results in a failure to resolve the domain name (often a SERVFAIL status seen by the client). If everything has been configured properly, this is the correct result; it means that an end user has been protected against a malicious attack.</p> <p>However, if there is a DNSSEC configuration issue (sometimes outside of the administrator’s control), a specific name or sometimes entire domains may “disappear” from the DNS, and become unreachable through that resolver. For the end user, the issue may manifest itself as name resolution being slow or failing altogether; some parts of a URL not loading; or the web browser returning an error message indicating that the page cannot be displayed. For example, if root name servers were misconfigured with the wrong information about <code class="docutils literal notranslate"><span class="pre">.org</span></code>, it could cause all validation for <code class="docutils literal notranslate"><span class="pre">.org</span></code> domains to fail. To end users, it would appear that all <code class="docutils literal notranslate"><span class="pre">.org</span></code> web sites were out of service. <a class="footnote-reference brackets" href="#wrong-root-addr" id="id17">2</a> Should you encounter DNSSEC-related problems, don’t be tempted to disable validation; there is almost certainly a solution that leaves validation enabled. A basic troubleshooting guide can be found in <a class="reference internal" href="#dnssec-troubleshooting"><span class="std std-ref">Basic DNSSEC Troubleshooting</span></a>.</p> <dl class="footnote brackets"> <dt class="label" id="wrong-root-addr"><span class="brackets"><a class="fn-backref" href="#id17">2</a></span></dt> <dd><p>Of course, something like this could happen for reasons other than DNSSEC: for example, the root publishing the wrong addresses for the <code class="docutils literal notranslate"><span class="pre">.org</span></code> nameservers.</p> </dd> </dl> </section> </section> <section id="so-you-think-you-are-validating-how-to-test-a-recursive-server"> <span id="how-to-test-recursive-server"></span><h3>So You Think You Are Validating (How To Test A Recursive Server)<a class="headerlink" href="#so-you-think-you-are-validating-how-to-test-a-recursive-server" title="Permalink to this headline"></a></h3> <p>Now that you have reconfigured your recursive server and restarted it, how do you know that your recursive name server is actually verifying each DNS query? There are several ways to check, and we’ve listed a few of them below.</p> <section id="using-web-based-tools-to-verify"> <span id="using-web-based-tests-to-verify"></span><h4>Using Web-Based Tools to Verify<a class="headerlink" href="#using-web-based-tools-to-verify" title="Permalink to this headline"></a></h4> <p>For most people, the simplest way to check if a recursive name server is indeed validating DNS queries is to use one of the many web-based tools available.</p> <p>Configure your client computer to use the newly reconfigured recursive server for DNS resolution; then use one of these web-based tests to confirm that it is in fact validating DNS responses.</p> <ul class="simple"> <li><p><a class="reference external" href="http://conn.internet.nl/connection/">Internet.nl</a></p></li> <li><p><a class="reference external" href="https://www.dnssec-or-not.com/">DNSSEC or Not (VeriSign)</a></p></li> </ul> </section> <section id="using-dig-to-verify"> <span id="id18"></span><h4>Using <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> to Verify<a class="headerlink" href="#using-dig-to-verify" title="Permalink to this headline"></a></h4> <p>Web-based DNSSEC-verification tools often employ JavaScript. If you don’t trust the JavaScript magic that the web-based tools rely on, you can take matters into your own hands and use a command-line DNS tool to check your validating resolver yourself.</p> <p>While <a class="reference internal" href="manpages.html#std-iscman-nslookup"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nslookup</span></code></a> is popular, partly because it comes pre-installed on most systems, it is not DNSSEC-aware. <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a>, on the other hand, fully supports the DNSSEC standard and comes as a part of BIND. If you do not have <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> already installed on your system, install it by downloading it from ISC’s <a class="reference external" href="https://www.isc.org/download">website</a>. ISC provides pre-compiled Windows versions on its website.</p> <p><a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name servers that were queried. Most seasoned DNS administrators use <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> to troubleshoot DNS problems because of its flexibility, ease of use, and clarity of output.</p> <p>The example below shows how to use <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> to query the name server 10.53.0.1 for the A record for <code class="docutils literal notranslate"><span class="pre">ftp.isc.org</span></code> when DNSSEC validation is enabled (i.e. the default). The address 10.53.0.1 is only used as an example; replace it with the actual address or host name of your recursive name server.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.1 ftp.isc.org. A +dnssec +multiline ; <<>> DiG 9.16.0 <<>> @10.53.0.1 ftp.isc.org a +dnssec +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48742 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ; COOKIE: 29a9705c2160b08c010000005e67a4a102b9ae079c1b24c8 (good) ;; QUESTION SECTION: ;ftp.isc.org. IN A ;; ANSWER SECTION: ftp.isc.org. 300 IN A 149.20.1.49 ftp.isc.org. 300 IN RRSIG A 13 3 300 ( 20200401191851 20200302184340 27566 isc.org. e9Vkb6/6aHMQk/t23Im71ioiDUhB06sncsduoW9+Asl4 L3TZtpLvZ5+zudTJC2coI4D/D9AXte1cD6FV6iS6PQ== ) ;; Query time: 452 msec ;; SERVER: 10.53.0.1#53(10.53.0.1) ;; WHEN: Tue Mar 10 14:30:57 GMT 2020 ;; MSG SIZE rcvd: 187 </pre></div> </div> <p>The important detail in this output is the presence of the <code class="docutils literal notranslate"><span class="pre">ad</span></code> flag in the header. This signifies that BIND has retrieved all related DNSSEC information related to the target of the query (<code class="docutils literal notranslate"><span class="pre">ftp.isc.org</span></code>) and that the answer received has passed the validation process described in <a class="reference internal" href="#how-are-answers-verified"><span class="std std-ref">How Are Answers Verified?</span></a>. We can have confidence in the authenticity and integrity of the answer, that <code class="docutils literal notranslate"><span class="pre">ftp.isc.org</span></code> really points to the IP address 149.20.1.49, and that it was not a spoofed answer from a clever attacker.</p> <p>Unlike earlier versions of BIND, the current versions of BIND always request DNSSEC records (by setting the <code class="docutils literal notranslate"><span class="pre">do</span></code> bit in the query they make to upstream servers), regardless of DNSSEC settings. However, with validation disabled, the returned signature is not checked. This can be seen by explicitly disabling DNSSEC validation. To do this, add the line <code class="docutils literal notranslate"><span class="pre">dnssec-validation</span> <span class="pre">no;</span></code> to the “options” section of the configuration file, i.e.:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">options</span> <span class="p">{</span> <span class="o">...</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">validation</span> <span class="n">no</span><span class="p">;</span> <span class="o">...</span> <span class="p">};</span> </pre></div> </div> <p>If the server is restarted (to ensure a clean cache) and the same <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> command executed, the result is very similar:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.1 ftp.isc.org. A +dnssec +multiline ; <<>> DiG 9.16.0 <<>> @10.53.0.1 ftp.isc.org a +dnssec +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39050 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ; COOKIE: a8dc9d1b9ec45e75010000005e67a8a69399741fdbe126f2 (good) ;; QUESTION SECTION: ;ftp.isc.org. IN A ;; ANSWER SECTION: ftp.isc.org. 300 IN A 149.20.1.49 ftp.isc.org. 300 IN RRSIG A 13 3 300 ( 20200401191851 20200302184340 27566 isc.org. e9Vkb6/6aHMQk/t23Im71ioiDUhB06sncsduoW9+Asl4 L3TZtpLvZ5+zudTJC2coI4D/D9AXte1cD6FV6iS6PQ== ) ;; Query time: 261 msec ;; SERVER: 10.53.0.1#53(10.53.0.1) ;; WHEN: Tue Mar 10 14:48:06 GMT 2020 ;; MSG SIZE rcvd: 187 </pre></div> </div> <p>However, this time there is no <code class="docutils literal notranslate"><span class="pre">ad</span></code> flag in the header. Although <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> is still returning the DNSSEC-related resource records, it is not checking them, and thus cannot vouch for the authenticity of the answer. If you do carry out this test, remember to re-enable DNSSEC validation (by removing the <code class="docutils literal notranslate"><span class="pre">dnssec-validation</span> <span class="pre">no;</span></code> line from the configuration file) before continuing.</p> </section> </section> <section id="verifying-protection-from-bad-domain-names"> <span id="verifying-protection-from-bad-domains"></span><h3>Verifying Protection From Bad Domain Names<a class="headerlink" href="#verifying-protection-from-bad-domain-names" title="Permalink to this headline"></a></h3> <p>It is also important to make sure that DNSSEC is protecting your network from domain names that fail to validate; such failures could be caused by attacks on your system, attempting to get it to accept false DNS information. Validation could fail for a number of reasons: maybe the answer doesn’t verify because it’s a spoofed response; maybe the signature was a replayed network attack that has expired; or maybe the child zone has been compromised along with its keys, and the parent zone’s information tells us that things don’t add up. There is a domain name specifically set up to fail DNSSEC validation, <code class="docutils literal notranslate"><span class="pre">www.dnssec-failed.org</span></code>.</p> <p>With DNSSEC validation enabled (the default), an attempt to look up that name fails:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.1 www.dnssec-failed.org. A ; <<>> DiG 9.16.0 <<>> @10.53.0.1 www.dnssec-failed.org. A ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 22667 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 69c3083144854587010000005e67bb57f5f90ff2688e455d (good) ;; QUESTION SECTION: ;www.dnssec-failed.org. IN A ;; Query time: 2763 msec ;; SERVER: 10.53.0.1#53(10.53.0.1) ;; WHEN: Tue Mar 10 16:07:51 GMT 2020 ;; MSG SIZE rcvd: 78 </pre></div> </div> <p>On the other hand, if DNSSEC validation is disabled (by adding the statement <code class="docutils literal notranslate"><span class="pre">dnssec-validation</span> <span class="pre">no;</span></code> to the <a class="reference internal" href="reference.html#namedconf-statement-options" title="namedconf-statement-options"><code class="xref namedconf namedconf-ref docutils literal notranslate"><span class="pre">options</span></code></a> clause in the configuration file), the lookup succeeds:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.1 www.dnssec-failed.org. A ; <<>> DiG 9.16.0 <<>> @10.53.0.1 www.dnssec-failed.org. A ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54704 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 251eee58208917f9010000005e67bb6829f6dabc5ae6b7b9 (good) ;; QUESTION SECTION: ;www.dnssec-failed.org. IN A ;; ANSWER SECTION: www.dnssec-failed.org. 7200 IN A 68.87.109.242 www.dnssec-failed.org. 7200 IN A 69.252.193.191 ;; Query time: 439 msec ;; SERVER: 10.53.0.1#53(10.53.0.1) ;; WHEN: Tue Mar 10 16:08:08 GMT 2020 ;; MSG SIZE rcvd: 110 </pre></div> </div> <p>Do not be tempted to disable DNSSEC validation just because some names are failing to resolve. Remember, DNSSEC protects your DNS lookup from hacking. The next section describes how to quickly check whether the failure to successfully look up a name is due to a validation failure.</p> <section id="how-do-i-know-i-have-a-validation-problem"> <span id="how-do-i-know-validation-problem"></span><h4>How Do I Know I Have a Validation Problem?<a class="headerlink" href="#how-do-i-know-i-have-a-validation-problem" title="Permalink to this headline"></a></h4> <p>Since all DNSSEC validation failures result in a general <code class="docutils literal notranslate"><span class="pre">SERVFAIL</span></code> message, how do we know if it was really a validation error? Fortunately, there is a flag in <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a>, (“CD” for “checking disabled”) which tells the server to disable DNSSEC validation. If you receive a <code class="docutils literal notranslate"><span class="pre">SERVFAIL</span></code> message, re-run the query a second time and set the <a class="reference internal" href="manpages.html#cmdoption-dig-arg-cd"><code class="xref std std-option docutils literal notranslate"><span class="pre">dig</span> <span class="pre">+cd</span></code></a> flag. If the query succeeds with <a class="reference internal" href="manpages.html#cmdoption-dig-arg-cd"><code class="xref std std-option docutils literal notranslate"><span class="pre">dig</span> <span class="pre">+cd</span></code></a>, but ends in <code class="docutils literal notranslate"><span class="pre">SERVFAIL</span></code> without it, you know you are dealing with a validation problem. So using the previous example of <code class="docutils literal notranslate"><span class="pre">www.dnssec-failed.org</span></code> and with DNSSEC validation enabled in the resolver:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.1 www.dnssec-failed.org A +cd ; <<>> DiG 9.16.0 <<>> @10.53.0.1 www.dnssec-failed.org. A +cd ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62313 ;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 73ca1be3a74dd2cf010000005e67c8c8e6df64b519cd87fd (good) ;; QUESTION SECTION: ;www.dnssec-failed.org. IN A ;; ANSWER SECTION: www.dnssec-failed.org. 7197 IN A 68.87.109.242 www.dnssec-failed.org. 7197 IN A 69.252.193.191 ;; Query time: 0 msec ;; SERVER: 10.53.0.1#53(10.53.0.1) ;; WHEN: Tue Mar 10 17:05:12 GMT 2020 ;; MSG SIZE rcvd: 110 </pre></div> </div> <p>For more information on troubleshooting, please see <a class="reference internal" href="#dnssec-troubleshooting"><span class="std std-ref">Basic DNSSEC Troubleshooting</span></a>.</p> </section> </section> <section id="validation-easy-start-explained"> <span id="id19"></span><h3>Validation Easy Start Explained<a class="headerlink" href="#validation-easy-start-explained" title="Permalink to this headline"></a></h3> <p>In <a class="reference internal" href="#easy-start-guide-for-recursive-servers"><span class="std std-ref">Easy-Start Guide for Recursive Servers</span></a>, we used one line of configuration to turn on DNSSEC validation: the act of chasing down signatures and keys, making sure they are authentic. Now we are going to take a closer look at what DNSSEC validation actually does, and some other options.</p> <section id="dnssec-validation-explained"> <span id="id20"></span><h4><a class="reference internal" href="reference.html#namedconf-statement-dnssec-validation" title="namedconf-statement-dnssec-validation"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-validation</span></code></a><a class="headerlink" href="#dnssec-validation-explained" title="Permalink to this headline"></a></h4> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">options</span> <span class="p">{</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">validation</span> <span class="n">auto</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p>This “auto” line enables automatic DNSSEC trust anchor configuration using the <a class="reference internal" href="reference.html#namedconf-statement-managed-keys" title="namedconf-statement-managed-keys"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">managed-keys</span></code></a> feature. In this case, no manual key configuration is needed. There are three possible choices for the <a class="reference internal" href="reference.html#namedconf-statement-dnssec-validation" title="namedconf-statement-dnssec-validation"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-validation</span></code></a> option:</p> <ul class="simple"> <li><p><em>yes</em>: DNSSEC validation is enabled, but a trust anchor must be manually configured. No validation actually takes place until at least one trusted key has been manually configured.</p></li> <li><p><em>no</em>: DNSSEC validation is disabled, and the recursive server behaves in the “old-fashioned” way of performing insecure DNS lookups.</p></li> <li><p><em>auto</em>: DNSSEC validation is enabled, and a default trust anchor (included as part of BIND 9) for the DNS root zone is used. This is the default; BIND automatically does this if there is no <a class="reference internal" href="reference.html#namedconf-statement-dnssec-validation" title="namedconf-statement-dnssec-validation"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-validation</span></code></a> line in the configuration file.</p></li> </ul> <p>Let’s discuss the difference between <em>yes</em> and <em>auto</em>. If set to <em>yes</em>, the trust anchor must be manually defined and maintained using the <a class="reference internal" href="reference.html#namedconf-statement-trust-anchors" title="namedconf-statement-trust-anchors"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">trust-anchors</span></code></a> statement (with either the <code class="docutils literal notranslate"><span class="pre">static-key</span></code> or <code class="docutils literal notranslate"><span class="pre">static-ds</span></code> modifier) in the configuration file; if set to <em>auto</em> (the default, and as shown in the example), then no further action should be required as BIND includes a copy <a class="footnote-reference brackets" href="#root-zone-key-update" id="id21">4</a> of the root key. When set to <em>auto</em>, BIND automatically keeps the keys (also known as trust anchors, discussed in <a class="reference internal" href="#trust-anchors-description"><span class="std std-ref">Trust Anchors</span></a>) up-to-date without intervention from the DNS administrator.</p> <p>We recommend using the default <em>auto</em> unless there is a good reason to require a manual trust anchor. To learn more about trust anchors, please refer to <a class="reference internal" href="#trusted-keys-and-managed-keys"><span class="std std-ref">Trusted Keys and Managed Keys</span></a>.</p> </section> <section id="how-does-dnssec-change-dns-lookup-revisited"> <span id="id22"></span><h4>How Does DNSSEC Change DNS Lookup (Revisited)?<a class="headerlink" href="#how-does-dnssec-change-dns-lookup-revisited" title="Permalink to this headline"></a></h4> <p>Now you’ve enabled validation on your recursive name server and verified that it works. What exactly changed? In <a class="reference internal" href="#how-does-dnssec-change-dns-lookup"><span class="std std-ref">How Does DNSSEC Change DNS Lookup?</span></a> we looked at a very high-level, simplified version of the 12 steps of the DNSSEC validation process. Let’s revisit that process now and see what your validating resolver is doing in more detail. Again, as an example we are looking up the A record for the domain name <code class="docutils literal notranslate"><span class="pre">www.isc.org</span></code> (see <a class="reference internal" href="#dnssec-12-steps"><span class="std std-ref">The 12-Step DNSSEC Validation Process (Simplified)</span></a>):</p> <ol class="arabic simple"> <li><p>The validating resolver queries the <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> name servers for the A record of <code class="docutils literal notranslate"><span class="pre">www.isc.org</span></code>. This query has the <code class="docutils literal notranslate"><span class="pre">DNSSEC</span> <span class="pre">OK</span></code> (<code class="docutils literal notranslate"><span class="pre">do</span></code>) bit set to 1, notifying the remote authoritative server that DNSSEC answers are desired.</p></li> <li><p>Since the zone <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> is signed, and its name servers are DNSSEC-aware, it responds with the answer to the A record query plus the RRSIG for the A record.</p></li> <li><p>The validating resolver queries for the DNSKEY for <code class="docutils literal notranslate"><span class="pre">isc.org</span></code>.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">isc.org</span></code> name server responds with the DNSKEY and RRSIG records. The DNSKEY is used to verify the answers received in #2.</p></li> <li><p>The validating resolver queries the parent (<code class="docutils literal notranslate"><span class="pre">.org</span></code>) for the DS record for <code class="docutils literal notranslate"><span class="pre">isc.org</span></code>.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">.org</span></code> name server is also DNSSEC-aware, so it responds with the DS and RRSIG records. The DS record is used to verify the answers received in #4.</p></li> <li><p>The validating resolver queries for the DNSKEY for <code class="docutils literal notranslate"><span class="pre">.org</span></code>.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">.org</span></code> name server responds with its DNSKEY and RRSIG. The DNSKEY is used to verify the answers received in #6.</p></li> <li><p>The validating resolver queries the parent (root) for the DS record for <code class="docutils literal notranslate"><span class="pre">.org</span></code>.</p></li> <li><p>The root name server, being DNSSEC-aware, responds with DS and RRSIG records. The DS record is used to verify the answers received in #8.</p></li> <li><p>The validating resolver queries for the DNSKEY for root.</p></li> <li><p>The root name server responds with its DNSKEY and RRSIG. The DNSKEY is used to verify the answers received in #10.</p></li> </ol> <p>After step #12, the validating resolver takes the DNSKEY received and compares it to the key or keys it has configured, to decide whether the received key can be trusted. We talk about these locally configured keys, or trust anchors, in <a class="reference internal" href="#trust-anchors-description"><span class="std std-ref">Trust Anchors</span></a>.</p> <p>With DNSSEC, every response includes not just the answer, but a digital signature (RRSIG) as well, so the validating resolver can verify the answer received. That is what we look at in the next section, <a class="reference internal" href="#how-are-answers-verified"><span class="std std-ref">How Are Answers Verified?</span></a>.</p> </section> <section id="how-are-answers-verified"> <span id="id23"></span><h4>How Are Answers Verified?<a class="headerlink" href="#how-are-answers-verified" title="Permalink to this headline"></a></h4> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Keep in mind, as you read this section, that although words like “encryption” and “decryption” are used here from time to time, DNSSEC does not provide privacy. Public key cryptography is used to verify data <em>authenticity</em> (who sent it) and data <em>integrity</em> (it did not change during transit), but any eavesdropper can still see DNS requests and responses in clear text, even when DNSSEC is enabled.</p> </div> <p>So how exactly are DNSSEC answers verified? Let’s first see how verifiable information is generated. On the authoritative server, each DNS record (or message) is run through a hash function, and this hashed value is then encrypted by a private key. This encrypted hash value is the digital signature.</p> <figure class="align-default" id="id52"> <a class="reference internal image-reference" href="_images/signature-generation.png"><img alt="Signature Generation" src="_images/signature-generation.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Signature Generation</span><a class="headerlink" href="#id52" title="Permalink to this image"></a></p> </figcaption> </figure> <p>When the validating resolver queries for the resource record, it receives both the plain-text message and the digital signature(s). The validating resolver knows the hash function used (it is listed in the digital signature record itself), so it can take the plain-text message and run it through the same hash function to produce a hashed value, which we’ll call hash value X. The validating resolver can also obtain the public key (published as DNSKEY records), decrypt the digital signature, and get back the original hashed value produced by the authoritative server, which we’ll call hash value Y. If hash values X and Y are identical, and the time is correct (more on what this means below), the answer is verified, meaning this answer came from the authoritative server (authenticity), and the content remained intact during transit (integrity).</p> <figure class="align-default" id="id53"> <a class="reference internal image-reference" href="_images/signature-verification.png"><img alt="Signature Verification" src="_images/signature-verification.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Signature Verification</span><a class="headerlink" href="#id53" title="Permalink to this image"></a></p> </figcaption> </figure> <p>Take the A record <code class="docutils literal notranslate"><span class="pre">ftp.isc.org</span></code>, for example. The plain text is:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">.</span> <span class="mi">4</span> <span class="n">IN</span> <span class="n">A</span> <span class="mf">149.20.1.49</span> </pre></div> </div> <p>The digital signature portion is:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">A</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">300</span> <span class="p">(</span> <span class="mi">20200401191851</span> <span class="mi">20200302184340</span> <span class="mi">27566</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">.</span> <span class="n">e9Vkb6</span><span class="o">/</span><span class="mi">6</span><span class="n">aHMQk</span><span class="o">/</span><span class="n">t23Im71ioiDUhB06sncsduoW9</span><span class="o">+</span><span class="n">Asl4</span> <span class="n">L3TZtpLvZ5</span><span class="o">+</span><span class="n">zudTJC2coI4D</span><span class="o">/</span><span class="n">D9AXte1cD6FV6iS6PQ</span><span class="o">==</span> <span class="p">)</span> </pre></div> </div> <p>When a validating resolver queries for the A record <code class="docutils literal notranslate"><span class="pre">ftp.isc.org</span></code>, it receives both the A record and the RRSIG record. It runs the A record through a hash function (in this example, SHA256 as indicated by the number 13, signifying ECDSAP256SHA256) and produces hash value X. The resolver also fetches the appropriate DNSKEY record to decrypt the signature, and the result of the decryption is hash value Y.</p> <p>But wait, there’s more! Just because X equals Y doesn’t mean everything is good. We still have to look at the time. Remember we mentioned a little earlier that we need to check if the time is correct? Look at the two timestamps in our example above:</p> <ul class="simple"> <li><p>Signature Expiration: 20200401191851</p></li> <li><p>Signature Inception: 20200302184340</p></li> </ul> <p>This tells us that this signature was generated UTC March 2nd, 2020, at 6:43:40 PM (20200302184340), and it is good until UTC April 1st, 2020, 7:18:51 PM (20200401191851). The validating resolver’s current system time needs to fall between these two timestamps. If it does not, the validation fails, because it could be an attacker replaying an old captured answer set from the past, or feeding us a crafted one with incorrect future timestamps.</p> <p>If the answer passes both the hash value check and the timestamp check, it is validated and the authenticated data (<code class="docutils literal notranslate"><span class="pre">ad</span></code>) bit is set, and the response is sent to the client; if it does not verify, a SERVFAIL is returned to the client.</p> </section> </section> <section id="trust-anchors"> <span id="trust-anchors-description"></span><h3>Trust Anchors<a class="headerlink" href="#trust-anchors" title="Permalink to this headline"></a></h3> <p>A trust anchor is a key that is placed into a validating resolver, so that the validator can verify the results of a given request with a known or trusted public key (the trust anchor). A validating resolver must have at least one trust anchor installed to perform DNSSEC validation.</p> </section> <section id="how-trust-anchors-are-used"> <span id="id24"></span><h3>How Trust Anchors are Used<a class="headerlink" href="#how-trust-anchors-are-used" title="Permalink to this headline"></a></h3> <p>In the section <a class="reference internal" href="#how-does-dnssec-change-dns-lookup-revisited"><span class="std std-ref">How Does DNSSEC Change DNS Lookup (Revisited)?</span></a>, we walked through the 12 steps of the DNSSEC lookup process. At the end of the 12 steps, a critical comparison happens: the key received from the remote server and the key we have on file are compared to see if we trust it. The key we have on file is called a trust anchor, sometimes also known as a trust key, trust point, or secure entry point.</p> <p>The 12-step lookup process describes the DNSSEC lookup in the ideal world, where every single domain name is signed and properly delegated, and where each validating resolver only needs to have one trust anchor - that is, the root’s public key. But there is no restriction that the validating resolver must only have one trust anchor. In fact, in the early stages of DNSSEC adoption, it was not unusual for a validating resolver to have more than one trust anchor.</p> <p>For instance, before the root zone was signed (in July 2010), some validating resolvers that wished to validate domain names in the <code class="docutils literal notranslate"><span class="pre">.gov</span></code> zone needed to obtain and install the key for <code class="docutils literal notranslate"><span class="pre">.gov</span></code>. A sample lookup process for <code class="docutils literal notranslate"><span class="pre">www.fbi.gov</span></code> at that time would have been eight steps rather than 12:</p> <figure class="align-default"> <img alt="DNSSEC Validation with ``.gov`` Trust Anchor" src="_images/dnssec-8-steps.png" /> </figure> <ol class="arabic simple"> <li><p>The validating resolver queried <code class="docutils literal notranslate"><span class="pre">fbi.gov</span></code> name server for the A record of <code class="docutils literal notranslate"><span class="pre">www.fbi.gov</span></code>.</p></li> <li><p>The FBI’s name server responded with the answer and its RRSIG.</p></li> <li><p>The validating resolver queried the FBI’s name server for its DNSKEY.</p></li> <li><p>The FBI’s name server responded with the DNSKEY and its RRSIG.</p></li> <li><p>The validating resolver queried a <code class="docutils literal notranslate"><span class="pre">.gov</span></code> name server for the DS record of <code class="docutils literal notranslate"><span class="pre">fbi.gov</span></code>.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">.gov</span></code> name server responded with the DS record and the associated RRSIG for <code class="docutils literal notranslate"><span class="pre">fbi.gov</span></code>.</p></li> <li><p>The validating resolver queried the <code class="docutils literal notranslate"><span class="pre">.gov</span></code> name server for its DNSKEY.</p></li> <li><p>The <code class="docutils literal notranslate"><span class="pre">.gov</span></code> name server responded with its DNSKEY and the associated RRSIG.</p></li> </ol> <p>This all looks very similar, except it’s shorter than the 12 steps that we saw earlier. Once the validating resolver receives the DNSKEY file in #8, it recognizes that this is the manually configured trusted key (trust anchor), and never goes to the root name servers to ask for the DS record for <code class="docutils literal notranslate"><span class="pre">.gov</span></code>, or ask the root name servers for their DNSKEY.</p> <p>In fact, whenever the validating resolver receives a DNSKEY, it checks to see if this is a configured trusted key to decide whether it needs to continue chasing down the validation chain.</p> <section id="trusted-keys-and-managed-keys"> <span id="id25"></span><h4>Trusted Keys and Managed Keys<a class="headerlink" href="#trusted-keys-and-managed-keys" title="Permalink to this headline"></a></h4> <p>Since the resolver is validating, we must have at least one key (trust anchor) configured. How did it get here, and how do we maintain it?</p> <p>If you followed the recommendation in <a class="reference internal" href="#easy-start-guide-for-recursive-servers"><span class="std std-ref">Easy-Start Guide for Recursive Servers</span></a>, by setting <a class="reference internal" href="reference.html#namedconf-statement-dnssec-validation" title="namedconf-statement-dnssec-validation"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-validation</span></code></a> to <em>auto</em>, there is nothing left to do. BIND already includes a copy of the root key (in the file <code class="docutils literal notranslate"><span class="pre">bind.keys</span></code>), <a class="footnote-reference brackets" href="#bind-keys" id="id26">3</a> and automatically updates it when the root key changes. <a class="footnote-reference brackets" href="#root-zone-key-update" id="id27">4</a> It looks something like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">trust</span><span class="o">-</span><span class="n">anchors</span> <span class="p">{</span> <span class="c1"># This key (20326) was published in the root zone in 2017.</span> <span class="o">.</span> <span class="n">initial</span><span class="o">-</span><span class="n">key</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">8</span> <span class="s2">"AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3</span> <span class="o">+/</span><span class="mi">4</span><span class="n">RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4</span><span class="o">+</span><span class="n">B5xQlNVz8Og8kv</span> <span class="n">ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF</span> <span class="mi">0</span><span class="n">jLHwVN8efS3rCj</span><span class="o">/</span><span class="n">EWgvIWgb9tarpVUDK</span><span class="o">/</span><span class="n">b58Da</span><span class="o">+</span><span class="n">sqqls3eNbuv7pr</span><span class="o">+</span><span class="n">e</span> <span class="n">oZG</span><span class="o">+</span><span class="n">SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4</span><span class="o">/</span><span class="n">ilBmSVIzuDWfd</span> <span class="n">RUfhHdY6</span><span class="o">+</span><span class="n">cn8HFRm</span><span class="o">+</span><span class="mi">2</span><span class="n">hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN</span> <span class="n">R1AkUTV74bU</span><span class="o">=</span><span class="s2">";</span> <span class="p">};</span> </pre></div> </div> <p>You can, of course, decide to manage this key manually yourself. First, you need to make sure that <a class="reference internal" href="reference.html#namedconf-statement-dnssec-validation" title="namedconf-statement-dnssec-validation"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-validation</span></code></a> is set to <em>yes</em> rather than <em>auto</em>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">options</span> <span class="p">{</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">validation</span> <span class="n">yes</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p>Then, download the root key manually from a trustworthy source, such as <a class="reference external" href="https://www.isc.org/bind-keys">https://www.isc.org/bind-keys</a>. Finally, take the root key you manually downloaded and put it into a <a class="reference internal" href="reference.html#namedconf-statement-trust-anchors" title="namedconf-statement-trust-anchors"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">trust-anchors</span></code></a> statement as shown below:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">trust</span><span class="o">-</span><span class="n">anchors</span> <span class="p">{</span> <span class="c1"># This key (20326) was published in the root zone in 2017.</span> <span class="o">.</span> <span class="n">static</span><span class="o">-</span><span class="n">key</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">8</span> <span class="s2">"AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3</span> <span class="o">+/</span><span class="mi">4</span><span class="n">RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4</span><span class="o">+</span><span class="n">B5xQlNVz8Og8kv</span> <span class="n">ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF</span> <span class="mi">0</span><span class="n">jLHwVN8efS3rCj</span><span class="o">/</span><span class="n">EWgvIWgb9tarpVUDK</span><span class="o">/</span><span class="n">b58Da</span><span class="o">+</span><span class="n">sqqls3eNbuv7pr</span><span class="o">+</span><span class="n">e</span> <span class="n">oZG</span><span class="o">+</span><span class="n">SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4</span><span class="o">/</span><span class="n">ilBmSVIzuDWfd</span> <span class="n">RUfhHdY6</span><span class="o">+</span><span class="n">cn8HFRm</span><span class="o">+</span><span class="mi">2</span><span class="n">hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN</span> <span class="n">R1AkUTV74bU</span><span class="o">=</span><span class="s2">";</span> <span class="p">};</span> </pre></div> </div> <p>While this <a class="reference internal" href="reference.html#namedconf-statement-trust-anchors" title="namedconf-statement-trust-anchors"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">trust-anchors</span></code></a> statement and the one in the <code class="docutils literal notranslate"><span class="pre">bind.keys</span></code> file appear similar, the definition of the key in <code class="docutils literal notranslate"><span class="pre">bind.keys</span></code> has the <code class="docutils literal notranslate"><span class="pre">initial-key</span></code> modifier, whereas in the statement in the configuration file, that is replaced by <code class="docutils literal notranslate"><span class="pre">static-key</span></code>. There is an important difference between the two: a key defined with <code class="docutils literal notranslate"><span class="pre">static-key</span></code> is always trusted until it is deleted from the configuration file. With the <code class="docutils literal notranslate"><span class="pre">initial-key</span></code> modified, keys are only trusted once: for as long as it takes to load the managed key database and start the key maintenance process. Thereafter, BIND uses the managed keys database (<code class="docutils literal notranslate"><span class="pre">managed-keys.bind.jnl</span></code>) as the source of key information.</p> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>Remember, if you choose to manage the keys on your own, whenever the key changes (which, for most zones, happens on a periodic basis), the configuration needs to be updated manually. Failure to do so will result in breaking nearly all DNS queries for the subdomain of the key. So if you are manually managing <code class="docutils literal notranslate"><span class="pre">.gov</span></code>, all domain names in the <code class="docutils literal notranslate"><span class="pre">.gov</span></code> space may become unresolvable; if you are manually managing the root key, you could break all DNS requests made to your recursive name server.</p> </div> <p>Explicit management of keys was common in the early days of DNSSEC, when neither the root zone nor many top-level domains were signed. Since then, <a class="reference external" href="https://ithi.research.icann.org/graph-m7.html">over 90%</a> of the top-level domains have been signed, including all the largest ones. Unless you have a particular need to manage keys yourself, it is best to use the BIND defaults and let the software manage the root key.</p> <dl class="footnote brackets"> <dt class="label" id="bind-keys"><span class="brackets"><a class="fn-backref" href="#id26">3</a></span></dt> <dd><p>BIND technically includes two copies of the root key: one is in <code class="docutils literal notranslate"><span class="pre">bind.keys.h</span></code> and is built into the executable, and one is in <code class="docutils literal notranslate"><span class="pre">bind.keys</span></code> as a <a class="reference internal" href="reference.html#namedconf-statement-trust-anchors" title="namedconf-statement-trust-anchors"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">trust-anchors</span></code></a> statement. The two copies of the key are identical.</p> </dd> <dt class="label" id="root-zone-key-update"><span class="brackets">4</span><span class="fn-backref">(<a href="#id21">1</a>,<a href="#id27">2</a>)</span></dt> <dd><p>The root zone was signed in July 2010 and, as at the time of this writing (mid-2020), the key has been changed once, in October 2018. The intention going forward is to roll the key once every five years.</p> </dd> </dl> </section> </section> <section id="what-s-edns-all-about-and-why-should-i-care"> <span id="whats-edns0-all-about"></span><h3>What’s EDNS All About (And Why Should I Care)?<a class="headerlink" href="#what-s-edns-all-about-and-why-should-i-care" title="Permalink to this headline"></a></h3> <section id="edns-overview"> <span id="whats-edns0-all-about-overview"></span><h4>EDNS Overview<a class="headerlink" href="#edns-overview" title="Permalink to this headline"></a></h4> <p>Traditional DNS responses are typically small in size (less than 512 bytes) and fit nicely into a small UDP packet. The Extension mechanism for DNS (EDNS, or EDNS(0)) offers a mechanism to send DNS data in larger packets over UDP. To support EDNS, both the DNS server and the network need to be properly prepared to support the larger packet sizes and multiple fragments.</p> <p>This is important for DNSSEC, since the <a class="reference internal" href="manpages.html#cmdoption-dig-arg-dnssec"><code class="xref std std-option docutils literal notranslate"><span class="pre">dig</span> <span class="pre">+do</span></code></a> bit that signals DNSSEC-awareness is carried within EDNS, and DNSSEC responses are larger than traditional DNS ones. If DNS servers and the network environment cannot support large UDP packets, it will cause retransmission over TCP, or the larger UDP responses will be discarded. Users will likely experience slow DNS resolution or be unable to resolve certain names at all.</p> <p>Note that EDNS applies regardless of whether you are validating DNSSEC, because BIND has DNSSEC enabled by default.</p> <p>Please see <a class="reference internal" href="#network-requirements"><span class="std std-ref">Network Requirements</span></a> for more information on what DNSSEC expects from the network environment.</p> </section> <section id="edns-on-dns-servers"> <span id="id28"></span><h4>EDNS on DNS Servers<a class="headerlink" href="#edns-on-dns-servers" title="Permalink to this headline"></a></h4> <p>For many years, BIND has had EDNS enabled by default, and the UDP packet size is set to a maximum of 4096 bytes. The DNS administrator should not need to perform any reconfiguration. You can use <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> to verify that your server supports EDNS and see the UDP packet size it allows with this <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> command:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.1 www.isc.org. A +dnssec +multiline ; <<>> DiG 9.16.0 <<>> @10.53.0.1 ftp.isc.org a +dnssec +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48742 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ; COOKIE: 29a9705c2160b08c010000005e67a4a102b9ae079c1b24c8 (good) ;; QUESTION SECTION: ;ftp.isc.org. IN A ;; ANSWER SECTION: ftp.isc.org. 300 IN A 149.20.1.49 ftp.isc.org. 300 IN RRSIG A 13 3 300 ( 20200401191851 20200302184340 27566 isc.org. e9Vkb6/6aHMQk/t23Im71ioiDUhB06sncsduoW9+Asl4 L3TZtpLvZ5+zudTJC2coI4D/D9AXte1cD6FV6iS6PQ== ) ;; Query time: 452 msec ;; SERVER: 10.53.0.1#53(10.53.0.1) ;; WHEN: Tue Mar 10 14:30:57 GMT 2020 ;; MSG SIZE rcvd: 187 </pre></div> </div> <p>There is a helpful testing tool available (provided by DNS-OARC) that you can use to verify resolver behavior regarding EDNS support: <a class="reference external" href="https://www.dns-oarc.net/oarc/services/replysizetest/">https://www.dns-oarc.net/oarc/services/replysizetest/</a> .</p> <p>Once you’ve verified that your name servers have EDNS enabled, that should be the end of the story, right? Unfortunately, EDNS is a hop-by-hop extension to DNS. This means the use of EDNS is negotiated between each pair of hosts in a DNS resolution process, which in turn means if one of your upstream name servers (for instance, your ISP’s recursive name server that your name server forwards to) does not support EDNS, you may experience DNS lookup failures or be unable to perform DNSSEC validation.</p> </section> <section id="support-for-large-packets-on-network-equipment"> <span id="support-for-large-packets-network-equipment"></span><h4>Support for Large Packets on Network Equipment<a class="headerlink" href="#support-for-large-packets-on-network-equipment" title="Permalink to this headline"></a></h4> <p>If both your recursive name server and your ISP’s name servers support EDNS, we are all good here, right? Not so fast. Since these large packets have to traverse the network, the network infrastructure itself must allow them to pass.</p> <p>When data is physically transmitted over a network, it has to be broken down into chunks. The size of the data chunk is known as the Maximum Transmission Unit (MTU), and it can differ from network to network. IP fragmentation occurs when a large data packet needs to be broken down into chunks smaller than the MTU; these smaller chunks then need to be reassembled back into the large data packet at their destination. IP fragmentation is not necessarily a bad thing, and it most likely occurs on your network today.</p> <p>Some network equipment, such as a firewall, may make assumptions about DNS traffic. One of these assumptions may be how large each DNS packet is. When a firewall sees a larger DNS packet than it expects, it may either reject the large packet or drop its fragments because the firewall thinks it’s an attack. This configuration probably didn’t cause problems in the past, since traditional DNS packets are usually pretty small in size. However, with DNSSEC, these configurations need to be updated, since DNSSEC traffic regularly exceeds 1500 bytes (a common MTU value). If the configuration is not updated to support a larger DNS packet size, it often results in the larger packets being rejected, and to the end user it looks like the queries go unanswered. Or in the case of fragmentation, only a part of the answer makes it to the validating resolver, and your validating resolver may need to re-ask the question again and again, creating the appearance for end users that the DNS/network is slow.</p> <p>While you are updating the configuration on your network equipment, make sure TCP port 53 is also allowed for DNS traffic.</p> </section> <section id="wait-dns-uses-tcp"> <span id="dns-uses-tcp"></span><h4>Wait… DNS Uses TCP?<a class="headerlink" href="#wait-dns-uses-tcp" title="Permalink to this headline"></a></h4> <p>Yes. DNS uses TCP port 53 as a fallback mechanism, when it cannot use UDP to transmit data. This has always been the case, even long before the arrival of DNSSEC. Traditional DNS relies on TCP port 53 for operations such as zone transfer. The use of DNSSEC, or DNS with IPv6 records such as AAAA, increases the chance that DNS data will be transmitted via TCP.</p> <p>Due to the increased packet size, DNSSEC may fall back to TCP more often than traditional (insecure) DNS. If your network blocks or filters TCP port 53 today, you may already experience instability with DNS resolution, before even deploying DNSSEC.</p> </section> </section> </section> <section id="signing"> <span id="dnssec-signing"></span><h2>Signing<a class="headerlink" href="#signing" title="Permalink to this headline"></a></h2> <section id="easy-start-guide-for-signing-authoritative-zones"> <span id="easy-start-guide-for-authoritative-servers"></span><h3>Easy-Start Guide for Signing Authoritative Zones<a class="headerlink" href="#easy-start-guide-for-signing-authoritative-zones" title="Permalink to this headline"></a></h3> <p>This section provides the basic information needed to set up a DNSSEC-enabled authoritative name server. A DNSSEC-enabled (or “signed”) zone contains additional resource records that are used to verify the authenticity of its zone information.</p> <p>To convert a traditional (insecure) DNS zone to a secure one, we need to create some additional records (DNSKEY, RRSIG, and NSEC or NSEC3), and upload verifiable information (such as a DS record) to the parent zone to complete the chain of trust. For more information about DNSSEC resource records, please see <a class="reference internal" href="#what-does-dnssec-add-to-dns"><span class="std std-ref">What Does DNSSEC Add to DNS?</span></a>.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>In this chapter, we assume all configuration files, key files, and zone files are stored in <code class="docutils literal notranslate"><span class="pre">/etc/bind</span></code>, and most examples show commands run as the root user. This may not be ideal, but the point is not to distract from what is important here: learning how to sign a zone. There are many best practices for deploying a more secure BIND installation, with techniques such as jailed process and restricted user privileges, but those are not covered in this document. We trust you, a responsible DNS administrator, to take the necessary precautions to secure your system.</p> </div> <p>For the examples below, we work with the assumption that there is an existing insecure zone <code class="docutils literal notranslate"><span class="pre">example.com</span></code> that we are converting to a secure zone.</p> <section id="enabling-automated-dnssec-zone-maintenance-and-key-generation"> <span id="signing-easy-start-policy-enable"></span><h4>Enabling Automated DNSSEC Zone Maintenance and Key Generation<a class="headerlink" href="#enabling-automated-dnssec-zone-maintenance-and-key-generation" title="Permalink to this headline"></a></h4> <p>To sign a zone, add the following statement to its <a class="reference internal" href="reference.html#namedconf-statement-zone" title="namedconf-statement-zone"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">zone</span></code></a> clause in the BIND 9 configuration file:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">options</span> <span class="p">{</span> <span class="n">directory</span> <span class="s2">"/etc/bind"</span><span class="p">;</span> <span class="n">recursion</span> <span class="n">no</span><span class="p">;</span> <span class="o">...</span> <span class="p">};</span> <span class="n">zone</span> <span class="s2">"example.com"</span> <span class="ow">in</span> <span class="p">{</span> <span class="o">...</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="n">default</span><span class="p">;</span> <span class="n">inline</span><span class="o">-</span><span class="n">signing</span> <span class="n">yes</span><span class="p">;</span> <span class="o">...</span> <span class="p">};</span> </pre></div> </div> <p>The <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement causes the zone to be signed and turns on automatic maintenance for the zone. This includes re-signing the zone as signatures expire and replacing keys on a periodic basis. The value <code class="docutils literal notranslate"><span class="pre">default</span></code> selects the default policy, which contains values suitable for most situations. We cover the creation of a custom policy in <a class="reference internal" href="#signing-custom-policy"><span class="std std-ref">Creating a Custom DNSSEC Policy</span></a>, but for the moment we are accepting the default values.</p> <p>Using <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> requires dynamic DNS or <a class="reference internal" href="reference.html#namedconf-statement-inline-signing" title="namedconf-statement-inline-signing"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">inline-signing</span></code></a> to be enabled.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Previously, if a zone with a <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> did not have dynamic DNS set up and <a class="reference internal" href="reference.html#namedconf-statement-inline-signing" title="namedconf-statement-inline-signing"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">inline-signing</span></code></a> was not explicity set, BIND 9 used inline-signing implicitly. But this caused a lot of problems when operators switched on or off dynamic DNS for their zones. Therefor, you now have to configure it explicitly.</p> </div> <p>When the configuration file is updated, tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to reload the configuration file by running <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-reconfig"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">reconfig</span></code></a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># rndc reconfig</span> </pre></div> </div> <p>And that’s it - BIND signs your zone.</p> <p>At this point, before you go away and merrily add <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statements to all your zones, we should mention that, like a number of other BIND configuration options, its scope depends on where it is placed. In the example above, we placed it in a <a class="reference internal" href="reference.html#namedconf-statement-zone" title="namedconf-statement-zone"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">zone</span></code></a> clause, so it applied only to the zone in question. If we had placed it in a <a class="reference internal" href="reference.html#namedconf-statement-view" title="namedconf-statement-view"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">view</span></code></a> clause, it would have applied to all zones in the view; and if we had placed it in the <a class="reference internal" href="reference.html#namedconf-statement-options" title="namedconf-statement-options"><code class="xref namedconf namedconf-ref docutils literal notranslate"><span class="pre">options</span></code></a> clause, it would have applied to all zones served by this instance of BIND.</p> </section> <section id="verification"> <span id="signing-verification"></span><h4>Verification<a class="headerlink" href="#verification" title="Permalink to this headline"></a></h4> <p>The BIND 9 reconfiguration starts the process of signing the zone. First, it generates a key for the zone and includes it in the published zone. The log file shows messages such as these:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mf">55.045</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="n">reconfiguring</span> <span class="n">zone</span> <span class="n">keys</span> <span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mf">55.045</span> <span class="n">reloading</span> <span class="n">configuration</span> <span class="n">succeeded</span> <span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mf">55.046</span> <span class="n">keymgr</span><span class="p">:</span> <span class="n">DNSKEY</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">ECDSAP256SHA256</span><span class="o">/</span><span class="mi">10376</span> <span class="p">(</span><span class="n">CSK</span><span class="p">)</span> <span class="n">created</span> <span class="k">for</span> <span class="n">policy</span> <span class="n">default</span> <span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mf">55.046</span> <span class="n">Fetching</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">ECDSAP256SHA256</span><span class="o">/</span><span class="mi">10376</span> <span class="p">(</span><span class="n">CSK</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">key</span> <span class="n">repository</span><span class="o">.</span> <span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mf">55.046</span> <span class="n">DNSKEY</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">ECDSAP256SHA256</span><span class="o">/</span><span class="mi">10376</span> <span class="p">(</span><span class="n">CSK</span><span class="p">)</span> <span class="ow">is</span> <span class="n">now</span> <span class="n">published</span> <span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mf">55.046</span> <span class="n">DNSKEY</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">ECDSAP256SHA256</span><span class="o">/</span><span class="mi">10376</span> <span class="p">(</span><span class="n">CSK</span><span class="p">)</span> <span class="ow">is</span> <span class="n">now</span> <span class="n">active</span> <span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mf">55.048</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="nb">next</span> <span class="n">key</span> <span class="n">event</span><span class="p">:</span> <span class="mi">07</span><span class="o">-</span><span class="n">Apr</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">18</span><span class="p">:</span><span class="mi">07</span><span class="p">:</span><span class="mf">55.045</span> </pre></div> </div> <p>It then starts signing the zone. How long this process takes depends on the size of the zone, the speed of the server, and how much activity is taking place. We can check what is happening by using <a class="reference internal" href="manpages.html#std-iscman-rndc"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">rndc</span></code></a>, entering the command:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># rndc signing -list example.com</span> </pre></div> </div> <p>While the signing is in progress, the output is something like:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Signing</span> <span class="k">with</span> <span class="n">key</span> <span class="mi">10376</span><span class="o">/</span><span class="n">ECDSAP256SHA256</span> </pre></div> </div> <p>and when it is finished:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Done</span> <span class="n">signing</span> <span class="k">with</span> <span class="n">key</span> <span class="mi">10376</span><span class="o">/</span><span class="n">ECDSAP256SHA256</span> </pre></div> </div> <p>When the second message appears, the zone is signed.</p> <p>Before moving on to the next step of coordinating with the parent zone, let’s make sure everything looks good using <a class="reference internal" href="manpages.html#std-iscman-delv"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">delv</span></code></a>. We want to simulate what a validating resolver will check, by telling <a class="reference internal" href="manpages.html#std-iscman-delv"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">delv</span></code></a> to use a specific trust anchor.</p> <p>First, we need to make a copy of the key created by BIND. This is in the directory you set with the <a class="reference internal" href="reference.html#namedconf-statement-directory" title="namedconf-statement-directory"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">directory</span></code></a> statement in your configuration file’s <a class="reference internal" href="reference.html#namedconf-statement-options" title="namedconf-statement-options"><code class="xref namedconf namedconf-ref docutils literal notranslate"><span class="pre">options</span></code></a> clause, and is named something like <code class="docutils literal notranslate"><span class="pre">Kexample.com.+013.10376.key</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cp /etc/bind/Kexample.com.+013+10376.key /tmp/example.key</span> </pre></div> </div> <p>The original key file looks like this (with the actual key shortened for ease of display, and comments omitted):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cat /etc/bind/Kexample.com.+013+10376.key</span> <span class="o">...</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">3600</span> <span class="n">IN</span> <span class="n">DNSKEY</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">13</span> <span class="mi">6</span><span class="n">saiq99qDB</span><span class="o">...</span><span class="n">dqp</span><span class="o">+</span><span class="n">o0dw</span><span class="o">==</span> </pre></div> </div> <p>We want to edit the copy to be in the <a class="reference internal" href="reference.html#namedconf-statement-trust-anchors" title="namedconf-statement-trust-anchors"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">trust-anchors</span></code></a> format, so that it looks like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cat /tmp/example.key</span> <span class="n">trust</span><span class="o">-</span><span class="n">anchors</span> <span class="p">{</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">static</span><span class="o">-</span><span class="n">key</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">13</span> <span class="s2">"6saiq99qDB...dqp+o0dw=="</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p>Now we can run the <a class="reference internal" href="manpages.html#std-iscman-delv"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">delv</span></code></a> command and instruct it to use this trusted-key file to validate the answer it receives from the authoritative name server 192.168.1.13:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ delv @192.168.1.13 -a /tmp/example.key +root=example.com example.com. SOA +multiline ; fully validated example.com. 600 IN SOA ns1.example.com. admin.example.com. ( 2020040703 ; serial 1800 ; refresh (30 minutes) 900 ; retry (15 minutes) 2419200 ; expire (4 weeks) 300 ; minimum (5 minutes) ) example.com. 600 IN RRSIG SOA 13 2 600 ( 20200421150255 20200407140255 10376 example.com. jBsz92zwAcGMNV/yu167aKQZvFyC7BiQe1WEnlogdLTF oq4yBQumOhO5WX61LjA17l1DuLWcd/ASwlUZWFGCYQ== ) </pre></div> </div> </section> <section id="uploading-information-to-the-parent-zone"> <span id="signing-easy-start-upload-to-parent-zone"></span><h4>Uploading Information to the Parent Zone<a class="headerlink" href="#uploading-information-to-the-parent-zone" title="Permalink to this headline"></a></h4> <p>Once everything is complete on our name server, we need to generate some information to be uploaded to the parent zone to complete the chain of trust. The format and the upload methods are actually dictated by your parent zone’s administrator, so contact your registrar or parent zone administrator to find out what the actual format should be and how to deliver or upload the information to the parent zone.</p> <p>What about your zone between the time you signed it and the time your parent zone accepts the upload? To the rest of the world, your zone still appears to be insecure, because if a validating resolver attempts to validate your domain name via your parent zone, your parent zone will indicate that you are not yet signed (as far as it knows). The validating resolver will then give up attempting to validate your domain name, and will fall back to the insecure DNS. Until you complete this final step with your parent zone, your zone remains insecure.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Before uploading to your parent zone, verify that your newly signed zone has propagated to all of your name servers (usually via zone transfers). If some of your name servers still have unsigned zone data while the parent tells the world it should be signed, validating resolvers around the world cannot resolve your domain name.</p> </div> <p>Here are some examples of what you may upload to your parent zone, with the DNSKEY/DS data shortened for display. Note that no matter what format may be required, the end result is the parent zone publishing DS record(s) based on the information you upload. Again, contact your parent zone administrator(s) to find out the correct format for their system.</p> <ol class="arabic"> <li><p>DS record format:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">3600</span> <span class="n">IN</span> <span class="n">DS</span> <span class="mi">10376</span> <span class="mi">13</span> <span class="mi">2</span> <span class="n">B92E22CAE0</span><span class="o">..</span><span class="mf">.33</span><span class="n">B8312EF0</span> </pre></div> </div> </li> <li><p>DNSKEY format:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">3600</span> <span class="n">IN</span> <span class="n">DNSKEY</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">13</span> <span class="mi">6</span><span class="n">saiq99qDB</span><span class="o">...</span><span class="n">dqp</span><span class="o">+</span><span class="n">o0dw</span><span class="o">==</span> </pre></div> </div> </li> </ol> <p>The DS record format may be generated from the DNSKEY using the <a class="reference internal" href="manpages.html#std-iscman-dnssec-dsfromkey"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-dsfromkey</span></code></a> tool, which is covered in <a class="reference internal" href="#parent-ds-record-format"><span class="std std-ref">DS Record Format</span></a>. For more details and examples on how to work with your parent zone, please see <a class="reference internal" href="#working-with-parent-zone"><span class="std std-ref">Working With the Parent Zone</span></a>.</p> </section> <section id="so-what-now"> <span id="signing-easy-start-so-what-now"></span><h4>So… What Now?<a class="headerlink" href="#so-what-now" title="Permalink to this headline"></a></h4> <p>Congratulations! Your zone is signed, your secondary servers have received the new zone data, and the parent zone has accepted your upload and published your DS record. Your zone is now officially DNSSEC-enabled. What happens next? That is basically it - BIND takes care of everything else. As for updating your zone file, you can continue to update it the same way as prior to signing your zone; the normal work flow of editing a zone file and using the <a class="reference internal" href="manpages.html#std-iscman-rndc"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">rndc</span></code></a> command to reload the zone still works as usual, and although you are editing the unsigned version of the zone, BIND generates the signed version automatically.</p> <p>Curious as to what all these commands did to your zone file? Read on to <a class="reference internal" href="#your-zone-before-and-after-dnssec"><span class="std std-ref">Your Zone, Before and After DNSSEC</span></a> and find out. If you are interested in how to roll this out to your existing primary and secondary name servers, check out <a class="reference internal" href="#recipes-inline-signing"><span class="std std-ref">DNSSEC Signing</span></a> in the <a class="reference internal" href="#dnssec-recipes"><span class="std std-ref">Recipes</span></a> chapter.</p> </section> </section> <section id="your-zone-before-and-after-dnssec"> <span id="id29"></span><h3>Your Zone, Before and After DNSSEC<a class="headerlink" href="#your-zone-before-and-after-dnssec" title="Permalink to this headline"></a></h3> <p>When we assigned the default DNSSEC policy to the zone, we provided the minimal amount of information to convert a traditional DNS zone into a DNSSEC-enabled zone. This is what the zone looked like before we started:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. AXFR +multiline +onesoa ; <<>> DiG 9.16.0 <<>> @192.168.1.13 example.com AXFR +multiline +onesoa ; (1 server found) ;; global options: +cmd example.com. 600 IN SOA ns1.example.com. admin.example.com. ( 2020040700 ; serial 1800 ; refresh (30 minutes) 900 ; retry (15 minutes) 2419200 ; expire (4 weeks) 300 ; minimum (5 minutes) ) example.com. 600 IN NS ns1.example.com. ftp.example.com. 600 IN A 192.168.1.200 ns1.example.com. 600 IN A 192.168.1.1 web.example.com. 600 IN CNAME www.example.com. www.example.com. 600 IN A 192.168.1.100 </pre></div> </div> <p>Below shows the test zone <code class="docutils literal notranslate"><span class="pre">example.com</span></code> after reloading the server configuration. Clearly, the zone grew in size, and the number of records multiplied:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># dig @192.168.1.13 example.com. AXFR +multiline +onesoa</span> <span class="p">;</span> <span class="o"><<>></span> <span class="n">DiG</span> <span class="mf">9.16.0</span> <span class="o"><<>></span> <span class="o">@</span><span class="mf">192.168.1.13</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span> <span class="n">AXFR</span> <span class="o">+</span><span class="n">multiline</span> <span class="o">+</span><span class="n">onesoa</span> <span class="p">;</span> <span class="p">(</span><span class="mi">1</span> <span class="n">server</span> <span class="n">found</span><span class="p">)</span> <span class="p">;;</span> <span class="k">global</span> <span class="n">options</span><span class="p">:</span> <span class="o">+</span><span class="n">cmd</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">SOA</span> <span class="n">ns1</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">admin</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="p">(</span> <span class="mi">2020040703</span> <span class="p">;</span> <span class="n">serial</span> <span class="mi">1800</span> <span class="p">;</span> <span class="n">refresh</span> <span class="p">(</span><span class="mi">30</span> <span class="n">minutes</span><span class="p">)</span> <span class="mi">900</span> <span class="p">;</span> <span class="n">retry</span> <span class="p">(</span><span class="mi">15</span> <span class="n">minutes</span><span class="p">)</span> <span class="mi">2419200</span> <span class="p">;</span> <span class="n">expire</span> <span class="p">(</span><span class="mi">4</span> <span class="n">weeks</span><span class="p">)</span> <span class="mi">300</span> <span class="p">;</span> <span class="n">minimum</span> <span class="p">(</span><span class="mi">5</span> <span class="n">minutes</span><span class="p">)</span> <span class="p">)</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="mi">13</span> <span class="mi">2</span> <span class="mi">300</span> <span class="p">(</span> <span class="mi">20200413050536</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">drtV1rJbo5OMi65OJtu7Jmg</span><span class="o">/</span><span class="n">thgpdTWrzr6O3Pzt12</span><span class="o">+</span><span class="n">B</span> <span class="n">oCxMAv3orWWYjfP2n9w5wj0rx2Mt2ev7MOOG8IOUCA</span><span class="o">==</span> <span class="p">)</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">ftp</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">NS</span> <span class="n">SOA</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">DNSKEY</span> <span class="n">TYPE65534</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">NS</span> <span class="mi">13</span> <span class="mi">2</span> <span class="mi">600</span> <span class="p">(</span> <span class="mi">20200413130638</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">2</span><span class="n">ipmzm1Ei6vfE9OLowPMsxLBCbjrCpWPgWJ0ekwZBbux</span> <span class="n">MLffZOXn8clt0Ql2U9iCPdyoQryuJCiojHSE2d6nrw</span><span class="o">==</span> <span class="p">)</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">SOA</span> <span class="mi">13</span> <span class="mi">2</span> <span class="mi">600</span> <span class="p">(</span> <span class="mi">20200421150255</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">jBsz92zwAcGMNV</span><span class="o">/</span><span class="n">yu167aKQZvFyC7BiQe1WEnlogdLTF</span> <span class="n">oq4yBQumOhO5WX61LjA17l1DuLWcd</span><span class="o">/</span><span class="n">ASwlUZWFGCYQ</span><span class="o">==</span> <span class="p">)</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">0</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">TYPE65534</span> <span class="mi">13</span> <span class="mi">2</span> <span class="mi">0</span> <span class="p">(</span> <span class="mi">20200413050536</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">Xjkom24N6qeCJjg9BMUfuWf</span><span class="o">+</span><span class="n">euLeZB169DHvLYZPZNlm</span> <span class="n">GgM2czUDPio6VpQbUw6JE5DSNjuGjgpgXC5SipC42g</span><span class="o">==</span> <span class="p">)</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">3600</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">DNSKEY</span> <span class="mi">13</span> <span class="mi">2</span> <span class="mi">3600</span> <span class="p">(</span> <span class="mi">20200421150255</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">maK75</span><span class="o">+</span><span class="mi">28</span><span class="n">oUyDtci3V7wjTsuhgkLUZW</span><span class="o">+</span><span class="n">Q</span><span class="o">++</span><span class="n">q46Lea6bKn</span> <span class="n">Xj77kXcLNogNdUOr5am</span><span class="o">/</span><span class="mi">6</span><span class="n">O6cnPeJKJWsnmTLISm62g</span><span class="o">==</span> <span class="p">)</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">0</span> <span class="n">IN</span> <span class="n">TYPE65534</span> \<span class="c1"># 5 ( 0D28880001 )</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">3600</span> <span class="n">IN</span> <span class="n">DNSKEY</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">13</span> <span class="p">(</span> <span class="mi">6</span><span class="n">saiq99qDBb5b4G4cx13cPjFTrIvUs3NW44SvbbHorHb</span> <span class="n">kXwOzeGAWyPORN</span><span class="o">+</span><span class="n">pwEV</span><span class="o">/</span><span class="n">LP9</span><span class="o">+</span><span class="n">FHAF</span><span class="o">/</span><span class="n">JzAJYdqp</span><span class="o">+</span><span class="n">o0dw</span><span class="o">==</span> <span class="p">)</span> <span class="p">;</span> <span class="n">KSK</span><span class="p">;</span> <span class="n">alg</span> <span class="o">=</span> <span class="n">ECDSAP256SHA256</span> <span class="p">;</span> <span class="n">key</span> <span class="nb">id</span> <span class="o">=</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">NS</span> <span class="n">ns1</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">ftp</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">A</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">600</span> <span class="p">(</span> <span class="mi">20200413130638</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">UYo1njeUA49VhKnPSS3JO4G</span><span class="o">+/</span><span class="n">Xd2PD4m3Vaacnd191yz</span> <span class="n">BIoouEBAGPcrEM2BNrgR0op1EWSus9tG86SM1ZHGuQ</span><span class="o">==</span> <span class="p">)</span> <span class="n">ftp</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">300</span> <span class="p">(</span> <span class="mi">20200413130638</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">rPADrAMAPIPSF3S45OSY8kXBTYMS3nrZg4Awj7qRL</span><span class="o">+/</span><span class="n">b</span> <span class="n">sOKy6044MbIbjg</span><span class="o">+</span><span class="n">YWL69dBjKoTSeEGSCSt73uIxrYA</span><span class="o">==</span> <span class="p">)</span> <span class="n">ftp</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">ns1</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">ftp</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">A</span> <span class="mf">192.168.1.200</span> <span class="n">ns1</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">A</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">600</span> <span class="p">(</span> <span class="mi">20200413130638</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">Yeojg7qrJmxL6uLTnALwKU5byNldZ9Ggj5XjcbpPvujQ</span> <span class="n">ocG</span><span class="o">/</span><span class="n">ovGBg6pdugXC9UxE39bCDl8dua1frjDcRCCZAA</span><span class="o">==</span> <span class="p">)</span> <span class="n">ns1</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">300</span> <span class="p">(</span> <span class="mi">20200413130638</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">vukgQme6k7JwCf</span><span class="o">/</span><span class="n">mJOOzHXbE3fKtSro</span><span class="o">+</span><span class="n">Kc10T6dHMdsc</span> <span class="n">oM1</span><span class="o">/</span><span class="n">oXioZvgBZ9cKrQhIAUt7r1KUnrUwM6Je36wWFA</span><span class="o">==</span> <span class="p">)</span> <span class="n">ns1</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">web</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">ns1</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">A</span> <span class="mf">192.168.1.1</span> <span class="n">web</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">CNAME</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">600</span> <span class="p">(</span> <span class="mi">20200413130638</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">JXi4WYypofD5geUowVqlqJyHzvcRnsvU</span><span class="o">/</span><span class="n">ONhTBaUCw5Y</span> <span class="n">XtifKAXRHWrUL1HIwt37JYPLf5uYu90RfkWLj0GqTQ</span><span class="o">==</span> <span class="p">)</span> <span class="n">web</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">300</span> <span class="p">(</span> <span class="mi">20200413130638</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">XF4Hsd58dalL</span><span class="o">+</span><span class="n">s6Qu99bG80PQyMf7ZrHEzDiEflRuykP</span> <span class="n">DfBRuf34z27vj70LO1lp2ZiX4BB1ahcEK2ae9ASAmA</span><span class="o">==</span> <span class="p">)</span> <span class="n">web</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">CNAME</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">web</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">CNAME</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">A</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">600</span> <span class="p">(</span> <span class="mi">20200413050536</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">mACKXrDOF5JMWqncSiQ3pYWA6abyGDJ4wgGCumjLXhPy</span> <span class="mi">0</span><span class="n">cMzJmKv2s7G6</span><span class="o">+</span><span class="n">tW3TsA6BK3UoMfv30oblY2Mnl4</span><span class="o">/</span><span class="n">A</span><span class="o">==</span> <span class="p">)</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="mi">13</span> <span class="mi">3</span> <span class="mi">300</span> <span class="p">(</span> <span class="mi">20200413050536</span> <span class="mi">20200407140255</span> <span class="mi">10376</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">1</span><span class="n">YQ22odVt0TeP5gbNJwkvS684ipDmx6sEOsF0eCizhCv</span> <span class="n">x8osuOATdlPjIEztt</span><span class="o">+</span><span class="n">rveaErZ2nsoLor5k1nQAHsbQ</span><span class="o">==</span> <span class="p">)</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">600</span> <span class="n">IN</span> <span class="n">A</span> <span class="mf">192.168.1.100</span> </pre></div> </div> <p>But this is a really messy way to tell if the zone is set up properly with DNSSEC. Fortunately, there are tools to help us with that. Read on to <a class="reference internal" href="#how-to-test-authoritative-server"><span class="std std-ref">How To Test Authoritative Zones</span></a> to learn more.</p> </section> <section id="how-to-test-authoritative-zones"> <span id="how-to-test-authoritative-server"></span><h3>How To Test Authoritative Zones<a class="headerlink" href="#how-to-test-authoritative-zones" title="Permalink to this headline"></a></h3> <p>So we’ve activated DNSSEC and uploaded some data to our parent zone. How do we know our zone is signed correctly? Here are a few ways to check.</p> <section id="look-for-key-data-in-your-zone"> <span id="signing-verify-key-data"></span><h4>Look for Key Data in Your Zone<a class="headerlink" href="#look-for-key-data-in-your-zone" title="Permalink to this headline"></a></h4> <p>One way to see if your zone is signed is to check for the presence of DNSKEY record types. In our example, we created a single key, and we expect to see it returned when we query for it.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. DNSKEY +multiline ; <<>> DiG 9.16.0 <<>> @10.53.0.6 example.com DNSKEY +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18637 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: efe186423313fb66010000005e8c997e99864f7d69ed7c11 (good) ;; QUESTION SECTION: ;example.com. IN DNSKEY ;; ANSWER SECTION: example.com. 3600 IN DNSKEY 257 3 13 ( 6saiq99qDBb5b4G4cx13cPjFTrIvUs3NW44SvbbHorHb kXwOzeGAWyPORN+pwEV/LP9+FHAF/JzAJYdqp+o0dw== ) ; KSK; alg = ECDSAP256SHA256 ; key id = 10376 </pre></div> </div> </section> <section id="look-for-signatures-in-your-zone"> <span id="signing-verify-signature"></span><h4>Look for Signatures in Your Zone<a class="headerlink" href="#look-for-signatures-in-your-zone" title="Permalink to this headline"></a></h4> <p>Another way to see if your zone data is signed is to check for the presence of a signature. With DNSSEC, every record <a class="footnote-reference brackets" href="#every-record-signed" id="id30">5</a> now comes with at least one corresponding signature, known as an RRSIG.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. SOA +dnssec +multiline ; <<>> DiG 9.16.0 <<>> @10.53.0.6 example.com SOA +dnssec +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45219 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ; COOKIE: 75adff4f4ce916b2010000005e8c99c0de47eabb7951b2f5 (good) ;; QUESTION SECTION: ;example.com. IN SOA ;; ANSWER SECTION: example.com. 600 IN SOA ns1.example.com. admin.example.com. ( 2020040703 ; serial 1800 ; refresh (30 minutes) 900 ; retry (15 minutes) 2419200 ; expire (4 weeks) 300 ; minimum (5 minutes) ) example.com. 600 IN RRSIG SOA 13 2 600 ( 20200421150255 20200407140255 10376 example.com. jBsz92zwAcGMNV/yu167aKQZvFyC7BiQe1WEnlogdLTF oq4yBQumOhO5WX61LjA17l1DuLWcd/ASwlUZWFGCYQ== ) </pre></div> </div> <p>The serial number was automatically incremented from the old, unsigned version. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> keeps track of the serial number of the signed version of the zone independently of the unsigned version. If the unsigned zone is updated with a new serial number that is higher than the one in the signed copy, then the signed copy is increased to match it; otherwise, the two are kept separate.</p> </section> <section id="examine-the-zone-file"> <span id="signing-verify-zone-file"></span><h4>Examine the Zone File<a class="headerlink" href="#examine-the-zone-file" title="Permalink to this headline"></a></h4> <p>Our original zone file <code class="docutils literal notranslate"><span class="pre">example.com.db</span></code> remains untouched, and <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> has generated three additional files automatically for us (shown below). The signed DNS data is stored in <code class="docutils literal notranslate"><span class="pre">example.com.db.signed</span></code> and in the associated journal file.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind</span> <span class="c1"># ls</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">jbk</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">signed</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">signed</span><span class="o">.</span><span class="n">jnl</span> </pre></div> </div> <p>A quick description of each of the files:</p> <ul class="simple"> <li><p><code class="docutils literal notranslate"><span class="pre">.jbk</span></code>: a transient file used by <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">.signed</span></code>: the signed version of the zone in raw format</p></li> <li><p><code class="docutils literal notranslate"><span class="pre">.signed.jnl</span></code>: a journal file for the signed version of the zone</p></li> </ul> <p>These files are stored in raw (binary) format for faster loading. To reveal the human-readable version, use <a class="reference internal" href="manpages.html#std-iscman-named-compilezone"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named-compilezone</span></code></a> as shown below. In the example below, we run the command on the raw format zone <code class="docutils literal notranslate"><span class="pre">example.com.db.signed</span></code> to produce a text version of the zone <code class="docutils literal notranslate"><span class="pre">example.com.text</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># named-compilezone -f raw -F text -o example.com.text example.com example.com.db.signed</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span><span class="p">:</span> <span class="n">loaded</span> <span class="n">serial</span> <span class="mi">2014112008</span> <span class="p">(</span><span class="n">DNSSEC</span> <span class="n">signed</span><span class="p">)</span> <span class="n">dump</span> <span class="n">zone</span> <span class="n">to</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">text</span><span class="o">...</span><span class="n">done</span> <span class="n">OK</span> </pre></div> </div> </section> <section id="check-the-parent"> <span id="signing-verify-check-parent"></span><h4>Check the Parent<a class="headerlink" href="#check-the-parent" title="Permalink to this headline"></a></h4> <p>Although this is not strictly related to whether the zone is signed, a critical part of DNSSEC is the trust relationship between the parent and the child. Just because we, the child, have all the correctly signed records in our zone does not mean it can be fully validated by a validating resolver, unless our parent’s data agrees with ours. To check if our upload to the parent was successful, ask the parent name server for the DS record of our child zone; we should get back the DS record(s) containing the information we uploaded in <a class="reference internal" href="#signing-easy-start-upload-to-parent-zone"><span class="std std-ref">Uploading Information to the Parent Zone</span></a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig example.com. DS ; <<>> DiG 9.16.0 <<>> example.com DS ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16954 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: db280d5b52576780010000005e8c9bf5b0d8de103d934e5d (good) ;; QUESTION SECTION: ;example.com. IN DS ;; ANSWER SECTION: example.com. 61179 IN DS 10376 13 2 B92E22CAE0B41430EC38D3F7EDF1183C3A94F4D4748569250C15EE33B8312EF0 </pre></div> </div> <dl class="footnote brackets"> <dt class="label" id="every-record-signed"><span class="brackets"><a class="fn-backref" href="#id30">5</a></span></dt> <dd><p>Well, almost every record: NS records and glue records for delegations do not have RRSIG records. If there are no delegations, then every record in your zone is signed and comes with its own RRSIG.</p> </dd> </dl> </section> <section id="external-testing-tools"> <span id="signing-verify-external-tools"></span><h4>External Testing Tools<a class="headerlink" href="#external-testing-tools" title="Permalink to this headline"></a></h4> <p>We recommend two tools, below: Verisign DNSSEC Debugger and DNSViz. Others can be found via a simple online search. These excellent online tools are an easy way to verify that your domain name is fully secured.</p> <section id="verisign-dnssec-debugger"> <span id="signing-verify-external-tools-dnssec-debugger"></span><h5>Verisign DNSSEC Debugger<a class="headerlink" href="#verisign-dnssec-debugger" title="Permalink to this headline"></a></h5> <p>URL: <a class="reference external" href="https://dnssec-debugger.verisignlabs.com/">https://dnssec-debugger.verisignlabs.com/</a></p> <p>This tool shows a nice summary of checks performed on your domain name. You can expand it to view more details for each of the items checked, to get a detailed report.</p> <figure class="align-default" id="id54"> <img alt="Verisign DNSSEC Debugger" src="_images/verisign-dnssec-debugger-example.png" /> <figcaption> <p><span class="caption-text">Verisign DNSSEC Debugger</span><a class="headerlink" href="#id54" title="Permalink to this image"></a></p> </figcaption> </figure> </section> <section id="dnsviz"> <span id="signing-verify-external-tools-dnsviz"></span><h5>DNSViz<a class="headerlink" href="#dnsviz" title="Permalink to this headline"></a></h5> <p>URL: <a class="reference external" href="https://dnsviz.net/">https://dnsviz.net/</a></p> <p>DNSViz provides a visual analysis of the DNSSEC authentication chain for a domain name and its resolution path in the DNS namespace.</p> <figure class="align-default" id="id55"> <a class="reference internal image-reference" href="_images/dnsviz-example-small.png"><img alt="DNSViz" src="_images/dnsviz-example-small.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">DNSViz</span><a class="headerlink" href="#id55" title="Permalink to this image"></a></p> </figcaption> </figure> </section> </section> </section> <section id="signing-easy-start-explained"> <span id="id31"></span><h3>Signing Easy Start Explained<a class="headerlink" href="#signing-easy-start-explained" title="Permalink to this headline"></a></h3> <section id="enable-automatic-dnssec-maintenance-explained"> <span id="enable-automatic-maintenance-explained"></span><h4>Enable Automatic DNSSEC Maintenance Explained<a class="headerlink" href="#enable-automatic-dnssec-maintenance-explained" title="Permalink to this headline"></a></h4> <p>Signing a zone requires a number of separate steps:</p> <ul class="simple"> <li><p>Generation of the keys to sign the zone.</p></li> <li><p>Inclusion of the keys into the zone.</p></li> <li><p>Signing of the records in the file (including the generation of the NSEC or NSEC3 records).</p></li> </ul> <p>Maintaining a signed zone comprises a set of ongoing tasks:</p> <ul class="simple"> <li><p>Re-signing the zone as signatures approach expiration.</p></li> <li><p>Generation of new keys as the time approaches for a key roll.</p></li> <li><p>Inclusion of new keys into the zone when the rollover starts.</p></li> <li><p>Transition from signing the zone with the old set of keys to signing the zone with the new set of keys.</p></li> <li><p>Waiting the appropriate interval before removing the old keys from the zone.</p></li> <li><p>Deleting the old keys.</p></li> </ul> <p>That is quite complex, and it is all handled in BIND 9 with the single <code class="docutils literal notranslate"><span class="pre">dnssec-policy</span> <span class="pre">default</span></code> statement. We will see later on (in the <a class="reference internal" href="#signing-custom-policy"><span class="std std-ref">Creating a Custom DNSSEC Policy</span></a> section) how these actions can be tuned, by setting up our own DNSSEC policy with customized parameters. However, in many cases the defaults are adequate.</p> <p>At the time of this writing (mid-2020), <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> is still a relatively new feature in BIND. Although it is the preferred way to run DNSSEC in a zone, it is not yet able to automatically implement all the features that are available with a more “hands-on” approach to signing and key maintenance. For this reason, we cover alternative signing techniques in <a class="reference internal" href="#signing-alternative-ways"><span class="std std-ref">Alternate Ways of Signing a Zone</span></a>.</p> </section> </section> <section id="working-with-the-parent-zone"> <span id="working-with-parent-zone"></span><h3>Working With the Parent Zone<a class="headerlink" href="#working-with-the-parent-zone" title="Permalink to this headline"></a></h3> <p>As mentioned in <a class="reference internal" href="#signing-easy-start-upload-to-parent-zone"><span class="std std-ref">Uploading Information to the Parent Zone</span></a>, the format of the information uploaded to your parent zone is dictated by your parent zone administrator. The two main formats are:</p> <ol class="arabic simple"> <li><p>DS record format</p></li> <li><p>DNSKEY format</p></li> </ol> <p>Check with your parent zone to see which format they require.</p> <p>But how can you get each of the formats from your existing data?</p> <p>When <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> turned on automatic DNSSEC maintenance, essentially the first thing it did was to create the DNSSEC keys and put them in the directory you specified in the configuration file. If you look in that directory, you will see three files with names like <code class="docutils literal notranslate"><span class="pre">Kexample.com.+013+10376.key</span></code>, <code class="docutils literal notranslate"><span class="pre">Kexample.com.+013+10376.private</span></code>, and <code class="docutils literal notranslate"><span class="pre">Kexample.com.+013+10376.state</span></code>. The one we are interested in is the one with the <code class="docutils literal notranslate"><span class="pre">.key</span></code> suffix, which contains the zone’s public key. (The other files contain the zone’s private key and the DNSSEC state associated with the key.) This public key is used to generate the information we need to pass to the parent.</p> <section id="ds-record-format"> <span id="parent-ds-record-format"></span><h4>DS Record Format<a class="headerlink" href="#ds-record-format" title="Permalink to this headline"></a></h4> <p>Below is an example of a DS record format generated from the KSK we created earlier (<code class="docutils literal notranslate"><span class="pre">Kexample.com.+013+10376.key</span></code>):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">dsfromkey</span> <span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">013</span><span class="o">+</span><span class="mf">10376.</span><span class="n">key</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">IN</span> <span class="n">DS</span> <span class="mi">10376</span> <span class="mi">13</span> <span class="mi">2</span> <span class="n">B92E22CAE0B41430EC38D3F7EDF1183C3A94F4D4748569250C15EE33B8312EF0</span> </pre></div> </div> <p>Some registrars ask their customers to manually specify the types of algorithm and digest used. In this example, 13 represents the algorithm used, and 2 represents the digest type (SHA-256). The key tag or key ID is 10376.</p> </section> <section id="dnskey-format"> <span id="parent-dnskey-format"></span><h4>DNSKEY Format<a class="headerlink" href="#dnskey-format" title="Permalink to this headline"></a></h4> <p>Below is an example of the same key ID (10376) using DNSKEY format (with the actual key shortened for ease of display):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">3600</span> <span class="n">IN</span> <span class="n">DNSKEY</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">13</span> <span class="p">(</span><span class="mi">6</span><span class="n">saiq99qDB</span><span class="o">...</span><span class="n">dqp</span><span class="o">+</span><span class="n">o0dw</span><span class="o">==</span><span class="p">)</span> <span class="p">;</span> <span class="n">key</span> <span class="nb">id</span> <span class="o">=</span> <span class="mi">10376</span> </pre></div> </div> <p>The key itself is easy to find (it’s difficult to miss that long base64 string) in the file.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind</span> <span class="c1"># cat Kexample.com.+013+10376.key</span> <span class="p">;</span> <span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">key</span><span class="o">-</span><span class="n">signing</span> <span class="n">key</span><span class="p">,</span> <span class="n">keyid</span> <span class="mi">10376</span><span class="p">,</span> <span class="k">for</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="p">;</span> <span class="n">Created</span><span class="p">:</span> <span class="mi">20200407150255</span> <span class="p">(</span><span class="n">Tue</span> <span class="n">Apr</span> <span class="mi">7</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mi">55</span> <span class="mi">2020</span><span class="p">)</span> <span class="p">;</span> <span class="n">Publish</span><span class="p">:</span> <span class="mi">20200407150255</span> <span class="p">(</span><span class="n">Tue</span> <span class="n">Apr</span> <span class="mi">7</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mi">55</span> <span class="mi">2020</span><span class="p">)</span> <span class="p">;</span> <span class="n">Activate</span><span class="p">:</span> <span class="mi">20200407150255</span> <span class="p">(</span><span class="n">Tue</span> <span class="n">Apr</span> <span class="mi">7</span> <span class="mi">16</span><span class="p">:</span><span class="mi">02</span><span class="p">:</span><span class="mi">55</span> <span class="mi">2020</span><span class="p">)</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">3600</span> <span class="n">IN</span> <span class="n">DNSKEY</span> <span class="mi">257</span> <span class="mi">3</span> <span class="mi">13</span> <span class="mi">6</span><span class="n">saiq99qDB</span><span class="o">...</span><span class="n">dqp</span><span class="o">+</span><span class="n">o0dw</span><span class="o">==</span> </pre></div> </div> </section> </section> <section id="creating-a-custom-dnssec-policy"> <span id="signing-custom-policy"></span><h3>Creating a Custom DNSSEC Policy<a class="headerlink" href="#creating-a-custom-dnssec-policy" title="Permalink to this headline"></a></h3> <p>The remainder of this section describes the contents of a custom DNSSEC policy. <a class="reference internal" href="#dnssec-advanced-discussions"><span class="std std-ref">Advanced Discussions</span></a> describes the concepts involved here and the pros and cons of choosing particular values. If you are not already familiar with DNSSEC, it may be worth reading that chapter first.</p> <p>Setting up your own DNSSEC policy means that you must include a <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> clause in the zone file. This sets values for the various parameters that affect the signing of zones and the rolling of keys. The following is an example of such a clause:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="n">standard</span> <span class="p">{</span> <span class="n">dnskey</span><span class="o">-</span><span class="n">ttl</span> <span class="mi">600</span><span class="p">;</span> <span class="n">keys</span> <span class="p">{</span> <span class="n">ksk</span> <span class="n">lifetime</span> <span class="mi">365</span><span class="n">d</span> <span class="n">algorithm</span> <span class="n">ecdsap256sha256</span><span class="p">;</span> <span class="n">zsk</span> <span class="n">lifetime</span> <span class="mi">60</span><span class="n">d</span> <span class="n">algorithm</span> <span class="n">ecdsap256sha256</span><span class="p">;</span> <span class="p">};</span> <span class="nb">max</span><span class="o">-</span><span class="n">zone</span><span class="o">-</span><span class="n">ttl</span> <span class="mi">600</span><span class="p">;</span> <span class="n">parent</span><span class="o">-</span><span class="n">ds</span><span class="o">-</span><span class="n">ttl</span> <span class="mi">600</span><span class="p">;</span> <span class="n">parent</span><span class="o">-</span><span class="n">propagation</span><span class="o">-</span><span class="n">delay</span> <span class="mi">2</span><span class="n">h</span><span class="p">;</span> <span class="n">publish</span><span class="o">-</span><span class="n">safety</span> <span class="mi">7</span><span class="n">d</span><span class="p">;</span> <span class="n">retire</span><span class="o">-</span><span class="n">safety</span> <span class="mi">7</span><span class="n">d</span><span class="p">;</span> <span class="n">signatures</span><span class="o">-</span><span class="n">refresh</span> <span class="mi">5</span><span class="n">d</span><span class="p">;</span> <span class="n">signatures</span><span class="o">-</span><span class="n">validity</span> <span class="mi">15</span><span class="n">d</span><span class="p">;</span> <span class="n">signatures</span><span class="o">-</span><span class="n">validity</span><span class="o">-</span><span class="n">dnskey</span> <span class="mi">15</span><span class="n">d</span><span class="p">;</span> <span class="n">zone</span><span class="o">-</span><span class="n">propagation</span><span class="o">-</span><span class="n">delay</span> <span class="mi">2</span><span class="n">h</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p>The policy has multiple parts:</p> <ul class="simple"> <li><p>The name must be specified. As each zone can use a different policy, <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> needs to be able to distinguish between policies. This is done by giving each policy a name, such as <code class="docutils literal notranslate"><span class="pre">standard</span></code> in the above example.</p></li> <li><p>The <a class="reference internal" href="reference.html#namedconf-statement-keys" title="namedconf-statement-keys"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">keys</span></code></a> clause lists all keys that should be in the zone, along with their associated parameters. In this example, we are using the conventional KSK/ZSK split, with the KSK changed every year and the ZSK changed every two months (the <code class="docutils literal notranslate"><span class="pre">default</span></code> DNSSEC policy sets a CSK that is never changed). Keys are created using the ECDSAPS256SHA256 algorithm; each KSK/ZSK pair must have the same algorithm. A CSK combines the functionality of a ZSK and a KSK.</p></li> <li><p>The parameters ending in <code class="docutils literal notranslate"><span class="pre">-ttl</span></code> are, as expected, the TTLs of the associated records. Remember that during a key rollover, we have to wait for records to expire from caches? The values here tell BIND 9 the maximum amount of time it has to wait for this to happen. Values can be set for the DNSKEY records in your zone, the non-DNSKEY records in your zone, and the DS records in the parent zone.</p></li> <li><p>Another set of time-related parameters are those ending in <code class="docutils literal notranslate"><span class="pre">-propagation-delay</span></code>. These tell BIND how long it takes for a change in zone contents to become available on all secondary servers. (This may be non-negligible: for example, if a large zone is transferred over a slow link.)</p></li> <li><p>The policy also sets values for the various signature parameters: how long the signatures on the DNSKEY and non-DNSKEY records are valid, and how often BIND should re-sign the zone.</p></li> <li><p>The parameters ending in <code class="docutils literal notranslate"><span class="pre">-safety</span></code> are there to give you a bit of leeway in case a key roll doesn’t go to plan. When introduced into the zone, the <a class="reference internal" href="reference.html#namedconf-statement-publish-safety" title="namedconf-statement-publish-safety"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">publish-safety</span></code></a> time is the amount of additional time, over and above that calculated from the other parameters, during which the new key is in the zone but before BIND starts to sign records with it. Similarly, the <a class="reference internal" href="reference.html#namedconf-statement-retire-safety" title="namedconf-statement-retire-safety"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">retire-safety</span></code></a> is the amount of additional time, over and above that calculated from the other parameters, during which the old key is retained in the zone before being removed.</p></li> <li><p>Finally, the <a class="reference internal" href="reference.html#namedconf-statement-purge-keys" title="namedconf-statement-purge-keys"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">purge-keys</span></code></a> option allows you to clean up key files automatically after a period of time. If a key has been removed from the zone, this option will determine how long its key files will be retained on disk.</p></li> </ul> <p>(You do not have to specify all the items listed above in your policy definition. Any that are not set simply take the default value.)</p> <p>Usually, the exact timing of a key roll, or how long a signature remains valid, is not critical. For this reason, err on the side of caution when setting values for the parameters. It is better to have an operation like a key roll take a few days longer than absolutely required, than it is to have a quick key roll but have users get validation failures during the process.</p> <p>Having defined a new policy called “standard”, we now need to tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to use it. We do this by adding a <code class="docutils literal notranslate"><span class="pre">dnssec-policy</span> <span class="pre">standard;</span></code> statement to the configuration file. Like many other configuration statements, it can be placed in the <a class="reference internal" href="reference.html#namedconf-statement-options" title="namedconf-statement-options"><code class="xref namedconf namedconf-ref docutils literal notranslate"><span class="pre">options</span></code></a> statement (thus applying to all zones on the server), a <a class="reference internal" href="reference.html#namedconf-statement-view" title="namedconf-statement-view"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">view</span></code></a> statement (applying to all zones in the view), or a <a class="reference internal" href="reference.html#namedconf-statement-zone" title="namedconf-statement-zone"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">zone</span></code></a> statement (applying only to that zone). In this example, we’ll add it to the <a class="reference internal" href="reference.html#namedconf-statement-zone" title="namedconf-statement-zone"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">zone</span></code></a> statement:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="s2">"example.net"</span> <span class="ow">in</span> <span class="p">{</span> <span class="o">...</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="n">standard</span><span class="p">;</span> <span class="n">inline</span><span class="o">-</span><span class="n">signing</span> <span class="n">yes</span><span class="p">;</span> <span class="o">...</span> <span class="p">};</span> </pre></div> </div> <p>Finally, tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to use the new policy:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># rndc reconfig</span> </pre></div> </div> <p>… and that’s it. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> now applies the “standard” policy to your zone.</p> </section> <section id="maintenance-tasks"> <span id="signing-maintenance-tasks"></span><h3>Maintenance Tasks<a class="headerlink" href="#maintenance-tasks" title="Permalink to this headline"></a></h3> <p>Zone data is signed and the parent zone has published your DS records: at this point your zone is officially secure. When other validating resolvers look up information in your zone, they are able to follow the 12-step process as described in <a class="reference internal" href="#how-does-dnssec-change-dns-lookup-revisited"><span class="std std-ref">How Does DNSSEC Change DNS Lookup (Revisited)?</span></a> and verify the authenticity and integrity of the answers.</p> <p>There is not that much left for you, as the DNS administrator, to do on an ongoing basis. Whenever you update your zone, BIND automatically re-signs your zone with new RRSIG and NSEC/NSEC3 records, and even increments the serial number for you. If you choose to split your keys into a KSK and ZSK, the rolling of the ZSK is completely automatic. Rolling of a KSK or CSK may require some manual intervention, though, so let’s examine two more DNSSEC-related resource records, CDS and CDNSKEY.</p> <section id="the-cds-and-cdnskey-resource-records"> <span id="cds-cdnskey"></span><h4>The CDS and CDNSKEY Resource Records<a class="headerlink" href="#the-cds-and-cdnskey-resource-records" title="Permalink to this headline"></a></h4> <p>Passing the DS record to the organization running the parent zone has always been recognized as a bottleneck in the key rollover process. To automate the process, the CDS and CDNSKEY resource records were introduced.</p> <p>The CDS and CDNSKEY records are identical to the DS and DNSKEY records, except in the type code and the name. When such a record appears in the child zone, it is a signal to the parent that it should update the DS it has for that zone. In essence, when the parent notices the presence of the CDS and/or CDNSKEY record(s) in the child zone, it checks these records to verify that they are signed by a valid key for the zone. If the record(s) successfully validate, the parent zone’s DS RRset for the child zone is changed to correspond to the CDS (or CDNSKEY) records. (For more information on how the signaling works and the issues surrounding it, please refer to <span class="target" id="index-1"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7344.html"><strong>RFC 7344</strong></a> and <span class="target" id="index-2"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc8078.html"><strong>RFC 8078</strong></a>.)</p> </section> <section id="working-with-the-parent-zone-2"> <span id="working-with-the-parent-2"></span><h4>Working with the Parent Zone (2)<a class="headerlink" href="#working-with-the-parent-zone-2" title="Permalink to this headline"></a></h4> <p>Once the zone is signed, the only required manual tasks are to monitor KSK or CSK key rolls and pass the new DS record to the parent zone. However, if the parent can process CDS or CDNSKEY records, you may not even have to do that. <a class="footnote-reference brackets" href="#parent-zone-security-considerations" id="id32">6</a></p> <p>When the time approaches for the roll of a KSK or CSK, BIND adds a CDS and a CDNSKEY record for the key in question to the apex of the zone. If your parent zone supports polling for CDS/CDNSKEY records, they are uploaded and the DS record published in the parent - at least ideally.</p> <p>If BIND is configured with <a class="reference internal" href="reference.html#namedconf-statement-parental-agents" title="namedconf-statement-parental-agents"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">parental-agents</span></code></a>, it will check for the DS presence. Let’s look at the following configuration excerpt:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">parental</span><span class="o">-</span><span class="n">agents</span> <span class="s2">"net"</span> <span class="p">{</span> <span class="mf">10.53.0.11</span><span class="p">;</span> <span class="mf">10.53.0.12</span><span class="p">;</span> <span class="p">};</span> <span class="n">zone</span> <span class="s2">"example.net"</span> <span class="ow">in</span> <span class="p">{</span> <span class="o">...</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="n">standard</span><span class="p">;</span> <span class="n">inline</span><span class="o">-</span><span class="n">signing</span> <span class="n">yes</span><span class="p">;</span> <span class="n">parental</span><span class="o">-</span><span class="n">agents</span> <span class="p">{</span> <span class="s2">"net"</span><span class="p">;</span> <span class="p">};</span> <span class="o">...</span> <span class="p">};</span> </pre></div> </div> <p>BIND will check for the presence of the DS record in the parent zone by querying its parental agents (defined in <span class="target" id="index-3"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7344.html"><strong>RFC 7344</strong></a> to be the entities that the child zone has a relationship with to change its delegation information). In the example above, The zone <cite>example.net</cite> is configured with two parental agents, at the addresses 10.53.0.11 and 10.53.0.12. These addresses are used as an example only. Both addresses will have to respond with a DS RRset that includes the DS record identifying the key that is being rolled. If one or both don’t have the DS included yet the rollover is paused, and the check for DS presence is retried after an hour. The same applies for DS withdrawal.</p> <p>Alternatively, you can use the <a class="reference internal" href="manpages.html#std-iscman-rndc"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">rndc</span></code></a> tool to tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> that the DS record has been published or withdrawn. For example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># rndc dnssec -checkds published example.net</span> </pre></div> </div> <p>If your parent zone doesn’t support CDS/CDNSKEY, you will have to supply the DNSKEY or DS record to the parent zone manually when a new KSK appears in your zone, presumably using the same mechanism you used to upload the records for the first time. Again, you need to use the <a class="reference internal" href="manpages.html#std-iscman-rndc"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">rndc</span></code></a> tool to tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> that the DS record has been published.</p> <dl class="footnote brackets"> <dt class="label" id="parent-zone-security-considerations"><span class="brackets"><a class="fn-backref" href="#id32">6</a></span></dt> <dd><p>For security reasons, a parent zone that supports CDS/CDNSKEY may require the DS record to be manually uploaded when we first sign the zone. Until our zone is signed, the parent cannot be sure that a CDS or CDNSKEY record it finds by querying our zone really comes from our zone; thus, it needs to use some other form of secure transfer to obtain the information.</p> </dd> </dl> </section> </section> <section id="alternate-ways-of-signing-a-zone"> <span id="signing-alternative-ways"></span><h3>Alternate Ways of Signing a Zone<a class="headerlink" href="#alternate-ways-of-signing-a-zone" title="Permalink to this headline"></a></h3> <p>Although use of the automatic <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> is the preferred way to sign zones in BIND, there are occasions where a more manual approach may be needed, such as when external hardware is used to generate and sign the zone. <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> does not currently support the use of external hardware, so if your security policy requires it, you need to use one of the methods described here.</p> <p>The idea of DNSSEC was first discussed in the 1990s and has been extensively developed over the intervening years. BIND has tracked the development of this technology, often being the first name server implementation to introduce new features. However, for compatibility reasons, BIND retained older ways of doing things even when new ways were added. This particularly applies to signing and maintaining zones, where different levels of automation are available.</p> <p>The following is a list of the available methods of signing in BIND, in the order that they were introduced - and in order of decreasing complexity.</p> <dl> <dt>Manual</dt><dd><p>“Manual” signing was the first method to be introduced into BIND and its name describes it perfectly: the user needs to do everything. In the more-automated methods, you load an unsigned zone file into <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a>, which takes care of signing it. With manual signing, you have to provide a signed zone for <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to serve.</p> <p>In practice, this means creating an unsigned zone file as usual, then using the BIND-provided tools <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a> to create the keys and <a class="reference internal" href="manpages.html#std-iscman-dnssec-signzone"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-signzone</span></code></a> to sign the zone. The signed zone is stored in another file and is the one you tell BIND to load. To update the zone (for example, to add a resource record), you update the unsigned zone, re-sign it, and tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to load the updated signed copy. The same goes for refreshing signatures or rolling keys; the user is responsible for providing the signed zone served by <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a>. (In the case of rolling keys, you are also responsible for ensuring that the keys are added and removed at the correct times.)</p> <p>Why would you want to sign your zone this way? You probably wouldn’t in the normal course of events, but as there may be circumstances in which it is required, the scripts have been left in the BIND distribution.</p> </dd> <dt>Semi-Automatic</dt><dd><p>The first step in DNSSEC automation came with BIND 9.7, when the <a class="reference internal" href="reference.html#namedconf-statement-auto-dnssec" title="namedconf-statement-auto-dnssec"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">auto-dnssec</span></code></a> option was added. This causes <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to periodically search the directory holding the key files (see <a class="reference internal" href="#generate-keys"><span class="std std-ref">Generate Keys</span></a> for a description) and to use the information in them to both add and remove keys and sign the zone.</p> <p>Use of <a class="reference internal" href="reference.html#namedconf-statement-auto-dnssec" title="namedconf-statement-auto-dnssec"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">auto-dnssec</span></code></a> alone requires that the zone be dynamic, something not suitable for a number of situations, so BIND 9.9 added the <a class="reference internal" href="reference.html#namedconf-statement-inline-signing" title="namedconf-statement-inline-signing"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">inline-signing</span></code></a> option. With this, <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> essentially keeps the signed and unsigned copies of the zone separate. The signed zone is created from the unsigned one using the key information; when the unsigned zone is updated and the zone reloaded, <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> detects the changes and updates the signed copy of the zone.</p> <p>This mode of signing has been termed “semi-automatic” in this document because keys still have to be manually created (and deleted when appropriate). Although not an onerous task, it is still additional work.</p> <p>Why would anyone want to use this method when fully automated ones are available? At the time of this writing (mid-2020), the fully automatic methods cannot handle all scenarios, particularly that of having a single key shared among multiple zones. They also do not handle keys stored in Hardware Security Modules (HSMs), which are briefly covered in <a class="reference internal" href="#hardware-security-modules"><span class="std std-ref">Hardware Security Modules (HSMs)</span></a>.</p> </dd> <dt>Fully Automatic with <code class="docutils literal notranslate"><span class="pre">dnssec-keymgr</span></code></dt><dd><p>The next step in the automation of DNSSEC operations came with BIND 9.11, which introduced the <code class="docutils literal notranslate"><span class="pre">dnssec-keymgr</span></code> utility. This is a separate program and was expected to be run on a regular basis (probably via <code class="docutils literal notranslate"><span class="pre">cron</span></code>). It read a DNSSEC policy from its configuration file and read timing information from the DNSSEC key files. With this information it created new key files with timing information in them consistent with the policy. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> was run as usual, picking up the timing information in the key files to determine when to add and remove keys, and when to sign with them.</p> <p>In BIND 9.17.0 and later, this method of handling DNSSEC policies has been replaced by the <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement in the configuration file.</p> </dd> <dt>Fully Automatic with <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a></dt><dd><p>Introduced a BIND 9.16, <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> replaces <code class="docutils literal notranslate"><span class="pre">dnssec-keymgr</span></code> from BIND 9.17 onwards and avoids the need to run a separate program. It also handles the creation of keys if a zone is added (<code class="docutils literal notranslate"><span class="pre">dnssec-keymgr</span></code> requires an initial key) and deletes old key files as they are removed from the zone. This is the method described in <a class="reference internal" href="#easy-start-guide-for-authoritative-servers"><span class="std std-ref">Easy-Start Guide for Signing Authoritative Zones</span></a>.</p> </dd> </dl> <p>We now look at some of these methods in more detail. We cover semi-automatic signing first, as that contains a lot of useful information about keys and key timings. After that, we touch on fully automatic signing with <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a>. Since this has already been described in <a class="reference internal" href="#easy-start-guide-for-authoritative-servers"><span class="std std-ref">Easy-Start Guide for Signing Authoritative Zones</span></a>, we will just mention a few additional points. Finally, we briefly describe manual signing.</p> <section id="semi-automatic-signing"> <span id="id33"></span><h4>Semi-Automatic Signing<a class="headerlink" href="#semi-automatic-signing" title="Permalink to this headline"></a></h4> <p>As noted above, the term semi-automatic signing has been used in this document to indicate the mode of signing enabled by the <a class="reference internal" href="reference.html#namedconf-statement-auto-dnssec" title="namedconf-statement-auto-dnssec"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">auto-dnssec</span></code></a> and <a class="reference internal" href="reference.html#namedconf-statement-inline-signing" title="namedconf-statement-inline-signing"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">inline-signing</span></code></a> keywords. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> signs the zone without any manual intervention, based purely on the timing information in the DNSSEC key files. The files, however, must be created manually.</p> <p>By appropriately setting the key parameters and the timing information in the key files, you can implement any DNSSEC policy you want for your zones. But why manipulate the key information yourself rather than rely on <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> to do it for you? The answer is that semi-automatic signing allows you to do things that, at the time of this writing (mid-2020), are currently not possible with one of the key managers: for example, the ability to use an HSM to store keys, or the ability to use the same key for multiple zones.</p> <p>To convert a traditional (insecure) DNS zone to a secure one, we need to create various additional records (DNSKEY, RRSIG, NSEC/NSEC3) and, as with fully automatic signing, to upload verifiable information (such as a DS record) to the parent zone to complete the chain of trust.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Again, we assume all configuration files, key files, and zone files are stored in <code class="docutils literal notranslate"><span class="pre">/etc/bind</span></code>, and most examples show commands run as the root user. This may not be ideal, but the point is not to distract from what is important here: learning how to sign a zone. There are many best practices for deploying a more secure BIND installation, with techniques such as jailed process and restricted user privileges, but those are not covered in this document. We trust you, a responsible DNS administrator, to take the necessary precautions to secure your system.</p> <p>For our examples below, we work with the assumption that there is an existing insecure zone <code class="docutils literal notranslate"><span class="pre">example.com</span></code> that we are converting to a secure version. The secure version uses both a KSK and a ZSK.</p> </div> <section id="generate-keys"> <span id="id34"></span><h5>Generate Keys<a class="headerlink" href="#generate-keys" title="Permalink to this headline"></a></h5> <p>Everything in DNSSEC centers around keys, so we begin by generating our own keys.</p> <div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp"># </span><span class="nb">cd</span> /etc/bind/keys <span class="gp"># </span>dnssec-keygen -a ECDSAP256SHA256 example.com <span class="go">Generating key pair...........................+++++ ......................+++++</span> <span class="go">Kexample.com.+013+34371</span> <span class="gp"># </span>dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com <span class="go">Generating key pair........................+++ ..................................+++</span> <span class="go">Kexample.com.+013+00472</span> </pre></div> </div> <p>This command generates four key files in <code class="docutils literal notranslate"><span class="pre">/etc/bind/keys</span></code>:</p> <ul class="simple"> <li><p>Kexample.com.+013+34371.key</p></li> <li><p>Kexample.com.+013+34371.private</p></li> <li><p>Kexample.com.+013+00472.key</p></li> <li><p>Kexample.com.+013+00472.private</p></li> </ul> <p>The two files ending in <code class="docutils literal notranslate"><span class="pre">.key</span></code> are the public keys. These contain the DNSKEY resource records that appear in the zone. The two files ending in <code class="docutils literal notranslate"><span class="pre">.private</span></code> are the private keys, and contain the information that <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> actually uses to sign the zone.</p> <p>Of the two pairs, one is the zone-signing key (ZSK), and one is the key-signing key (KSK). <a class="footnote-reference brackets" href="#signal-zone-presence" id="id35">7</a> We can tell which is which by looking at the file contents (the actual keys are shortened here for ease of display):</p> <div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp"># </span>cat Kexample.com.+013+34371.key <span class="go">; This is a zone-signing key, keyid 34371, for example.com.</span> <span class="go">; Created: 20200616104249 (Tue Jun 16 11:42:49 2020)</span> <span class="go">; Publish: 20200616104249 (Tue Jun 16 11:42:49 2020)</span> <span class="go">; Activate: 20200616104249 (Tue Jun 16 11:42:49 2020)</span> <span class="go">example.com. IN DNSKEY 256 3 13 AwEAAfel66...LqkA7cvn8=</span> <span class="gp"># </span>cat Kexample.com.+013+00472.key <span class="go">; This is a key-signing key, keyid 472, for example.com.</span> <span class="go">; Created: 20200616104254 (Tue Jun 16 11:42:54 2020)</span> <span class="go">; Publish: 20200616104254 (Tue Jun 16 11:42:54 2020)</span> <span class="go">; Activate: 20200616104254 (Tue Jun 16 11:42:54 2020)</span> <span class="go">example.com. IN DNSKEY 257 3 13 AwEAAbCR6U...l8xPjokVU=</span> </pre></div> </div> <p>The first line of each file tells us what type of key it is. Also, by looking at the actual DNSKEY record, we can tell them apart: 256 is ZSK, and 257 is KSK.</p> <p>The name of the file also tells us something about the contents. See chapter <a class="reference internal" href="chapter5.html#zone-keys"><span class="std std-ref">Zone keys</span></a> for more details.</p> <p>Make sure that these files are readable by <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> and that the <code class="docutils literal notranslate"><span class="pre">.private</span></code> files are not readable by anyone else.</p> <p>Alternativelly, the <a class="reference internal" href="manpages.html#std-iscman-dnssec-keyfromlabel"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keyfromlabel</span></code></a> program is used to get a key pair from a crypto hardware device and build the key files. Its usage is similar to <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a>.</p> </section> <section id="setting-key-timing-information"> <h5>Setting Key Timing Information<a class="headerlink" href="#setting-key-timing-information" title="Permalink to this headline"></a></h5> <p>You may remember that in the above description of this method, we said that time information related to rolling keys is stored in the key files. This is placed there by <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a> when the file is created, and it can be modified using <a class="reference internal" href="manpages.html#std-iscman-dnssec-settime"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-settime</span></code></a>. By default, only a limited amount of timing information is included in the file, as illustrated in the examples in the previous section.</p> <p>All the dates are the same, and are the date and time that <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a> created the key. We can use <a class="reference internal" href="manpages.html#std-iscman-dnssec-settime"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-settime</span></code></a> to modify the dates. The dates can also be modified using an editor, but that is likely to be more error-prone than using <a class="reference internal" href="manpages.html#std-iscman-dnssec-settime"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-settime</span></code></a>. For example, to publish this key in the zone on 1 July 2020, use it to sign records for a year starting on 15 July 2020, and remove it from the zone at the end of July 2021, we can use the following command:</p> <div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp"># </span>dnssec-settime -P <span class="m">20200701</span> -A <span class="m">20200715</span> -I <span class="m">20210715</span> -D <span class="m">20210731</span> Kexample.com.+013+34371.key <span class="go">./Kexample.com.+013+34371.key</span> <span class="go">./Kexample.com.+013+34371.private</span> </pre></div> </div> <p>which would set the contents of the key file to:</p> <div class="highlight-none notranslate"><div class="highlight"><pre><span></span>; This is a zone-signing key, keyid 34371, for example.com. ; Created: 20200616104249 (Tue Jun 16 11:42:49 2020) ; Publish: 20200701000000 (Wed Jul 1 01:00:00 2020) ; Activate: 20200715000000 (Wed Jul 15 01:00:00 2020) ; Inactive: 20210715000000 (Thu Jul 15 01:00:00 2021) ; Delete: 20210731000000 (Sat Jul 31 01:00:00 2021) example.com. IN DNSKEY 256 3 13 AwEAAfel66...LqkA7cvn8= </pre></div> </div> <p>(The actual key is truncated here to improve readability.)</p> <p>Below is a complete list of each of the metadata fields, and how each one affects the signing of your zone:</p> <ol class="arabic simple"> <li><p><em>Created</em>: This records the date on which the key was created. It is not used in calculations; it is useful simply for documentation purposes.</p></li> <li><p><em>Publish</em>: This sets the date on which a key is to be published to the zone. After that date, the key is included in the zone but is not used to sign it. This allows validating resolvers to get a copy of the new key in their cache before there are any resource records signed with it. By default, if not specified at creation time, this is set to the current time, meaning the key is published as soon as <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> picks it up.</p></li> <li><p><em>Activate</em>: This sets the date on which the key is to be activated. After that date, resource records are signed with the key. By default, if not specified during creation time, this is set to the current time, meaning the key is used to sign data as soon as <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> picks it up.</p></li> <li><p><em>Revoke:</em> This sets the date on which the key is to be revoked. After that date, the key is flagged as revoked, although it is still included in the zone and used to sign it. This is used to notify validating resolvers that this key is about to be removed or retired from the zone. (This state is not used in normal day-to-day operations. See <span class="target" id="index-4"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc5011.html"><strong>RFC 5011</strong></a> to understand the circumstances where it may be used.)</p></li> <li><p><em>Inactive</em>: This sets the date on which the key is to become inactive. After that date, the key is still included in the zone, but it is no longer used to sign it. This sets the “expiration” or “retire” date for a key.</p></li> <li><p><em>Delete</em>: This sets the date on which the key is to be deleted. After that date, the key is no longer included in the zone, but it continues to exist on the file system or key repository.</p></li> </ol> <p>This can be summarized as follows:</p> <table class="docutils align-default" id="id56"> <caption><span class="caption-text">Key Metadata Comparison</span><a class="headerlink" href="#id56" title="Permalink to this table"></a></caption> <colgroup> <col style="width: 16%" /> <col style="width: 28%" /> <col style="width: 28%" /> <col style="width: 28%" /> </colgroup> <thead> <tr class="row-odd"><th class="head"><p>Metadata</p></th> <th class="head"><p>Included in Zone File?</p></th> <th class="head"><p>Used to Sign Data?</p></th> <th class="head"><p>Purpose</p></th> </tr> </thead> <tbody> <tr class="row-even"><td><p>Created</p></td> <td><p>No</p></td> <td><p>No</p></td> <td><p>Recording of key creation</p></td> </tr> <tr class="row-odd"><td><p>Publish</p></td> <td><p>Yes</p></td> <td><p>No</p></td> <td><p>Introduction of a key soon to be active</p></td> </tr> <tr class="row-even"><td><p>Activate</p></td> <td><p>Yes</p></td> <td><p>Yes</p></td> <td><p>Activation date for new key</p></td> </tr> <tr class="row-odd"><td><p>Revoke</p></td> <td><p>Yes</p></td> <td><p>Yes</p></td> <td><p>Notification of a key soon to be retired</p></td> </tr> <tr class="row-even"><td><p>Inactive</p></td> <td><p>Yes</p></td> <td><p>No</p></td> <td><p>Inactivation or retirement of a key</p></td> </tr> <tr class="row-odd"><td><p>Delete</p></td> <td><p>No</p></td> <td><p>No</p></td> <td><p>Deletion or removal of a key from a zone</p></td> </tr> </tbody> </table> <p>The publication date is the date the key is introduced into the zone. Sometime later it is activated and is used to sign resource records. After a specified period, BIND stops using it to sign records, and at some other specified later time it is removed from the zone.</p> <p>Finally, we should note that the <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a> command supports the same set of switches so we could have set the dates when we created the key.</p> </section> <section id="reconfiguring-bind"> <span id="semi-automatic-signing-reconfigure-bind"></span><h5>Reconfiguring BIND<a class="headerlink" href="#reconfiguring-bind" title="Permalink to this headline"></a></h5> <p>Having created the keys with the appropriate timing information, the next step is to turn on DNSSEC signing. Below is a very simple <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a>; in our example environment, this file is <code class="docutils literal notranslate"><span class="pre">/etc/bind/named.conf</span></code>.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">options</span> <span class="p">{</span> <span class="n">directory</span> <span class="s2">"/etc/bind"</span><span class="p">;</span> <span class="n">recursion</span> <span class="n">no</span><span class="p">;</span> <span class="n">minimal</span><span class="o">-</span><span class="n">responses</span> <span class="n">yes</span><span class="p">;</span> <span class="p">};</span> <span class="n">zone</span> <span class="s2">"example.com"</span> <span class="n">IN</span> <span class="p">{</span> <span class="nb">type</span> <span class="n">primary</span><span class="p">;</span> <span class="n">file</span> <span class="s2">"example.com.db"</span><span class="p">;</span> <span class="n">auto</span><span class="o">-</span><span class="n">dnssec</span> <span class="n">maintain</span><span class="p">;</span> <span class="n">inline</span><span class="o">-</span><span class="n">signing</span> <span class="n">yes</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p>Once the configuration file is updated, tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to reload:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># rndc reload</span> <span class="n">server</span> <span class="n">reload</span> <span class="n">successful</span> </pre></div> </div> </section> <section id="verifying-that-the-zone-is-signed-correctly"> <span id="semi-automated-signing-verification"></span><h5>Verifying That the Zone Is Signed Correctly<a class="headerlink" href="#verifying-that-the-zone-is-signed-correctly" title="Permalink to this headline"></a></h5> <p>You should now check that the zone is signed. Follow the steps in <a class="reference internal" href="#signing-verification"><span class="std std-ref">Verification</span></a>.</p> </section> <section id="uploading-the-ds-record-to-the-parent"> <span id="semi-automatic-signing-upload-ds"></span><h5>Uploading the DS Record to the Parent<a class="headerlink" href="#uploading-the-ds-record-to-the-parent" title="Permalink to this headline"></a></h5> <p>As described in <a class="reference internal" href="#signing-easy-start-upload-to-parent-zone"><span class="std std-ref">Uploading Information to the Parent Zone</span></a>, we must now upload the new information to the parent zone. The format of the information and how to generate it is described in <a class="reference internal" href="#working-with-parent-zone"><span class="std std-ref">Working With the Parent Zone</span></a>, although it is important to remember that you must use the contents of the KSK file that you generated above as part of the process.</p> <p>When the DS record is published in the parent zone, your zone is fully signed.</p> </section> <section id="checking-that-your-zone-can-be-validated"> <h5>Checking That Your Zone Can Be Validated<a class="headerlink" href="#checking-that-your-zone-can-be-validated" title="Permalink to this headline"></a></h5> <p>Finally, follow the steps in <a class="reference internal" href="#how-to-test-authoritative-server"><span class="std std-ref">How To Test Authoritative Zones</span></a> to confirm that a query recognizes the zone as properly signed and vouched for by the parent zone.</p> </section> <section id="id36"> <h5>So… What Now?<a class="headerlink" href="#id36" title="Permalink to this headline"></a></h5> <p>Once the zone is signed, it must be monitored as described in <a class="reference internal" href="#signing-maintenance-tasks"><span class="std std-ref">Maintenance Tasks</span></a>. However, as the time approaches for a key roll, you must create the new key. Of course, it is possible to create keys for the next fifty years all at once and set the key times appropriately. Whether the increased risk in having the private key files for future keys available on disk offsets the overhead of having to remember to create a new key before a rollover depends on your organization’s security policy.</p> </section> </section> <section id="fully-automatic-signing-with-dnssec-policy"> <span id="advanced-discussions-automatic-dnssec-policy"></span><h4>Fully Automatic Signing With <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a><a class="headerlink" href="#fully-automatic-signing-with-dnssec-policy" title="Permalink to this headline"></a></h4> <p>Since BIND 9.16, key management is fully integrated ingo <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a>. Managing the signing process and rolling of these keys has been described in <a class="reference internal" href="#easy-start-guide-for-authoritative-servers"><span class="std std-ref">Easy-Start Guide for Signing Authoritative Zones</span></a> and is not repeated here. A few points are worth noting, though:</p> <ul class="simple"> <li><p>The <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement in the <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> configuration file describes all aspects of the DNSSEC policy, including the signing.</p></li> <li><p>The <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement requires to zone to use dynamic DNS, or that <a class="reference internal" href="reference.html#namedconf-statement-inline-signing" title="namedconf-statement-inline-signing"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">inline-signing</span></code></a> is enabled.</p></li> </ul> </section> <section id="manual-signing"> <span id="advanced-discussions-manual-key-management-and-signing"></span><h4>Manual Signing<a class="headerlink" href="#manual-signing" title="Permalink to this headline"></a></h4> <p>Manual signing of a zone was the first method of signing introduced into BIND and offers, as the name suggests, no automation. The user must handle everything: create the keys, sign the zone file with them, load the signed zone, periodically re-sign the zone, and manage key rolls, including interaction with the parent. A user certainly can do all this, but why not use one of the automated methods? Nevertheless, it may be useful for test purposes, so we cover it briefly here.</p> <p>BIND 9 ships with several tools that are used in this process, which are explained in more detail below. In all cases, the <code class="docutils literal notranslate"><span class="pre">-h</span></code> option prints a full list of parameters. Note that the DNSSEC tools require the keyset files to be in the working directory or the directory specified by the <code class="docutils literal notranslate"><span class="pre">-d</span></code> option.</p> <p>The first step is to create the keys as described in <a class="reference internal" href="#generate-keys"><span class="std std-ref">Generate Keys</span></a>.</p> <p>Then, edit the zone file to make sure the proper DNSKEY entries are included. The public keys should be inserted into the zone file by including the <code class="docutils literal notranslate"><span class="pre">.key</span></code> files using <code class="docutils literal notranslate"><span class="pre">$INCLUDE</span></code> statements.</p> <p>Finally, use the command <a class="reference internal" href="manpages.html#std-iscman-dnssec-signzone"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-signzone</span></code></a>. Any <code class="docutils literal notranslate"><span class="pre">keyset</span></code> files corresponding to secure sub-zones should be present. The zone signer generates <code class="docutils literal notranslate"><span class="pre">NSEC</span></code>, <code class="docutils literal notranslate"><span class="pre">NSEC3</span></code>, and <code class="docutils literal notranslate"><span class="pre">RRSIG</span></code> records for the zone, as well as <code class="docutils literal notranslate"><span class="pre">DS</span></code> for the child zones if <a class="reference internal" href="manpages.html#cmdoption-dnssec-signzone-g"><code class="xref std std-option docutils literal notranslate"><span class="pre">-g</span></code></a> is specified. If <a class="reference internal" href="manpages.html#cmdoption-dnssec-signzone-g"><code class="xref std std-option docutils literal notranslate"><span class="pre">-g</span></code></a> is not specified, then DS RRsets for the secure child zones need to be added manually.</p> <p>By default, all zone keys which have an available private key are used to generate signatures. The following command signs the zone, assuming it is in a file called <code class="docutils literal notranslate"><span class="pre">zone.child.example</span></code>, using manually specified keys:</p> <div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp"># </span><span class="nb">cd</span> /etc/bind/keys/example.com/ <span class="gp"># </span>dnssec-signzone -t -N INCREMENT -o example.com -f /etc/bind/db/example.com.signed.db <span class="se">\</span> /etc/bind/db/example.com.db Kexample.com.+013+17694.key Kexample.com.+013+06817.key <span class="go">Verifying the zone using the following algorithms: ECDSAP256SHA256.</span> <span class="go">Zone fully signed:</span> <span class="go">Algorithm: ECDSAP256SHA256: KSKs: 1 active, 0 stand-by, 0 revoked</span> <span class="go"> ZSKs: 1 active, 0 stand-by, 0 revoked</span> <span class="go">/etc/bind/db/example.com.signed.db</span> <span class="go">Signatures generated: 17</span> <span class="go">Signatures retained: 0</span> <span class="go">Signatures dropped: 0</span> <span class="go">Signatures successfully verified: 0</span> <span class="go">Signatures unsuccessfully verified: 0</span> <span class="go">Signing time in seconds: 0.046</span> <span class="go">Signatures per second: 364.634</span> <span class="go">Runtime in seconds: 0.055</span> </pre></div> </div> <p>The <a class="reference internal" href="manpages.html#cmdoption-dnssec-signzone-o"><code class="xref std std-option docutils literal notranslate"><span class="pre">-o</span></code></a> switch explicitly defines the domain name (<code class="docutils literal notranslate"><span class="pre">example.com</span></code> in this case), while the <a class="reference internal" href="manpages.html#cmdoption-dnssec-signzone-f"><code class="xref std std-option docutils literal notranslate"><span class="pre">-f</span></code></a> switch specifies the output file name. The second line has three parameters: the unsigned zone name (<code class="docutils literal notranslate"><span class="pre">/etc/bind/db/example.com.db</span></code>), the ZSK file name, and the KSK file name. This also generates a plain-text file <code class="docutils literal notranslate"><span class="pre">/etc/bind/db/example.com.signed.db</span></code>, which can be manually verified for correctness.</p> <p><a class="reference internal" href="manpages.html#std-iscman-dnssec-signzone"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-signzone</span></code></a> also produces keyset and dsset files. These are used to provide the parent zone administrators with the <code class="docutils literal notranslate"><span class="pre">DNSKEY</span></code> records (or their corresponding <code class="docutils literal notranslate"><span class="pre">DS</span></code> records) that are the secure entry point to the zone.</p> <p>Finally, <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a> needs to be updated to load the signed version of the zone, which looks something like this:</p> <div class="highlight-none notranslate"><div class="highlight"><pre><span></span>zone "example.com" IN { type primary; file "db/example.com.signed.db"; }; </pre></div> </div> <p>Once the <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-reconfig"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">reconfig</span></code></a> command is issued, BIND serves a signed zone. The file <code class="docutils literal notranslate"><span class="pre">dsset-example.com</span></code> (created by <a class="reference internal" href="manpages.html#std-iscman-dnssec-signzone"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-signzone</span></code></a> when it signed the <code class="docutils literal notranslate"><span class="pre">example.com</span></code> zone) contains the DS record for the zone’s KSK. You will need to pass that to the administrator of the parent zone, to be placed in the zone.</p> <p>Since this is a manual process, you will need to re-sign periodically, as well as every time the zone data changes. You will also need to manually roll the keys by adding and removing DNSKEY records (and interacting with the parent) at the appropriate times.</p> <dl class="footnote brackets"> <dt class="label" id="signal-zone-presence"><span class="brackets"><a class="fn-backref" href="#id35">7</a></span></dt> <dd><p>Only one key file - for either a KSK or ZSK - is needed to signal the presence of the zone. <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a> creates files of both types as needed.</p> </dd> </dl> </section> </section> </section> <section id="basic-dnssec-troubleshooting"> <span id="dnssec-troubleshooting"></span><h2>Basic DNSSEC Troubleshooting<a class="headerlink" href="#basic-dnssec-troubleshooting" title="Permalink to this headline"></a></h2> <p>In this chapter, we cover some basic troubleshooting techniques, some common DNSSEC symptoms, and their causes and solutions. This is not a comprehensive “how to troubleshoot any DNS or DNSSEC problem” guide, because that could easily be an entire book by itself.</p> <section id="query-path"> <span id="troubleshooting-query-path"></span><h3>Query Path<a class="headerlink" href="#query-path" title="Permalink to this headline"></a></h3> <p>The first step in troubleshooting DNS or DNSSEC should be to determine the query path. Whenever you are working with a DNS-related issue, it is always a good idea to determine the exact query path to identify the origin of the problem.</p> <p>End clients, such as laptop computers or mobile phones, are configured to talk to a recursive name server, and the recursive name server may in turn forward requests on to other recursive name servers before arriving at the authoritative name server. The giveaway is the presence of the Authoritative Answer (<code class="docutils literal notranslate"><span class="pre">aa</span></code>) flag in a query response: when present, we know we are talking to the authoritative server; when missing, we are talking to a recursive server. The example below shows an answer to a query for <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code> without the Authoritative Answer flag:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.3 www.example.com A ; <<>> DiG 9.16.0 <<>> @10.53.0.3 www.example.com a ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62714 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: c823fe302625db5b010000005e722b504d81bb01c2227259 (good) ;; QUESTION SECTION: ;www.example.com. IN A ;; ANSWER SECTION: www.example.com. 60 IN A 10.1.0.1 ;; Query time: 3 msec ;; SERVER: 10.53.0.3#53(10.53.0.3) ;; WHEN: Wed Mar 18 14:08:16 GMT 2020 ;; MSG SIZE rcvd: 88 </pre></div> </div> <p>Not only do we not see the <code class="docutils literal notranslate"><span class="pre">aa</span></code> flag, we see an <code class="docutils literal notranslate"><span class="pre">ra</span></code> flag, which indicates Recursion Available. This indicates that the server we are talking to (10.53.0.3 in this example) is a recursive name server: although we were able to get an answer for <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code>, we know that the answer came from somewhere else.</p> <p>If we query the authoritative server directly, we get:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.2 www.example.com A ; <<>> DiG 9.16.0 <<>> @10.53.0.2 www.example.com a ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39542 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ... </pre></div> </div> <p>The <code class="docutils literal notranslate"><span class="pre">aa</span></code> flag tells us that we are now talking to the authoritative name server for <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code>, and that this is not a cached answer it obtained from some other name server; it served this answer to us right from its own database. In fact, the Recursion Available (<code class="docutils literal notranslate"><span class="pre">ra</span></code>) flag is not present, which means this name server is not configured to perform recursion (at least not for this client), so it could not have queried another name server to get cached results.</p> </section> <section id="visible-dnssec-validation-symptoms"> <span id="troubleshooting-visible-symptoms"></span><h3>Visible DNSSEC Validation Symptoms<a class="headerlink" href="#visible-dnssec-validation-symptoms" title="Permalink to this headline"></a></h3> <p>After determining the query path, it is necessary to determine whether the problem is actually related to DNSSEC validation. You can use the <a class="reference internal" href="manpages.html#cmdoption-dig-arg-cd"><code class="xref std std-option docutils literal notranslate"><span class="pre">dig</span> <span class="pre">+cd</span></code></a> flag to disable validation, as described in <a class="reference internal" href="#how-do-i-know-validation-problem"><span class="std std-ref">How Do I Know I Have a Validation Problem?</span></a>.</p> <p>When there is indeed a DNSSEC validation problem, the visible symptoms, unfortunately, are very limited. With DNSSEC validation enabled, if a DNS response is not fully validated, it results in a generic SERVFAIL message, as shown below when querying against a recursive name server at 192.168.1.7:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.3 www.example.org. A ; <<>> DiG 9.16.0 <<>> @10.53.0.3 www.example.org A ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 28947 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: d1301968aca086ad010000005e723a7113603c01916d136b (good) ;; QUESTION SECTION: ;www.example.org. IN A ;; Query time: 3 msec ;; SERVER: 10.53.0.3#53(10.53.0.3) ;; WHEN: Wed Mar 18 15:12:49 GMT 2020 ;; MSG SIZE rcvd: 72 </pre></div> </div> <p>With <a class="reference internal" href="manpages.html#std-iscman-delv"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">delv</span></code></a>, a “resolution failed” message is output instead:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ delv @10.53.0.3 www.example.org. A +rtrace ;; fetch: www.example.org/A ;; resolution failed: SERVFAIL </pre></div> </div> <p>BIND 9 logging features may be useful when trying to identify DNSSEC errors.</p> </section> <section id="basic-logging"> <span id="troubleshooting-logging"></span><h3>Basic Logging<a class="headerlink" href="#basic-logging" title="Permalink to this headline"></a></h3> <p>DNSSEC validation error messages show up in <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a> as a query error by default. Here is an example of what it may look like:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">validating</span> <span class="n">www</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="n">no</span> <span class="n">valid</span> <span class="n">signature</span> <span class="n">found</span> <span class="n">RRSIG</span> <span class="n">failed</span> <span class="n">to</span> <span class="n">verify</span> <span class="n">resolving</span> <span class="s1">'www.example.org/A/IN'</span><span class="p">:</span> <span class="mf">10.53.0.2</span><span class="c1">#53</span> </pre></div> </div> <p>Usually, this level of error logging is sufficient. Debug logging, described in <a class="reference internal" href="#troubleshooting-logging-debug"><span class="std std-ref">BIND DNSSEC Debug Logging</span></a>, gives information on how to get more details about why DNSSEC validation may have failed.</p> </section> <section id="bind-dnssec-debug-logging"> <span id="troubleshooting-logging-debug"></span><h3>BIND DNSSEC Debug Logging<a class="headerlink" href="#bind-dnssec-debug-logging" title="Permalink to this headline"></a></h3> <p>A word of caution: before you enable debug logging, be aware that this may dramatically increase the load on your name servers. Enabling debug logging is thus not recommended for production servers.</p> <p>With that said, sometimes it may become necessary to temporarily enable BIND debug logging to see more details of how and whether DNSSEC is validating. DNSSEC-related messages are not recorded in <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a> by default, even if query log is enabled; only DNSSEC errors show up in <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a>.</p> <p>The example below shows how to enable debug level 3 (to see full DNSSEC validation messages) in BIND 9 and have it sent to <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">logging</span> <span class="p">{</span> <span class="n">channel</span> <span class="n">dnssec_log</span> <span class="p">{</span> <span class="n">syslog</span> <span class="n">daemon</span><span class="p">;</span> <span class="n">severity</span> <span class="n">debug</span> <span class="mi">3</span><span class="p">;</span> <span class="nb">print</span><span class="o">-</span><span class="n">category</span> <span class="n">yes</span><span class="p">;</span> <span class="p">};</span> <span class="n">category</span> <span class="n">dnssec</span> <span class="p">{</span> <span class="n">dnssec_log</span><span class="p">;</span> <span class="p">};</span> <span class="p">};</span> </pre></div> </div> <p>The example below shows how to log DNSSEC messages to their own file (here, <code class="docutils literal notranslate"><span class="pre">/var/log/dnssec.log</span></code>):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">logging</span> <span class="p">{</span> <span class="n">channel</span> <span class="n">dnssec_log</span> <span class="p">{</span> <span class="n">file</span> <span class="s2">"/var/log/dnssec.log"</span><span class="p">;</span> <span class="n">severity</span> <span class="n">debug</span> <span class="mi">3</span><span class="p">;</span> <span class="p">};</span> <span class="n">category</span> <span class="n">dnssec</span> <span class="p">{</span> <span class="n">dnssec_log</span><span class="p">;</span> <span class="p">};</span> <span class="p">};</span> </pre></div> </div> <p>After turning on debug logging and restarting BIND, a large number of log messages appear in <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a>. The example below shows the log messages as a result of successfully looking up and validating the domain name <code class="docutils literal notranslate"><span class="pre">ftp.isc.org</span></code>.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">validating</span> <span class="o">./</span><span class="n">NS</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="o">./</span><span class="n">NS</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">verify</span> <span class="n">rdataset</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">20326</span><span class="p">):</span> <span class="n">success</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">marking</span> <span class="k">as</span> <span class="n">secure</span> <span class="p">(</span><span class="n">DS</span><span class="p">)</span> <span class="n">validating</span> <span class="o">./</span><span class="n">NS</span><span class="p">:</span> <span class="ow">in</span> <span class="n">validator_callback_dnskey</span> <span class="n">validating</span> <span class="o">./</span><span class="n">NS</span><span class="p">:</span> <span class="n">keyset</span> <span class="k">with</span> <span class="n">trust</span> <span class="n">secure</span> <span class="n">validating</span> <span class="o">./</span><span class="n">NS</span><span class="p">:</span> <span class="n">resuming</span> <span class="n">validate</span> <span class="n">validating</span> <span class="o">./</span><span class="n">NS</span><span class="p">:</span> <span class="n">verify</span> <span class="n">rdataset</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">33853</span><span class="p">):</span> <span class="n">success</span> <span class="n">validating</span> <span class="o">./</span><span class="n">NS</span><span class="p">:</span> <span class="n">marking</span> <span class="k">as</span> <span class="n">secure</span><span class="p">,</span> <span class="n">noqname</span> <span class="n">proof</span> <span class="ow">not</span> <span class="n">needed</span> <span class="n">validating</span> <span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">keyset</span> <span class="k">with</span> <span class="n">trust</span> <span class="n">secure</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">verify</span> <span class="n">rdataset</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">33853</span><span class="p">):</span> <span class="n">success</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">marking</span> <span class="k">as</span> <span class="n">secure</span><span class="p">,</span> <span class="n">noqname</span> <span class="n">proof</span> <span class="ow">not</span> <span class="n">needed</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="ow">in</span> <span class="n">validator_callback_ds</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">dsset</span> <span class="k">with</span> <span class="n">trust</span> <span class="n">secure</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">verify</span> <span class="n">rdataset</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">9795</span><span class="p">):</span> <span class="n">success</span> <span class="n">validating</span> <span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">marking</span> <span class="k">as</span> <span class="n">secure</span> <span class="p">(</span><span class="n">DS</span><span class="p">)</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="ow">in</span> <span class="n">fetch_callback_dnskey</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">keyset</span> <span class="k">with</span> <span class="n">trust</span> <span class="n">secure</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">resuming</span> <span class="n">validate</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">verify</span> <span class="n">rdataset</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">33209</span><span class="p">):</span> <span class="n">success</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DS</span><span class="p">:</span> <span class="n">marking</span> <span class="k">as</span> <span class="n">secure</span><span class="p">,</span> <span class="n">noqname</span> <span class="n">proof</span> <span class="ow">not</span> <span class="n">needed</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="ow">in</span> <span class="n">validator_callback_ds</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">dsset</span> <span class="k">with</span> <span class="n">trust</span> <span class="n">secure</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">verify</span> <span class="n">rdataset</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">7250</span><span class="p">):</span> <span class="n">success</span> <span class="n">validating</span> <span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">marking</span> <span class="k">as</span> <span class="n">secure</span> <span class="p">(</span><span class="n">DS</span><span class="p">)</span> <span class="n">validating</span> <span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="ow">in</span> <span class="n">fetch_callback_dnskey</span> <span class="n">validating</span> <span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="n">keyset</span> <span class="k">with</span> <span class="n">trust</span> <span class="n">secure</span> <span class="n">validating</span> <span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="n">resuming</span> <span class="n">validate</span> <span class="n">validating</span> <span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="n">verify</span> <span class="n">rdataset</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">27566</span><span class="p">):</span> <span class="n">success</span> <span class="n">validating</span> <span class="n">ftp</span><span class="o">.</span><span class="n">isc</span><span class="o">.</span><span class="n">org</span><span class="o">/</span><span class="n">A</span><span class="p">:</span> <span class="n">marking</span> <span class="k">as</span> <span class="n">secure</span><span class="p">,</span> <span class="n">noqname</span> <span class="n">proof</span> <span class="ow">not</span> <span class="n">needed</span> </pre></div> </div> <p>Note that these log messages indicate that the chain of trust has been established and <code class="docutils literal notranslate"><span class="pre">ftp.isc.org</span></code> has been successfully validated.</p> <p>If validation had failed, you would see log messages indicating errors. We cover some of the most validation problems in the next section.</p> </section> <section id="common-problems"> <span id="troubleshooting-common-problems"></span><h3>Common Problems<a class="headerlink" href="#common-problems" title="Permalink to this headline"></a></h3> <section id="security-lameness"> <span id="troubleshooting-security-lameness"></span><h4>Security Lameness<a class="headerlink" href="#security-lameness" title="Permalink to this headline"></a></h4> <p>Similar to lame delegation in traditional DNS, security lameness refers to the condition when the parent zone holds a set of DS records that point to something that does not exist in the child zone. As a result, the entire child zone may “disappear,” having been marked as bogus by validating resolvers.</p> <p>Below is an example attempting to resolve the A record for a test domain name <code class="docutils literal notranslate"><span class="pre">www.example.net</span></code>. From the user’s perspective, as described in <a class="reference internal" href="#how-do-i-know-validation-problem"><span class="std std-ref">How Do I Know I Have a Validation Problem?</span></a>, only a SERVFAIL message is returned. On the validating resolver, we see the following messages in <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">named</span><span class="p">[</span><span class="mi">126063</span><span class="p">]:</span> <span class="n">validating</span> <span class="n">example</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">no</span> <span class="n">valid</span> <span class="n">signature</span> <span class="n">found</span> <span class="p">(</span><span class="n">DS</span><span class="p">)</span> <span class="n">named</span><span class="p">[</span><span class="mi">126063</span><span class="p">]:</span> <span class="n">no</span> <span class="n">valid</span> <span class="n">RRSIG</span> <span class="n">resolving</span> <span class="s1">'example.net/DNSKEY/IN'</span><span class="p">:</span> <span class="mf">10.53.0.2</span><span class="c1">#53</span> <span class="n">named</span><span class="p">[</span><span class="mi">126063</span><span class="p">]:</span> <span class="n">broken</span> <span class="n">trust</span> <span class="n">chain</span> <span class="n">resolving</span> <span class="s1">'www.example.net/A/IN'</span><span class="p">:</span> <span class="mf">10.53.0.2</span><span class="c1">#53</span> </pre></div> </div> <p>This gives us a hint that it is a broken trust chain issue. Let’s take a look at the DS records that are published for the zone (with the keys shortened for ease of display):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.3 example.net. DS ; <<>> DiG 9.16.0 <<>> @10.53.0.3 example.net DS ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59602 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 7026d8f7c6e77e2a010000005e735d7c9d038d061b2d24da (good) ;; QUESTION SECTION: ;example.net. IN DS ;; ANSWER SECTION: example.net. 256 IN DS 14956 8 2 9F3CACD...D3E3A396 ;; Query time: 0 msec ;; SERVER: 10.53.0.3#53(10.53.0.3) ;; WHEN: Thu Mar 19 11:54:36 GMT 2020 ;; MSG SIZE rcvd: 116 </pre></div> </div> <p>Next, we query for the DNSKEY and RRSIG of <code class="docutils literal notranslate"><span class="pre">example.net</span></code> to see if there’s anything wrong. Since we are having trouble validating, we can use the <a class="reference internal" href="manpages.html#cmdoption-dig-arg-cd"><code class="xref std std-option docutils literal notranslate"><span class="pre">dig</span> <span class="pre">+cd</span></code></a> option to temporarily disable checking and return results, even though they do not pass the validation tests. The <a class="reference internal" href="manpages.html#cmdoption-dig-arg-multiline"><code class="xref std std-option docutils literal notranslate"><span class="pre">dig</span> <span class="pre">+multiline</span></code></a> option causes <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> to print the type, algorithm type, and key id for DNSKEY records. Again, some long strings are shortened for ease of display:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.3 example.net. DNSKEY +dnssec +cd +multiline ; <<>> DiG 9.16.0 <<>> @10.53.0.3 example.net DNSKEY +cd +multiline +dnssec ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42980 ;; flags: qr rd ra cd; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ; COOKIE: 4b5e7c88b3680c35010000005e73722057551f9f8be1990e (good) ;; QUESTION SECTION: ;example.net. IN DNSKEY ;; ANSWER SECTION: example.net. 287 IN DNSKEY 256 3 8 ( AwEAAbu3NX...ADU/D7xjFFDu+8WRIn ) ; ZSK; alg = RSASHA256 ; key id = 35328 example.net. 287 IN DNSKEY 257 3 8 ( AwEAAbKtU1...PPP4aQZTybk75ZW+uL 6OJMAF63NO0s1nAZM2EWAVasbnn/X+J4N2rLuhk= ) ; KSK; alg = RSASHA256 ; key id = 27247 example.net. 287 IN RRSIG DNSKEY 8 2 300 ( 20811123173143 20180101000000 27247 example.net. Fz1sjClIoF...YEjzpAWuAj9peQ== ) example.net. 287 IN RRSIG DNSKEY 8 2 300 ( 20811123173143 20180101000000 35328 example.net. seKtUeJ4/l...YtDc1rcXTVlWIOw= ) ;; Query time: 0 msec ;; SERVER: 10.53.0.3#53(10.53.0.3) ;; WHEN: Thu Mar 19 13:22:40 GMT 2020 ;; MSG SIZE rcvd: 962 </pre></div> </div> <p>Here is the problem: the parent zone is telling the world that <code class="docutils literal notranslate"><span class="pre">example.net</span></code> is using the key 14956, but the authoritative server indicates that it is using keys 27247 and 35328. There are several potential causes for this mismatch: one possibility is that a malicious attacker has compromised one side and changed the data. A more likely scenario is that the DNS administrator for the child zone did not upload the correct key information to the parent zone.</p> </section> <section id="incorrect-time"> <span id="troubleshooting-incorrect-time"></span><h4>Incorrect Time<a class="headerlink" href="#incorrect-time" title="Permalink to this headline"></a></h4> <p>In DNSSEC, every record comes with at least one RRSIG, and each RRSIG contains two timestamps: one indicating when it becomes valid, and one when it expires. If the validating resolver’s current system time does not fall within the two RRSIG timestamps, error messages appear in the BIND debug log.</p> <p>The example below shows a log message when the RRSIG appears to have expired. This could mean the validating resolver system time is incorrectly set too far in the future, or the zone administrator has not kept up with RRSIG maintenance.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">validating</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">verify</span> <span class="n">failed</span> <span class="n">due</span> <span class="n">to</span> <span class="n">bad</span> <span class="n">signature</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">19036</span><span class="p">):</span> <span class="n">RRSIG</span> <span class="n">has</span> <span class="n">expired</span> </pre></div> </div> <p>The log below shows that the RRSIG validity period has not yet begun. This could mean the validation resolver’s system time is incorrectly set too far in the past, or the zone administrator has incorrectly generated signatures for this domain name.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">validating</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">verify</span> <span class="n">failed</span> <span class="n">due</span> <span class="n">to</span> <span class="n">bad</span> <span class="n">signature</span> <span class="p">(</span><span class="n">keyid</span><span class="o">=</span><span class="mi">4521</span><span class="p">):</span> <span class="n">RRSIG</span> <span class="n">validity</span> <span class="n">period</span> <span class="n">has</span> <span class="ow">not</span> <span class="n">begun</span> </pre></div> </div> </section> <section id="unable-to-load-keys"> <span id="troubleshooting-unable-to-load-keys"></span><h4>Unable to Load Keys<a class="headerlink" href="#unable-to-load-keys" title="Permalink to this headline"></a></h4> <p>This is a simple yet common issue. If the key files are present but unreadable by <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> for some reason, the <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a> returns clear error messages, as shown below:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">named</span><span class="p">[</span><span class="mi">32447</span><span class="p">]:</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="n">reconfiguring</span> <span class="n">zone</span> <span class="n">keys</span> <span class="n">named</span><span class="p">[</span><span class="mi">32447</span><span class="p">]:</span> <span class="n">dns_dnssec_findmatchingkeys</span><span class="p">:</span> <span class="n">error</span> <span class="n">reading</span> <span class="n">key</span> <span class="n">file</span> <span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">008</span><span class="o">+</span><span class="mf">06817.</span><span class="n">private</span><span class="p">:</span> <span class="n">permission</span> <span class="n">denied</span> <span class="n">named</span><span class="p">[</span><span class="mi">32447</span><span class="p">]:</span> <span class="n">dns_dnssec_findmatchingkeys</span><span class="p">:</span> <span class="n">error</span> <span class="n">reading</span> <span class="n">key</span> <span class="n">file</span> <span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">008</span><span class="o">+</span><span class="mf">17694.</span><span class="n">private</span><span class="p">:</span> <span class="n">permission</span> <span class="n">denied</span> <span class="n">named</span><span class="p">[</span><span class="mi">32447</span><span class="p">]:</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="nb">next</span> <span class="n">key</span> <span class="n">event</span><span class="p">:</span> <span class="mi">27</span><span class="o">-</span><span class="n">Nov</span><span class="o">-</span><span class="mi">2014</span> <span class="mi">20</span><span class="p">:</span><span class="mi">04</span><span class="p">:</span><span class="mf">36.521</span> </pre></div> </div> <p>However, if no keys are found, the error is not as obvious. Below shows the <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a> messages after executing <code class="docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">reload</span></code> with the key files missing from the key directory:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">received</span> <span class="n">control</span> <span class="n">channel</span> <span class="n">command</span> <span class="s1">'reload'</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">loading</span> <span class="n">configuration</span> <span class="kn">from</span> <span class="s1">'/etc/bind/named.conf'</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">reading</span> <span class="n">built</span><span class="o">-</span><span class="ow">in</span> <span class="n">trusted</span> <span class="n">keys</span> <span class="kn">from</span> <span class="nn">file</span> <span class="s1">'/etc/bind/bind.keys'</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">using</span> <span class="n">default</span> <span class="n">UDP</span><span class="o">/</span><span class="n">IPv4</span> <span class="n">port</span> <span class="nb">range</span><span class="p">:</span> <span class="p">[</span><span class="mi">1024</span><span class="p">,</span> <span class="mi">65535</span><span class="p">]</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">using</span> <span class="n">default</span> <span class="n">UDP</span><span class="o">/</span><span class="n">IPv6</span> <span class="n">port</span> <span class="nb">range</span><span class="p">:</span> <span class="p">[</span><span class="mi">1024</span><span class="p">,</span> <span class="mi">65535</span><span class="p">]</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">sizing</span> <span class="n">zone</span> <span class="n">task</span> <span class="n">pool</span> <span class="n">based</span> <span class="n">on</span> <span class="mi">6</span> <span class="n">zones</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">the</span> <span class="n">working</span> <span class="n">directory</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">writable</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">reloading</span> <span class="n">configuration</span> <span class="n">succeeded</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">reloading</span> <span class="n">zones</span> <span class="n">succeeded</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="nb">all</span> <span class="n">zones</span> <span class="n">loaded</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">running</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="n">reconfiguring</span> <span class="n">zone</span> <span class="n">keys</span> <span class="n">named</span><span class="p">[</span><span class="mi">32516</span><span class="p">]:</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="nb">next</span> <span class="n">key</span> <span class="n">event</span><span class="p">:</span> <span class="mi">27</span><span class="o">-</span><span class="n">Nov</span><span class="o">-</span><span class="mi">2014</span> <span class="mi">20</span><span class="p">:</span><span class="mi">07</span><span class="p">:</span><span class="mf">09.292</span> </pre></div> </div> <p>This happens to look exactly the same as if the keys were present and readable, and appears to indicate that <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> loaded the keys and signed the zone. It even generates the internal (raw) files:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind/db</span> <span class="c1"># ls</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">jbk</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">signed</span> </pre></div> </div> <p>If <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> really loaded the keys and signed the zone, you should see the following files:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind/db</span> <span class="c1"># ls</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">jbk</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">signed</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">signed</span><span class="o">.</span><span class="n">jnl</span> </pre></div> </div> <p>So, unless you see the <code class="docutils literal notranslate"><span class="pre">*.signed.jnl</span></code> file, your zone has not been signed.</p> </section> <section id="invalid-trust-anchors"> <span id="troubleshooting-invalid-trust-anchors"></span><h4>Invalid Trust Anchors<a class="headerlink" href="#invalid-trust-anchors" title="Permalink to this headline"></a></h4> <p>In most cases, you never need to explicitly configure trust anchors. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> supplies the current root trust anchor and, with the default setting of <a class="reference internal" href="reference.html#namedconf-statement-dnssec-validation" title="namedconf-statement-dnssec-validation"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-validation</span></code></a>, updates it on the infrequent occasions when it is changed.</p> <p>However, in some circumstances you may need to explicitly configure your own trust anchor. As we saw in the <a class="reference internal" href="#trust-anchors-description"><span class="std std-ref">Trust Anchors</span></a> section, whenever a DNSKEY is received by the validating resolver, it is compared to the list of keys the resolver explicitly trusts to see if further action is needed. If the two keys match, the validating resolver stops performing further verification and returns the answer(s) as validated.</p> <p>But what if the key file on the validating resolver is misconfigured or missing? Below we show some examples of log messages when things are not working properly.</p> <p>First of all, if the key you copied is malformed, BIND does not even start and you will likely find this error message in syslog:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">named</span><span class="p">[</span><span class="mi">18235</span><span class="p">]:</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">bind</span><span class="o">/</span><span class="n">named</span><span class="o">.</span><span class="n">conf</span><span class="o">.</span><span class="n">options</span><span class="p">:</span><span class="mi">29</span><span class="p">:</span> <span class="n">bad</span> <span class="n">base64</span> <span class="n">encoding</span> <span class="n">named</span><span class="p">[</span><span class="mi">18235</span><span class="p">]:</span> <span class="n">loading</span> <span class="n">configuration</span><span class="p">:</span> <span class="n">failure</span> </pre></div> </div> <p>If the key is a valid base64 string but the key algorithm is incorrect, or if the wrong key is installed, the first thing you will notice is that virtually all of your DNS lookups result in SERVFAIL, even when you are looking up domain names that have not been DNSSEC-enabled. Below shows an example of querying a recursive server 10.53.0.3:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @10.53.0.3 www.example.com. A ; <<>> DiG 9.16.0 <<>> @10.53.0.3 www.example.org A +dnssec ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 29586 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ; COOKIE: ee078fc321fa1367010000005e73a58bf5f205ca47e04bed (good) ;; QUESTION SECTION: ;www.example.org. IN A </pre></div> </div> <p><a class="reference internal" href="manpages.html#std-iscman-delv"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">delv</span></code></a> shows a similar result:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ delv @192.168.1.7 www.example.com. +rtrace ;; fetch: www.example.com/A ;; resolution failed: SERVFAIL </pre></div> </div> <p>The next symptom you see is in the DNSSEC log messages:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">managed</span><span class="o">-</span><span class="n">keys</span><span class="o">-</span><span class="n">zone</span><span class="p">:</span> <span class="n">DNSKEY</span> <span class="nb">set</span> <span class="k">for</span> <span class="n">zone</span> <span class="s1">'.'</span> <span class="n">could</span> <span class="ow">not</span> <span class="n">be</span> <span class="n">verified</span> <span class="k">with</span> <span class="n">current</span> <span class="n">keys</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">starting</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">attempting</span> <span class="n">positive</span> <span class="n">response</span> <span class="n">validation</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">no</span> <span class="n">DNSKEY</span> <span class="n">matching</span> <span class="n">DS</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">no</span> <span class="n">DNSKEY</span> <span class="n">matching</span> <span class="n">DS</span> <span class="n">validating</span> <span class="o">./</span><span class="n">DNSKEY</span><span class="p">:</span> <span class="n">no</span> <span class="n">valid</span> <span class="n">signature</span> <span class="n">found</span> <span class="p">(</span><span class="n">DS</span><span class="p">)</span> </pre></div> </div> <p>These errors are indications that there are problems with the trust anchor.</p> </section> </section> <section id="negative-trust-anchors"> <span id="troubleshooting-nta"></span><h3>Negative Trust Anchors<a class="headerlink" href="#negative-trust-anchors" title="Permalink to this headline"></a></h3> <p>BIND 9.11 introduced Negative Trust Anchors (NTAs) as a means to <em>temporarily</em> disable DNSSEC validation for a zone when you know that the zone’s DNSSEC is misconfigured.</p> <p>NTAs are added using the <a class="reference internal" href="manpages.html#std-iscman-rndc"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">rndc</span></code></a> command, e.g.:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ rndc nta example.com Negative trust anchor added: example.com/_default, expires 19-Mar-2020 19:57:42.000 </pre></div> </div> <p>The list of currently configured NTAs can also be examined using <a class="reference internal" href="manpages.html#std-iscman-rndc"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">rndc</span></code></a>, e.g.:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ rndc nta -dump example.com/_default: expiry 19-Mar-2020 19:57:42.000 </pre></div> </div> <p>The default lifetime of an NTA is one hour, although by default, BIND polls the zone every five minutes to see if the zone correctly validates, at which point the NTA automatically expires. Both the default lifetime and the polling interval may be configured via <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a>, and the lifetime can be overridden on a per-zone basis using the <code class="docutils literal notranslate"><span class="pre">-lifetime</span> <span class="pre">duration</span></code> parameter to <code class="docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">nta</span></code>. Both timer values have a permitted maximum value of one week.</p> </section> <section id="nsec3-troubleshooting"> <span id="troubleshooting-nsec3"></span><h3>NSEC3 Troubleshooting<a class="headerlink" href="#nsec3-troubleshooting" title="Permalink to this headline"></a></h3> <p>BIND includes a tool called <a class="reference internal" href="manpages.html#std-iscman-nsec3hash"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nsec3hash</span></code></a> that runs through the same steps as a validating resolver, to generate the correct hashed name based on NSEC3PARAM parameters. The command takes the following parameters in order: salt, algorithm, iterations, and domain. For example, if the salt is 1234567890ABCDEF, hash algorithm is 1, and iteration is 10, to get the NSEC3-hashed name for <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code> we would execute a command like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ nsec3hash 1234567890ABCEDF 1 10 www.example.com RN7I9ME6E1I6BDKIP91B9TCE4FHJ7LKF (salt=1234567890ABCEDF, hash=1, iterations=10) </pre></div> </div> <p>Zero-length salt can be specified as <code class="docutils literal notranslate"><span class="pre">-</span></code>.</p> <p>While it is unlikely you would construct a rainbow table of your own zone data, this tool may be useful when troubleshooting NSEC3 problems.</p> </section> </section> <section id="advanced-discussions"> <span id="dnssec-advanced-discussions"></span><h2>Advanced Discussions<a class="headerlink" href="#advanced-discussions" title="Permalink to this headline"></a></h2> <section id="signature-validity-periods-and-zone-re-signing-intervals"> <span id="signature-validity-periods"></span><h3>Signature Validity Periods and Zone Re-Signing Intervals<a class="headerlink" href="#signature-validity-periods-and-zone-re-signing-intervals" title="Permalink to this headline"></a></h3> <p>In <a class="reference internal" href="#how-are-answers-verified"><span class="std std-ref">How Are Answers Verified?</span></a>, we saw that record signatures have a validity period outside of which they are not valid. This means that at some point, a signature will no longer be valid and a query for the associated record will fail DNSSEC validation. But how long should a signature be valid for?</p> <p>The maximum value for the validity period should be determined by the impact of a replay attack: if this is low, the period can be long; if high, the period should be shorter. There is no “right” value, but periods of between a few days to a month are common.</p> <p>Deciding a minimum value is probably an easier task. Should something fail (e.g., a hidden primary distributing to secondary servers that actually answer queries), how long will it take before the failure is noticed, and how long before it is fixed? If you are a large 24x7 operation with operators always on-site, the answer might be less than an hour. In smaller companies, if the failure occurs just after everyone has gone home for a long weekend, the answer might be several days.</p> <p>Again, there are no “right” values - they depend on your circumstances. The signature validity period you decide to use should be a value between the two bounds. At the time of this writing (mid-2020), the default policy used by BIND sets a value of 14 days.</p> <p>To keep the zone valid, the signatures must be periodically refreshed since they expire - i.e., the zone must be periodically re-signed. The frequency of the re-signing depends on your network’s individual needs. For example, signing puts a load on your server, so if the server is very highly loaded, a lower re-signing frequency is better. Another consideration is the signature lifetime: obviously the intervals between signings must not be longer than the signature validity period. But if you have set a signature lifetime close to the minimum (see above), the signing interval must be much shorter. What would happen if the system failed just before the zone was re-signed?</p> <p>Again, there is no single “right” answer; it depends on your circumstances. The BIND 9 default policy sets the signature refresh interval to 5 days.</p> </section> <section id="proof-of-non-existence-nsec-and-nsec3"> <span id="advanced-discussions-proof-of-nonexistence"></span><h3>Proof of Non-Existence (NSEC and NSEC3)<a class="headerlink" href="#proof-of-non-existence-nsec-and-nsec3" title="Permalink to this headline"></a></h3> <p>How do you prove that something does not exist? This zen-like question is an interesting one, and in this section we provide an overview of how DNSSEC solves the problem.</p> <p>Why is it even important to have authenticated denial of existence in DNS? Couldn’t we just send back “hey, what you asked for does not exist,” and somehow generate a digital signature to go with it, proving it really is from the correct authoritative source? Aside from the technical challenge of signing something that doesn’t exist, this solution has flaws, one of which is it gives an attacker a way to create the appearance of denial of service by replaying this message on the network.</p> <p>Let’s use a little story, told three different ways, to illustrate how proof of nonexistence works. In our story, we run a small company with three employees: Alice, Edward, and Susan. For reasons that are far too complicated to go into, they don’t have email accounts; instead, email for them is sent to a single account and a nameless intern passes the message to them. The intern has access to our private DNSSEC key to create signatures for their responses.</p> <p>If we followed the approach of giving back the same answer no matter what was asked, when people emailed and asked for the message to be passed to “Bob,” our intern would simply answer “Sorry, that person doesn’t work here” and sign this message. This answer could be validated because our intern signed the response with our private DNSSEC key. However, since the signature doesn’t change, an attacker could record this message. If the attacker were able to intercept our email, when the next person emailed asking for the message to be passed to Susan, the attacker could return the exact same message: “Sorry, that person doesn’t work here,” with the same signature. Now the attacker has successfully fooled the sender into thinking that Susan doesn’t work at our company, and might even be able to convince all senders that no one works at this company.</p> <p>To solve this problem, two different solutions were created. We will look at the first one, NSEC, next.</p> <section id="nsec"> <span id="advanced-discussions-nsec"></span><span id="id37"></span><h4>NSEC<a class="headerlink" href="#nsec" title="Permalink to this headline"></a></h4> <p>The NSEC record is used to prove that something does not exist, by providing the name before it and the name after it. Using our tiny company example, this would be analogous to someone sending an email for Bob and our nameless intern responding with with: “I’m sorry, that person doesn’t work here. The name before the location where ‘Bob’ would be is Alice, and the name after that is Edward.” Let’s say another email was received for a non-existent person, this time Oliver; our intern would respond “I’m sorry, that person doesn’t work here. The name before the location where ‘Oliver’ would be is Edward, and the name after that is Susan.” If another sender asked for Todd, the answer would be: “I’m sorry, that person doesn’t work here. The name before the location where ‘Todd’ would be is Susan, and there are no other names after that.”</p> <p>So we end up with four NSEC records:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">alice</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">alice</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">edward</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">edward</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">susan</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> <span class="n">susan</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NSEC</span> </pre></div> </div> <p>What if the attacker tried to use the same replay method described earlier? If someone sent an email for Edward, none of the four answers would fit. If attacker replied with message #2, “I’m sorry, that person doesn’t work here. The name before it is Alice, and the name after it is Edward,” it is obviously false, since “Edward” is in the response; and the same goes for #3, Edward and Susan. As for #1 and #4, Edward does not fall in the alphabetical range before Alice or after Susan, so the sender can logically deduce that it was an incorrect answer.</p> <p>When BIND signs your zone, the zone data is automatically sorted on the fly before generating NSEC records, much like how a phone directory is sorted.</p> <p>The NSEC record allows for a proof of non-existence for record types. If you ask a signed zone for a name that exists but for a record type that doesn’t (for that name), the signed NSEC record returned lists all of the record types that <em>do</em> exist for the requested domain name.</p> <p>NSEC records can also be used to show whether a record was generated as the result of a wildcard expansion. The details of this are not within the scope of this document, but are described well in <span class="target" id="index-5"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7129.html"><strong>RFC 7129</strong></a>.</p> <p>Unfortunately, the NSEC solution has a few drawbacks, one of which is trivial “zone walking.” In our story, a curious person can keep sending emails, and our nameless, gullible intern keeps divulging information about our employees. Imagine if the sender first asked: “Is Bob there?” and received back the names Alice and Edward. Our sender could then email again: “Is Edwarda there?”, and will get back Edward and Susan. (No, “Edwarda” is not a real name. However, it is the first name alphabetically after “Edward” and that is enough to get the intern to reply with a message telling us the next valid name after Edward.) Repeat the process enough times and the person sending the emails eventually learns every name in our company phone directory. For many of you, this may not be a problem, since the very idea of DNS is similar to a public phone book: if you don’t want a name to be known publicly, don’t put it in DNS! Consider using DNS views (split DNS) and only display your sensitive names to a select audience.</p> <p>The second potential drawback of NSEC is a bigger zone file and memory consumption; there is no opt-out mechanism for insecure child zones, so each name in the zone will get an additional NSEC record and a RRSIG record to go with it. In practice this is a problem only for parent-zone operators dealing with mostly insecure child zones, such as <code class="docutils literal notranslate"><span class="pre">com.</span></code>. To learn more about opt-out, please see <a class="reference internal" href="#advanced-discussions-nsec3-optout"><span class="std std-ref">NSEC3 Opt-Out</span></a>.</p> </section> <section id="nsec3"> <span id="advanced-discussions-nsec3"></span><span id="id38"></span><h4>NSEC3<a class="headerlink" href="#nsec3" title="Permalink to this headline"></a></h4> <p>NSEC3 adds two additional features that NSEC does not have:</p> <ol class="arabic simple"> <li><p>It offers no easy zone enumeration.</p></li> <li><p>It provides a mechanism for the parent zone to exclude insecure delegations (i.e., delegations to zones that are not signed) from the proof of non-existence.</p></li> </ol> <p>Recall that in <a class="reference internal" href="#advanced-discussions-nsec"><span class="std std-ref">NSEC</span></a> we provided a range of names to prove that something does not exist. But as it turns out, even disclosing these ranges of names becomes a problem: this made it very easy for the curious-minded to look at our entire zone. Not only that, unlike a zone transfer, this “zone walking” is more resource-intensive. So how do we disclose something without actually disclosing it?</p> <p>The answer is actually quite simple: hashing functions, or one-way hashes. Without going into many details, think of it like a magical meat grinder. A juicy piece of ribeye steak goes in one end, and out comes a predictable shape and size of ground meat (hash) with a somewhat unique pattern. No matter how hard you try, you cannot turn the ground meat back into the ribeye steak: that’s what we call a one-way hash.</p> <p>NSEC3 basically runs the names through a one-way hash before giving them out, so the recipients can verify the non-existence without any knowledge of the other names in the zone.</p> <p>So let’s tell our little story for the third time, this time with NSEC3. In this version, our intern is not given a list of actual names; he is given a list of “hashed” names. So instead of Alice, Edward, and Susan, the list he is given reads like this (hashes shortened for easier reading):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">FSK5</span><span class="o">....</span> <span class="p">(</span><span class="n">produced</span> <span class="kn">from</span> <span class="nn">Edward</span><span class="p">)</span> <span class="n">JKMA</span><span class="o">....</span> <span class="p">(</span><span class="n">produced</span> <span class="kn">from</span> <span class="nn">Susan</span><span class="p">)</span> <span class="n">NTQ0</span><span class="o">....</span> <span class="p">(</span><span class="n">produced</span> <span class="kn">from</span> <span class="nn">Alice</span><span class="p">)</span> </pre></div> </div> <p>Then, an email is received for Bob again. Our intern takes the name Bob through a hash function, and the result is L8J2…, so he replies: “I’m sorry, that person doesn’t work here. The name before that is JKMA…, and the name after that is NTQ0…”. There, we proved Bob doesn’t exist, without giving away any names! To put that into proper NSEC3 resource records, they would look like this (again, hashes shortened for ease of display):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">FSK5</span><span class="o">....</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC3</span> <span class="mi">1</span> <span class="mi">0</span> <span class="mi">0</span> <span class="o">-</span> <span class="n">JKMA</span><span class="o">...</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">JKMA</span><span class="o">....</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC3</span> <span class="mi">1</span> <span class="mi">0</span> <span class="mi">0</span> <span class="o">-</span> <span class="n">NTQ0</span><span class="o">...</span> <span class="n">A</span> <span class="n">RRSIG</span> <span class="n">NTQ0</span><span class="o">....</span><span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="mi">300</span> <span class="n">IN</span> <span class="n">NSEC3</span> <span class="mi">1</span> <span class="mi">0</span> <span class="mi">0</span> <span class="o">-</span> <span class="n">FSK5</span><span class="o">...</span> <span class="n">A</span> <span class="n">RRSIG</span> </pre></div> </div> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Just because we employed one-way hash functions does not mean there is no way for a determined individual to figure out our zone data.</p> </div> <p>Most names published in the DNS are rarely secret or unpredictable. They are published to be memorable, used and consumed by humans. They are often recorded in many other network logs such as email logs, certificate transparency logs, web page links, intrusion detection systems, malware scanners, email archives, etc. Many times a simple dictionary of commonly used domain-name prefixes (www, mail, imap, login, database, etc.) can be used to quickly reveal a large number of labels within a zone. Additionally, if an adversary really wants to expend significant CPU resources to mount an offline dictionary attack on a zone’s NSEC3 chain, they will likely be able to find most of the “guessable” names despite any level of hashing.</p> <p>Also, it is still possible to gather all of our NSEC3 records and hashed names and perform an offline brute-force attack by trying all possible combinations to figure out what the original name is. In our meat-grinder analogy, this would be like someone buying all available cuts of meat and grinding them up at home using the same model of meat grinder, and comparing the output with the meat you gave him. It is expensive and time-consuming (especially with real meat), but like everything else in cryptography, if someone has enough resources and time, nothing is truly private forever. If you are concerned about someone performing this type of attack on your zone data, use some of the special techniques described in <span class="target" id="index-6"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc4470.html"><strong>RFC 4470</strong></a>.</p> <section id="nsec3param"> <span id="advanced-discussions-nsec3param"></span><h5>NSEC3PARAM<a class="headerlink" href="#nsec3param" title="Permalink to this headline"></a></h5> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>Before we dive into the details of NSEC3 parametrization, please note: the defaults should not be changed without a strong justification and a full understanding of the potential impact. See <span class="target" id="index-7"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc9276.html"><strong>RFC 9276</strong></a>.</p> </div> <p>The above NSEC3 examples used four parameters: 1, 0, 0, and zero-length salt. 1 represents the algorithm, 0 represents the opt-out flag, 0 represents the number of additional iterations, and - is the salt. Let’s look at how each one can be configured:</p> <dl class="glossary"> <dt id="term-Algorithm">Algorithm<a class="headerlink" href="#term-Algorithm" title="Permalink to this term"></a></dt><dt id="term-NSEC3-Hashing-Algorithm">NSEC3 Hashing Algorithm<a class="headerlink" href="#term-NSEC3-Hashing-Algorithm" title="Permalink to this term"></a></dt><dd><p>The only currently defined value is 1 for SHA-1, so there is no configuration field for it.</p> </dd> <dt id="term-Opt-out">Opt-out<a class="headerlink" href="#term-Opt-out" title="Permalink to this term"></a></dt><dd><p>Setting this bit to 1 enables NSEC3 opt-out, which is discussed in <a class="reference internal" href="#advanced-discussions-nsec3-optout"><span class="std std-ref">NSEC3 Opt-Out</span></a>.</p> </dd> <dt id="term-Iterations">Iterations<a class="headerlink" href="#term-Iterations" title="Permalink to this term"></a></dt><dd><p>Iterations defines the number of _additional_ times to apply the algorithm when generating an NSEC3 hash. More iterations consume more resources for both authoritative servers and validating resolvers. The considerations here are similar to those seen in <a class="reference internal" href="#key-sizes"><span class="std std-ref">Key Sizes</span></a>, of security versus resources.</p> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>Do not use values higher than zero. A value of zero provides one round of SHA-1 hashing and protects from non-determined attackers.</p> <p>A greater number of additional iterations causes interoperability problems and opens servers to CPU-exhausting DoS attacks, while providing only doubtful security benefits.</p> </div> </dd> <dt id="term-Salt">Salt<a class="headerlink" href="#term-Salt" title="Permalink to this term"></a></dt><dd><p>A salt value, which can be combined with an FQDN to influence the resulting hash. Salt is discussed in more detail in <a class="reference internal" href="#advanced-discussions-nsec3-salt"><span class="std std-ref">NSEC3 Salt</span></a>.</p> </dd> </dl> </section> <section id="nsec3-opt-out"> <span id="advanced-discussions-nsec3-optout"></span><h5>NSEC3 Opt-Out<a class="headerlink" href="#nsec3-opt-out" title="Permalink to this headline"></a></h5> <p>First things first: For most DNS administrators who do not manage a huge number of insecure delegations, the NSEC3 opt-out featuere is not relevant. See <span class="target" id="index-8"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc9276.html"><strong>RFC 9276</strong></a>.</p> <p>Opt-out allows for blocks of unsigned delegations to be covered by a single NSEC3 record. In other words, use of the opt-out allows large registries to only sign as many NSEC3 records as there are signed DS or other RRsets in the zone; with opt-out, unsigned delegations do not require additional NSEC3 records. This sacrifices the tamper-resistance proof of non-existence offered by NSEC3 in order to reduce memory and CPU overheads, and decreases the effectiveness of the cache (<span class="target" id="index-9"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc8198.html"><strong>RFC 8198</strong></a>).</p> <p>Why would that ever be desirable? If a significant number of delegations are not yet securely delegated, meaning they lack DS records and are still insecure or unsigned, generating DNSSEC records for all their NS records might consume lots of memory and is not strictly required by the child zones.</p> <p>This resource-saving typically makes a difference only for <em>huge</em> zones like <code class="docutils literal notranslate"><span class="pre">com.</span></code>. Imagine that you are the operator of busy top-level domains such as <code class="docutils literal notranslate"><span class="pre">com.</span></code>, with millions of insecure delegated domain names. As of mid-2022, around 3% of all <code class="docutils literal notranslate"><span class="pre">com.</span></code> zones are signed. Basically, without opt-out, with 1,000,000 delegations, only 30,000 of which are secure, you still have to generate NSEC RRsets for the other 970,000 delegations; with NSEC3 opt-out, you will have saved yourself 970,000 sets of records.</p> <p>In contrast, for a small zone the difference is operationally negligible and the drawbacks outweigh the benefits.</p> <p>If NSEC3 opt-out is truly essential for a zone, the following configuration can be added to <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a>; for example, to create an NSEC3 chain using the SHA-1 hash algorithm, with the opt-out flag, no additional iterations, and no extra salt, use:</p> <div class="highlight-none notranslate"><div class="highlight"><pre><span></span>dnssec-policy "nsec3" { ... nsec3param iterations 0 optout yes salt-length 0; }; </pre></div> </div> <p>To learn more about how to configure NSEC3 opt-out, please see <a class="reference internal" href="#recipes-nsec3-optout"><span class="std std-ref">NSEC3 Opt-Out</span></a>.</p> </section> <section id="nsec3-salt"> <span id="advanced-discussions-nsec3-salt"></span><h5>NSEC3 Salt<a class="headerlink" href="#nsec3-salt" title="Permalink to this headline"></a></h5> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>Contrary to popular belief, adding salt provides little value. Each DNS zone is always uniquely salted using the zone name. <strong>Operators should use a zero-length salt value.</strong></p> </div> <p>The properties of this extra salt are complicated and beyond scope of this document. For detailed description why the salt in the context of DNSSEC provides little value please see <span class="target" id="index-10"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc9276.html"><strong>RFC 9276</strong></a>.</p> </section> </section> <section id="nsec-or-nsec3"> <span id="advanced-discussions-nsec-or-nsec3"></span><h4>NSEC or NSEC3?<a class="headerlink" href="#nsec-or-nsec3" title="Permalink to this headline"></a></h4> <p>So which is better: NSEC or NSEC3? There is no single right answer here that fits everyone; it comes down to a given network’s needs or requirements.</p> <p>In most cases, NSEC is a good choice for zone administrators. It relieves the authoritative servers and resolver of the additional cryptographic operations that NSEC3 requires, and NSEC is comparatively easier to troubleshoot than NSEC3.</p> <p>NSEC3 comes with many drawbacks and should be implemented only if zone enumeration prevention is really needed, or when opt-out provides a significant reduction in memory and CPU overheads (in other words, with a huge zone with mostly insecure delegations).</p> </section> </section> <section id="dnssec-keys"> <span id="advanced-discussions-key-generation"></span><h3>DNSSEC Keys<a class="headerlink" href="#dnssec-keys" title="Permalink to this headline"></a></h3> <section id="types-of-keys"> <h4>Types of Keys<a class="headerlink" href="#types-of-keys" title="Permalink to this headline"></a></h4> <p>Although DNSSEC documentation talks about three types of keys, they are all the same thing - but they have different roles. The roles are:</p> <dl class="simple"> <dt>Zone-Signing Key (ZSK)</dt><dd><p>This is the key used to sign the zone. It signs all records in the zone apart from the DNSSEC key-related RRsets: DNSKEY, CDS, and CDNSKEY.</p> </dd> <dt>Key-Signing Key (KSK)</dt><dd><p>This is the key used to sign the DNSSEC key-related RRsets and is the key used to link the parent and child zones. The parent zone stores a digest of the KSK. When a resolver verifies the chain of trust it checks to see that the DS record in the parent (which holds the digest of a key) matches a key in the DNSKEY RRset, and that it is able to use that key to verify the DNSKEY RRset. If it can do that, the resolver knows that it can trust the DNSKEY resource records, and so can use one of them to validate the other records in the zone.</p> </dd> <dt>Combined Signing Key (CSK)</dt><dd><p>A CSK combines the functionality of a ZSK and a KSK. Instead of having one key for signing the zone and one for linking the parent and child zones, a CSK is a single key that serves both roles.</p> </dd> </dl> <p>It is important to realize the terms ZSK, KSK, and CSK describe how the keys are used - all these keys are represented by DNSKEY records. The following examples are the DNSKEY records from a zone signed with a KSK and ZSK:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.12 example.com DNSKEY ; <<>> DiG 9.16.0 <<>> @192.168.1.12 example.com dnskey +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54989 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 5258d7ed09db0d76010000005ea1cc8c672d8db27a464e37 (good) ;; QUESTION SECTION: ;example.com. IN DNSKEY ;; ANSWER SECTION: example.com. 60 IN DNSKEY 256 3 13 ( tAeXLtIQ3aVDqqS/1UVRt9AE6/nzfoAuaT1Vy4dYl2CK pLNcUJxME1Z//pnGXY+HqDU7Gr5HkJY8V0W3r5fzlw== ) ; ZSK; alg = ECDSAP256SHA256 ; key id = 63722 example.com. 60 IN DNSKEY 257 3 13 ( cxkNegsgubBPXSra5ug2P8rWy63B8jTnS4n0IYSsD9eW VhiyQDmdgevKUhfG3SE1wbLChjJc2FAbvSZ1qk03Nw== ) ; KSK; alg = ECDSAP256SHA256 ; key id = 42933 </pre></div> </div> <p>… and a zone signed with just a CSK:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com DNSKEY ; <<>> DiG 9.16.0 <<>> @192.168.1.13 example.com dnskey +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22628 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: bf19ee914b5df46e010000005ea1cd02b66c06885d274647 (good) ;; QUESTION SECTION: ;example.com. IN DNSKEY ;; ANSWER SECTION: example.com. 60 IN DNSKEY 257 3 13 ( p0XM6AJ68qid2vtOdyGaeH1jnrdk2GhZeVvGzXfP/PNa 71wGtzR6jdUrTbXo5Z1W5QeeJF4dls4lh4z7DByF5Q== ) ; KSK; alg = ECDSAP256SHA256 ; key id = 1231 </pre></div> </div> <p>The only visible difference between the records (apart from the key data itself) is the value of the flags fields; this is 256 for a ZSK and 257 for a KSK or CSK. Even then, the flags field is only a hint to the software using it as to the role of the key: zones can be signed by any key. The fact that a CSK and KSK both have the same flags emphasizes this. A KSK usually only signs the DNSSEC key-related RRsets in a zone, whereas a CSK is used to sign all records in the zone.</p> <p>The original idea of separating the function of the key into a KSK and ZSK was operational. With a single key, changing it for any reason is “expensive,” as it requires interaction with the parent zone (e.g., uploading the key to the parent may require manual interaction with the organization running that zone). By splitting it, interaction with the parent is required only if the KSK is changed; the ZSK can be changed as often as required without involving the parent.</p> <p>The split also allows the keys to be of different lengths. So the ZSK, which is used to sign the record in the zone, can be of a (relatively) short length, lowering the load on the server. The KSK, which is used only infrequently, can be of a much longer length. The relatively infrequent use also allows the private part of the key to be stored in a way that is more secure but that may require more overhead to access, e.g., on an HSM (see <a class="reference internal" href="#hardware-security-modules"><span class="std std-ref">Hardware Security Modules (HSMs)</span></a>).</p> <p>In the early days of DNSSEC, the idea of splitting the key went more or less unchallenged. However, with the advent of more powerful computers and the introduction of signaling methods between the parent and child zones (see <a class="reference internal" href="#cds-cdnskey"><span class="std std-ref">The CDS and CDNSKEY Resource Records</span></a>), the advantages of a ZSK/KSK split are less clear and, for many zones, a single key is all that is required.</p> <p>As with many questions related to the choice of DNSSEC policy, the decision on which is “best” is not clear and depends on your circumstances.</p> </section> <section id="which-algorithm"> <h4>Which Algorithm?<a class="headerlink" href="#which-algorithm" title="Permalink to this headline"></a></h4> <p>There are three algorithm choices for DNSSEC as of this writing (mid-2020):</p> <ul class="simple"> <li><p>RSA</p></li> <li><p>Elliptic Curve DSA (ECDSA)</p></li> <li><p>Edwards Curve Digital Security Algorithm (EdDSA)</p></li> </ul> <p>All are supported in BIND 9, but only RSA and ECDSA (specifically RSASHA256 and ECDSAP256SHA256) are mandatory to implement in DNSSEC. However, RSA is a little long in the tooth, and ECDSA/EdDSA are emerging as the next new cryptographic standards. In fact, the US federal government recommended discontinuing RSA use altogether by September 2015 and migrating to using ECDSA or similar algorithms.</p> <p>For now, use ECDSAP256SHA256 but keep abreast of developments in this area. For details about rolling over DNSKEYs to a new algorithm, see <a class="reference internal" href="#advanced-discussions-dnskey-algorithm-rollovers"><span class="std std-ref">Algorithm Rollovers</span></a>.</p> </section> <section id="key-sizes"> <span id="id39"></span><h4>Key Sizes<a class="headerlink" href="#key-sizes" title="Permalink to this headline"></a></h4> <p>If using RSA keys, the choice of key sizes is a classic issue of finding the balance between performance and security. The larger the key size, the longer it takes for an attacker to crack the key; but larger keys also mean more resources are needed both when generating signatures (authoritative servers) and verifying signatures (recursive servers).</p> <p>Of the two sets of keys, ZSK is used much more frequently. ZSK is used whenever zone data changes or when signatures expire, so performance certainly is of a bigger concern. As for KSK, it is used less frequently, so performance is less of a factor, but its impact is bigger because of its role in signing other keys.</p> <p>In earlier versions of this guide, the following key lengths were chosen for each set, with the recommendation that they be rotated more frequently for better security:</p> <ul class="simple"> <li><p><em>ZSK</em>: RSA 1024 bits, rollover every year</p></li> <li><p><em>KSK</em>: RSA 2048 bits, rollover every five years</p></li> </ul> <p>These should be considered minimum RSA key sizes. At the time of this writing (mid-2020), the root zone and many TLDs are already using 2048 bit ZSKs. If you choose to implement larger key sizes, keep in mind that larger key sizes result in larger DNS responses, which this may mean more load on network resources. Depending on your network configuration, end users may even experience resolution failures due to the increased response sizes, as discussed in <a class="reference internal" href="#whats-edns0-all-about"><span class="std std-ref">What’s EDNS All About (And Why Should I Care)?</span></a>.</p> <p>ECDSA key sizes can be much smaller for the same level of security, e.g., an ECDSA key length of 224 bits provides the same level of security as a 2048-bit RSA key. Currently BIND 9 sets a key size of 256 for all ECDSA keys.</p> </section> <section id="key-storage"> <span id="advanced-discussions-key-storage"></span><h4>Key Storage<a class="headerlink" href="#key-storage" title="Permalink to this headline"></a></h4> <section id="public-key-storage"> <h5>Public Key Storage<a class="headerlink" href="#public-key-storage" title="Permalink to this headline"></a></h5> <p>The beauty of a public key cryptography system is that the public key portion can and should be distributed to as many people as possible. As the administrator, you may want to keep the public keys on an easily accessible file system for operational ease, but there is no need to securely store them, since both ZSK and KSK public keys are published in the zone data as DNSKEY resource records.</p> <p>Additionally, a hash of the KSK public key is also uploaded to the parent zone (see <a class="reference internal" href="#working-with-parent-zone"><span class="std std-ref">Working With the Parent Zone</span></a> for more details), and is published by the parent zone as DS records.</p> </section> <section id="private-key-storage"> <h5>Private Key Storage<a class="headerlink" href="#private-key-storage" title="Permalink to this headline"></a></h5> <p>Ideally, private keys should be stored offline, in secure devices such as a smart card. Operationally, however, this creates certain challenges, since the private key is needed to create RRSIG resource records, and it is a hassle to bring the private key out of storage every time the zone file changes or signatures expire.</p> <p>A common approach to strike the balance between security and practicality is to have two sets of keys: a ZSK set and a KSK set. A ZSK private key is used to sign zone data, and can be kept online for ease of use, while a KSK private key is used to sign just the DNSKEY (the ZSK); it is used less frequently, and can be stored in a much more secure and restricted fashion.</p> <p>For example, a KSK private key stored on a USB flash drive that is kept in a fireproof safe, only brought online once a year to sign a new pair of ZSKs, combined with a ZSK private key stored on the network file system and available for routine use, may be a good balance between operational flexibility and security.</p> <p>For more information on changing keys, please see <a class="reference internal" href="#key-rollovers"><span class="std std-ref">Key Rollovers</span></a>.</p> </section> <section id="hardware-security-modules-hsms"> <span id="hardware-security-modules"></span><h5>Hardware Security Modules (HSMs)<a class="headerlink" href="#hardware-security-modules-hsms" title="Permalink to this headline"></a></h5> <p>A Hardware Security Module (HSM) may come in different shapes and sizes, but as the name indicates, it is a physical device or devices, usually with some or all of the following features:</p> <ul class="simple"> <li><p>Tamper-resistant key storage</p></li> <li><p>Strong random-number generation</p></li> <li><p>Hardware for faster cryptographic operations</p></li> </ul> <p>Most organizations do not incorporate HSMs into their security practices due to cost and the added operational complexity.</p> <p>BIND supports Public Key Cryptography Standard #11 (PKCS #11) for communication with HSMs and other cryptographic support devices. For more information on how to configure BIND to work with an HSM, please refer to the <a class="reference external" href="https://bind9.readthedocs.io/en/latest/index.html">BIND 9 Administrator Reference Manual</a>.</p> </section> </section> </section> <section id="rollovers"> <span id="advanced-discussions-key-management"></span><h3>Rollovers<a class="headerlink" href="#rollovers" title="Permalink to this headline"></a></h3> <section id="key-rollovers"> <span id="id40"></span><h4>Key Rollovers<a class="headerlink" href="#key-rollovers" title="Permalink to this headline"></a></h4> <p>A key rollover is where one key in a zone is replaced by a new one. There are arguments for and against regularly rolling keys. In essence these are:</p> <p>Pros:</p> <ol class="arabic simple"> <li><p>Regularly changing the key hinders attempts at determination of the private part of the key by cryptanalysis of signatures.</p></li> <li><p>It gives administrators practice at changing a key; should a key ever need to be changed in an emergency, they would not be doing it for the first time.</p></li> </ol> <p>Cons:</p> <ol class="arabic simple"> <li><p>A lot of effort is required to hack a key, and there are probably easier ways of obtaining it, e.g., by breaking into the systems on which it is stored.</p></li> <li><p>Rolling the key adds complexity to the system and introduces the possibility of error. We are more likely to have an interruption to our service than if we had not rolled it.</p></li> </ol> <p>Whether and when to roll the key is up to you. How serious would the damage be if a key were compromised without you knowing about it? How serious would a key roll failure be?</p> <p>Before going any further, it is worth noting that if you sign your zone with either of the fully automatic methods (described in ref:<cite>signing_alternative_ways</cite>), you don’t really need to concern yourself with the details of a key rollover: BIND 9 takes care of it all for you. If you are doing a manual key roll or are setting up the keys for a semi-automatic key rollover, you do need to familiarize yourself with the various steps involved and the timing details.</p> <p>Rolling a key is not as simple as replacing the DNSKEY statement in the zone. That is an essential part of it, but timing is everything. For example, suppose that we run the <code class="docutils literal notranslate"><span class="pre">example.com</span></code> zone and that a friend queries for the AAAA record of <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code>. As part of the resolution process (described in <a class="reference internal" href="#how-does-dnssec-change-dns-lookup"><span class="std std-ref">How Does DNSSEC Change DNS Lookup?</span></a>), their recursive server looks up the keys for the <code class="docutils literal notranslate"><span class="pre">example.com</span></code> zone and uses them to verify the signature associated with the AAAA record. We’ll assume that the records validated successfully, so they can use the address to visit <code class="docutils literal notranslate"><span class="pre">example.com</span></code>’s website.</p> <p>Let’s also assume that immediately after the lookup, we want to roll the ZSK for <code class="docutils literal notranslate"><span class="pre">example.com</span></code>. Our first attempt at this is to remove the old DNSKEY record and signatures, add a new DNSKEY record, and re-sign the zone with it. So one minute our server is serving the old DNSKEY and records signed with the old key, and the next minute it is serving the new key and records signed with it. We’ve achieved our goal - we are serving a zone signed with the new keys; to check this is really the case, we booted up our laptop and looked up the AAAA record <code class="docutils literal notranslate"><span class="pre">ftp.example.com</span></code>. The lookup succeeded so all must be well. Or is it? Just to be sure, we called our friend and asked them to check. They tried to lookup <code class="docutils literal notranslate"><span class="pre">ftp.example.com</span></code> but got a SERVFAIL response from their recursive server. What’s going on?</p> <p>The answer, in a word, is “caching.” When our friend looked up <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code>, their recursive server retrieved and cached not only the AAAA record, but also a lot of other records. It cached the NS records for <code class="docutils literal notranslate"><span class="pre">com</span></code> and <code class="docutils literal notranslate"><span class="pre">example.com</span></code>, as well as the AAAA (and A) records for those name servers (and this action may, in turn, have caused the lookup and caching of other NS and AAAA/A records). Most importantly for this example, it also looked up and cached the DNSKEY records for the root, <code class="docutils literal notranslate"><span class="pre">com</span></code>, and <code class="docutils literal notranslate"><span class="pre">example.com</span></code> zones. When a query was made for <code class="docutils literal notranslate"><span class="pre">ftp.example.com</span></code>, the recursive server believed it already had most of the information we needed. It knew what nameservers served <code class="docutils literal notranslate"><span class="pre">example.com</span></code> and their addresses, so it went directly to one of those to get the AAAA record for <code class="docutils literal notranslate"><span class="pre">ftp.example.com</span></code> and its associated signature. But when it tried to validate the signature, it used the cached copy of the DNSKEY, and that is when our friend had the problem. Their recursive server had a copy of the old DNSKEY in its cache, but the AAAA record for <code class="docutils literal notranslate"><span class="pre">ftp.example.com</span></code> was signed with the new key. So, not surprisingly, the signature could not validate.</p> <p>How should we roll the keys for <code class="docutils literal notranslate"><span class="pre">example.com</span></code>? A clue to the answer is to note that the problem came about because the DNSKEY records were cached by the recursive server. What would have happened had our friend flushed the DNSKEY records from the recursive server’s cache before making the query? That would have worked; those records would have been retrieved from <code class="docutils literal notranslate"><span class="pre">example.com</span></code>’s nameservers at the same time that we retrieved the AAAA record for <code class="docutils literal notranslate"><span class="pre">ftp.example.com</span></code>. Our friend’s server would have obtained the new key along with the AAAA record and associated signature created with the new key, and all would have been well.</p> <p>As it is obviously impossible for us to notify all recursive server operators to flush our DNSKEY records every time we roll a key, we must use another solution. That solution is to wait for the recursive servers to remove old records from caches when they reach their TTL. How exactly we do this depends on whether we are trying to roll a ZSK, a KSK, or a CSK.</p> <section id="zsk-rollover-methods"> <span id="id41"></span><h5>ZSK Rollover Methods<a class="headerlink" href="#zsk-rollover-methods" title="Permalink to this headline"></a></h5> <p>The ZSK can be rolled in one of the following two ways:</p> <ol class="arabic"> <li><p><em>Pre-Publication</em>: Publish the new ZSK into zone data before it is actually used. Wait at least one TTL interval, so the world’s recursive servers know about both keys, then stop using the old key and generate a new RRSIG using the new key. Wait at least another TTL, so the cached old key data is expunged from the world’s recursive servers, and then remove the old key.</p> <p>The benefit of the pre-publication approach is it does not dramatically increase the zone size; however, the duration of the rollover is longer. If insufficient time has passed after the new ZSK is published, some resolvers may only have the old ZSK cached when the new RRSIG records are published, and validation may fail. This is the method described in <a class="reference internal" href="#recipes-zsk-rollover"><span class="std std-ref">ZSK Rollover</span></a>.</p> </li> <li><p><em>Double-Signature</em>: Publish the new ZSK and new RRSIG, essentially doubling the size of the zone. Wait at least one TTL interval, and then remove the old ZSK and old RRSIG.</p> <p>The benefit of the double-signature approach is that it is easier to understand and execute, but it causes a significantly increased zone size during a rollover event.</p> </li> </ol> </section> <section id="ksk-rollover-methods"> <span id="id42"></span><h5>KSK Rollover Methods<a class="headerlink" href="#ksk-rollover-methods" title="Permalink to this headline"></a></h5> <p>Rolling the KSK requires interaction with the parent zone, so operationally this may be more complex than rolling ZSKs. There are three methods of rolling the KSK:</p> <ol class="arabic"> <li><p><em>Double-KSK</em>: Add the new KSK to the DNSKEY RRset, which is then signed with both the old and new keys. After waiting for the old RRset to expire from caches, change the DS record in the parent zone. After waiting a further TTL interval for this change to be reflected in caches, remove the old key from the RRset.</p> <p>Basically, the new KSK is added first at the child zone and used to sign the DNSKEY; then the DS record is changed, followed by the removal of the old KSK. Double-KSK keeps the interaction with the parent zone to a minimum, but for the duration of the rollover, the size of the DNSKEY RRset is increased.</p> </li> <li><p><em>Double-DS</em>: Publish the new DS record. After waiting for this change to propagate into caches, change the KSK. After a further TTL interval during which the old DNSKEY RRset expires from caches, remove the old DS record.</p> <p>Double-DS is the reverse of Double-KSK: the new DS is published at the parent first, then the KSK at the child is updated, then the old DS at the parent is removed. The benefit is that the size of the DNSKEY RRset is kept to a minimum, but interactions with the parent zone are increased to two events. This is the method described in <a class="reference internal" href="#recipes-ksk-rollover"><span class="std std-ref">KSK Rollover</span></a>.</p> </li> <li><p><em>Double-RRset</em>: Add the new KSK to the DNSKEY RRset, which is then signed with both the old and new key, and add the new DS record to the parent zone. After waiting a suitable interval for the old DS and DNSKEY RRsets to expire from caches, remove the old DNSKEY and old DS record.</p> <p>Double-RRset is the fastest way to roll the KSK (i.e., it has the shortest rollover time), but has the drawbacks of both of the other methods: a larger DNSKEY RRset and two interactions with the parent.</p> </li> </ol> </section> <section id="csk-rollover-methods"> <span id="id43"></span><h5>CSK Rollover Methods<a class="headerlink" href="#csk-rollover-methods" title="Permalink to this headline"></a></h5> <p>Rolling the CSK is more complex than rolling either the ZSK or KSK, as the timing constraints relating to both the parent zone and the caching of records by downstream recursive servers must be taken into account. There are numerous possible methods that are a combination of ZSK rollover and KSK rollover methods. BIND 9 automatic signing uses a combination of ZSK Pre-Publication and Double-KSK rollover.</p> </section> </section> <section id="emergency-key-rollovers"> <span id="advanced-discussions-emergency-rollovers"></span><h4>Emergency Key Rollovers<a class="headerlink" href="#emergency-key-rollovers" title="Permalink to this headline"></a></h4> <p>Keys are generally rolled on a regular schedule - if you choose to roll them at all. But sometimes, you may have to rollover keys out-of-schedule due to a security incident. The aim of an emergency rollover is to re-sign the zone with a new key as soon as possible, because when a key is suspected of being compromised, a malicious attacker (or anyone who has access to the key) could impersonate your server and trick other validating resolvers into believing that they are receiving authentic, validated answers.</p> <p>During an emergency rollover, follow the same operational procedures described in <a class="reference internal" href="#recipes-rollovers"><span class="std std-ref">Rollovers</span></a>, with the added task of reducing the TTL of the current active (potentially compromised) DNSKEY RRset, in an attempt to phase out the compromised key faster before the new key takes effect. The time frame should be significantly reduced from the 30-days-apart example, since you probably do not want to wait up to 60 days for the compromised key to be removed from your zone.</p> <p>Another method is to carry a spare key with you at all times. If you have a second key pre-published and that one is not compromised at the same time as the first key, you could save yourself some time by immediately activating the spare key if the active key is compromised. With pre-publication, all validating resolvers should already have this spare key cached, thus saving you some time.</p> <p>With a KSK emergency rollover, you also need to consider factors related to your parent zone, such as how quickly they can remove the old DS records and publish the new ones.</p> <p>As with many other facets of DNSSEC, there are multiple aspects to take into account when it comes to emergency key rollovers. For more in-depth considerations, please check out <span class="target" id="index-11"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7583.html"><strong>RFC 7583</strong></a>.</p> </section> <section id="algorithm-rollovers"> <span id="advanced-discussions-dnskey-algorithm-rollovers"></span><h4>Algorithm Rollovers<a class="headerlink" href="#algorithm-rollovers" title="Permalink to this headline"></a></h4> <p>From time to time, new digital signature algorithms with improved security are introduced, and it may be desirable for administrators to roll over DNSKEYs to a new algorithm, e.g., from RSASHA1 (algorithm 5 or 7) to RSASHA256 (algorithm 8). The algorithm rollover steps must be followed with care to avoid breaking DNSSEC validation.</p> <p>If you are managing DNSSEC by using the <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> configuration, <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> handles the rollover for you. Simply change the algorithm for the relevant keys, and <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> uses the new algorithm when the key is next rolled. It performs a smooth transition to the new algorithm, ensuring that the zone remains valid throughout rollover.</p> <p>If you are using other methods to sign the zone, the administrator needs to do more work. As with other key rollovers, when the zone is a primary zone, an algorithm rollover can be accomplished using dynamic updates or automatic key rollovers. For secondary zones, only automatic key rollovers are possible, but the <a class="reference internal" href="manpages.html#std-iscman-dnssec-settime"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-settime</span></code></a> utility can be used to control the timing.</p> <p>In any case, the first step is to put DNSKEYs in place using the new algorithm. You must generate the <code class="docutils literal notranslate"><span class="pre">K*</span></code> files for the new algorithm and put them in the zone’s key directory, where <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> can access them. Take care to set appropriate ownership and permissions on the keys. If the <a class="reference internal" href="reference.html#namedconf-statement-auto-dnssec" title="namedconf-statement-auto-dnssec"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">auto-dnssec</span></code></a> zone option is set to <code class="docutils literal notranslate"><span class="pre">maintain</span></code>, <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> automatically signs the zone with the new keys, based on their timing metadata when the <a class="reference internal" href="reference.html#namedconf-statement-dnssec-loadkeys-interval" title="namedconf-statement-dnssec-loadkeys-interval"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-loadkeys-interval</span></code></a> elapses or when you issue the <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-loadkeys"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">loadkeys</span></code></a> command. Otherwise, for primary zones, you can use <a class="reference internal" href="manpages.html#std-iscman-nsupdate"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nsupdate</span></code></a> to add the new DNSKEYs to the zone; this causes <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to use them to sign the zone. For secondary zones, e.g., on a “bump in the wire” signing server, <a class="reference internal" href="manpages.html#std-iscman-nsupdate"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nsupdate</span></code></a> cannot be used.</p> <p>Once the zone has been signed by the new DNSKEYs (and you have waited for at least one TTL period), you must inform the parent zone and any trust anchor repositories of the new KSKs, e.g., you might place DS records in the parent zone through your DNS registrar’s website.</p> <p>Before starting to remove the old algorithm from a zone, you must allow the maximum TTL on its DS records in the parent zone to expire. This assures that any subsequent queries retrieve the new DS records for the new algorithm. After the TTL has expired, you can remove the DS records for the old algorithm from the parent zone and any trust anchor repositories. You must then allow another maximum TTL interval to elapse so that the old DS records disappear from all resolver caches.</p> <p>The next step is to remove the DNSKEYs using the old algorithm from your zone. Again this can be accomplished using <a class="reference internal" href="manpages.html#std-iscman-nsupdate"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nsupdate</span></code></a> to delete the old DNSKEYs (for primary zones only) or by automatic key rollover when <a class="reference internal" href="reference.html#namedconf-statement-auto-dnssec" title="namedconf-statement-auto-dnssec"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">auto-dnssec</span></code></a> is set to <code class="docutils literal notranslate"><span class="pre">maintain</span></code>. You can cause the automatic key rollover to take place immediately by using the <a class="reference internal" href="manpages.html#std-iscman-dnssec-settime"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-settime</span></code></a> utility to set the <em>Delete</em> date on all keys to any time in the past. (See the <a class="reference internal" href="manpages.html#cmdoption-dnssec-settime-D"><code class="xref std std-option docutils literal notranslate"><span class="pre">dnssec-settime</span> <span class="pre">-D</span> <span class="pre">date/offset</span></code></a> option.)</p> <p>After adjusting the timing metadata, the <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-loadkeys"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">loadkeys</span></code></a> command causes <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to remove the DNSKEYs and RRSIGs for the old algorithm from the zone. Note also that with the <a class="reference internal" href="manpages.html#std-iscman-nsupdate"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nsupdate</span></code></a> method, removing the DNSKEYs also causes <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> to remove the associated RRSIGs automatically.</p> <p>Once you have verified that the old DNSKEYs and RRSIGs have been removed from the zone, the final (optional) step is to remove the key files for the old algorithm from the key directory.</p> </section> </section> <section id="other-topics"> <h3>Other Topics<a class="headerlink" href="#other-topics" title="Permalink to this headline"></a></h3> <section id="dnssec-and-dynamic-updates"> <h4>DNSSEC and Dynamic Updates<a class="headerlink" href="#dnssec-and-dynamic-updates" title="Permalink to this headline"></a></h4> <p>Dynamic DNS (DDNS) is actually independent of DNSSEC. DDNS provides a mechanism, separate from editing the zone file or zone database, to edit DNS data. Most DNS clients and servers are able to handle dynamic updates, and DDNS can also be integrated as part of your DHCP environment.</p> <p>When you have both DNSSEC and dynamic updates in your environment, updating zone data works the same way as with traditional (insecure) DNS: you can use <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-freeze"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">freeze</span></code></a> before editing the zone file, and <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-thaw"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">thaw</span></code></a> when you have finished editing, or you can use the command <a class="reference internal" href="manpages.html#std-iscman-nsupdate"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nsupdate</span></code></a> to add, edit, or remove records like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ nsupdate > server 192.168.1.13 > update add xyz.example.com. 300 IN A 1.1.1.1 > send > quit </pre></div> </div> <p>The examples provided in this guide make <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> automatically re-sign the zone whenever its content has changed. If you decide to sign your own zone file manually, you need to remember to execute the <a class="reference internal" href="manpages.html#std-iscman-dnssec-signzone"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-signzone</span></code></a> command whenever your zone file has been updated.</p> <p>As far as system resources and performance are concerned, be mindful that with a DNSSEC zone that changes frequently, every time the zone changes your system is executing a series of cryptographic operations to (re)generate signatures and NSEC or NSEC3 records.</p> </section> <section id="dnssec-on-private-networks"> <span id="id44"></span><h4>DNSSEC on Private Networks<a class="headerlink" href="#dnssec-on-private-networks" title="Permalink to this headline"></a></h4> <p>Let’s clarify what we mean: in this section, “private networks” really refers to a private or internal DNS view. Most DNS products offer the ability to have different versions of DNS answers, depending on the origin of the query. This feature is often called “DNS views” or “split DNS,” and is most commonly implemented as an “internal” versus an “external” setup.</p> <p>For instance, your organization may have a version of <code class="docutils literal notranslate"><span class="pre">example.com</span></code> that is offered to the world, and its names most likely resolve to publicly reachable IP addresses. You may also have an internal version of <code class="docutils literal notranslate"><span class="pre">example.com</span></code> that is only accessible when you are on the company’s private networks or via a VPN connection. These private networks typically fall under 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16 for IPv4.</p> <p>So what if you want to offer DNSSEC for your internal version of <code class="docutils literal notranslate"><span class="pre">example.com</span></code>? This can be done: the golden rule is to use the same key for both the internal and external versions of the zones. This avoids problems that can occur when machines (e.g., laptops) move between accessing the internal and external zones, when it is possible that they may have cached records from the wrong zone.</p> </section> <section id="introduction-to-dane"> <span id="id45"></span><h4>Introduction to DANE<a class="headerlink" href="#introduction-to-dane" title="Permalink to this headline"></a></h4> <p>With your DNS infrastructure secured with DNSSEC, information can now be stored in DNS and its integrity and authenticity can be proved. One of the new features that takes advantage of this is the DNS-Based Authentication of Named Entities, or DANE. This improves security in a number of ways, including:</p> <ul class="simple"> <li><p>The ability to store self-signed X.509 certificates and bypass having to pay a third party (such as a Certificate Authority) to sign the certificates (<span class="target" id="index-12"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc6698.html"><strong>RFC 6698</strong></a>).</p></li> <li><p>Improved security for clients connecting to mail servers (<span class="target" id="index-13"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7672.html"><strong>RFC 7672</strong></a>).</p></li> <li><p>A secure way of getting public PGP keys (<span class="target" id="index-14"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc7929.html"><strong>RFC 7929</strong></a>).</p></li> </ul> </section> </section> <section id="disadvantages-of-dnssec"> <h3>Disadvantages of DNSSEC<a class="headerlink" href="#disadvantages-of-dnssec" title="Permalink to this headline"></a></h3> <p>DNSSEC, like many things in this world, is not without its problems. Below are a few challenges and disadvantages that DNSSEC faces.</p> <ol class="arabic simple"> <li><p><em>Increased, well, everything</em>: With DNSSEC, signed zones are larger, thus taking up more disk space; for DNSSEC-aware servers, the additional cryptographic computation usually results in increased system load; and the network packets are bigger, possibly putting more strains on the network infrastructure.</p></li> <li><p><em>Different security considerations</em>: DNSSEC addresses many security concerns, most notably cache poisoning. But at the same time, it may introduce a set of different security considerations, such as amplification attack and zone enumeration through NSEC. These concerns are still being identified and addressed by the Internet community.</p></li> <li><p><em>More complexity</em>: If you have read this far, you have probably already concluded this yourself. With additional resource records, keys, signatures, and rotations, DNSSEC adds many more moving pieces on top of the existing DNS machine. The job of the DNS administrator changes, as DNS becomes the new secure repository of everything from spam avoidance to encryption keys, and the amount of work involved to troubleshoot a DNS-related issue becomes more challenging.</p></li> <li><p><em>Increased fragility</em>: The increased complexity means more opportunities for things to go wrong. Before DNSSEC, DNS was essentially “add something to the zone and forget it.” With DNSSEC, each new component - re-signing, key rollover, interaction with parent zone, key management - adds more opportunity for error. It is entirely possible that a failure to validate a name may come down to errors on the part of one or more zone operators rather than the result of a deliberate attack on the DNS.</p></li> <li><p><em>New maintenance tasks</em>: Even if your new secure DNS infrastructure runs without any hiccups or security breaches, it still requires regular attention, from re-signing to key rollovers. While most of these can be automated, some of the tasks, such as KSK rollover, remain manual for the time being.</p></li> <li><p><em>Not enough people are using it today</em>: While it’s estimated (as of mid-2020) that roughly 30% of the global Internet DNS traffic is validating, <a class="footnote-reference brackets" href="#apnic-validating-stats" id="id46">8</a> that doesn’t mean that many of the DNS zones are actually signed. What this means is, even if your company’s zone is signed today, fewer than 30% of the Internet’s servers are taking advantage of this extra security. It gets worse: with less than 1.5% of the <code class="docutils literal notranslate"><span class="pre">com.</span></code> domains signed, even if your DNSSEC validation is enabled today, it’s not likely to buy you or your users a whole lot more protection until these popular domain names decide to sign their zones.</p></li> </ol> <p>The last point may have more impact than you realize. Consider this: HTTP and HTTPS make up the majority of traffic on the Internet. While you may have secured your DNS infrastructure through DNSSEC, if your web hosting is outsourced to a third party that does not yet support DNSSEC in its own domain, or if your web page loads contents and components from insecure domains, end users may experience validation problems when trying to access your web page. For example, although you may have signed the zone <code class="docutils literal notranslate"><span class="pre">company.com</span></code>, the web address <code class="docutils literal notranslate"><span class="pre">www.company.com</span></code> may actually be a CNAME to <code class="docutils literal notranslate"><span class="pre">foo.random-cloud-provider.com</span></code>. As long as <code class="docutils literal notranslate"><span class="pre">random-cloud-provider.com</span></code> remains an insecure DNS zone, users cannot fully validate everything when they visit your web page and could be redirected elsewhere by a cache poisoning attack.</p> <dl class="footnote brackets"> <dt class="label" id="apnic-validating-stats"><span class="brackets"><a class="fn-backref" href="#id46">8</a></span></dt> <dd><p>Based on APNIC statistics at <a class="reference external" href="https://stats.labs.apnic.net/dnssec/XA">https://stats.labs.apnic.net/dnssec/XA</a></p> </dd> </dl> </section> </section> <section id="recipes"> <span id="dnssec-recipes"></span><h2>Recipes<a class="headerlink" href="#recipes" title="Permalink to this headline"></a></h2> <p>This chapter provides step-by-step “recipes” for some common DNSSEC configurations.</p> <section id="recipes-inline-signing"> <span id="id47"></span><h3>DNSSEC Signing<a class="headerlink" href="#recipes-inline-signing" title="Permalink to this headline"></a></h3> <p>There are two recipes here: the first shows an example using DNSSEC signing on the primary server, which has been covered in this guide; the second shows how to setup a “bump in the wire” between a hidden primary and the secondary servers to seamlessly sign the zone “on the fly.”</p> <section id="primary-server-dnssec-signing"> <span id="recipes-inline-signing-primary"></span><h4>Primary Server DNSSEC Signing<a class="headerlink" href="#primary-server-dnssec-signing" title="Permalink to this headline"></a></h4> <p>In this recipe, our servers are illustrated as shown in <a class="reference internal" href="#dnssec-signing-1"><span class="std std-ref">DNSSEC Signing Recipe #1</span></a>: we have a primary server (192.168.1.1) and three secondary servers (192.168.1.2, 192.168.1.3, and 192.168.1.4) that receive zone transfers. To get the zone signed, we need to reconfigure the primary server. Once reconfigured, a signed version of the zone is generated on the fly; zone transfers take care of synchronizing the signed zone data to all secondary name servers, without configuration or software changes on them.</p> <figure class="align-default" id="id57"> <span id="dnssec-signing-1"></span><a class="reference internal image-reference" href="_images/dnssec-inline-signing-1.png"><img alt="DNSSEC Signing Recipe #1" src="_images/dnssec-inline-signing-1.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">DNSSEC Signing Recipe #1</span><a class="headerlink" href="#id57" title="Permalink to this image"></a></p> </figcaption> </figure> <p>Using the method described in <a class="reference internal" href="#easy-start-guide-for-authoritative-servers"><span class="std std-ref">Easy-Start Guide for Signing Authoritative Zones</span></a>, we just need to add a <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement to the relevant zone clause. This is what the <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a> zone statement looks like on the primary server, 192.168.1.1:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="s2">"example.com"</span> <span class="n">IN</span> <span class="p">{</span> <span class="nb">type</span> <span class="n">primary</span><span class="p">;</span> <span class="n">file</span> <span class="s2">"db/example.com.db"</span><span class="p">;</span> <span class="n">key</span><span class="o">-</span><span class="n">directory</span> <span class="s2">"keys/example.com"</span><span class="p">;</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="n">default</span><span class="p">;</span> <span class="n">inline</span><span class="o">-</span><span class="n">signing</span> <span class="n">yes</span><span class="p">;</span> <span class="n">allow</span><span class="o">-</span><span class="n">transfer</span> <span class="p">{</span> <span class="mf">192.168.1.2</span><span class="p">;</span> <span class="mf">192.168.1.3</span><span class="p">;</span> <span class="mf">192.168.1.4</span><span class="p">;</span> <span class="p">};</span> <span class="p">};</span> </pre></div> </div> <p>We have chosen to use the default policy, storing the keys generated for the zone in the directory <code class="docutils literal notranslate"><span class="pre">keys/example.com</span></code>. To use a custom policy, define the policy in the configuration file and select it in the zone statement (as described in <a class="reference internal" href="#signing-custom-policy"><span class="std std-ref">Creating a Custom DNSSEC Policy</span></a>).</p> <p>On the secondary servers, <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a> does not need to be updated, and it looks like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="s2">"example.com"</span> <span class="n">IN</span> <span class="p">{</span> <span class="nb">type</span> <span class="n">secondary</span><span class="p">;</span> <span class="n">file</span> <span class="s2">"db/example.com.db"</span><span class="p">;</span> <span class="n">primaries</span> <span class="p">{</span> <span class="mf">192.168.1.1</span><span class="p">;</span> <span class="p">};</span> <span class="p">};</span> </pre></div> </div> <p>In fact, the secondary servers do not even need to be running BIND; they can run any DNS product that supports DNSSEC.</p> </section> <section id="bump-in-the-wire-signing"> <span id="recipes-inline-signing-bump-in-the-wire"></span><h4>“Bump in the Wire” Signing<a class="headerlink" href="#bump-in-the-wire-signing" title="Permalink to this headline"></a></h4> <p>In this recipe, we take advantage of the power of automated signing by placing an additional name server (192.168.1.5) between the hidden primary (192.168.1.1) and the DNS secondaries (192.168.1.2, 192.168.1.3, and 192.168.1.4). The additional name server, 192.168.1.5, acts as a “bump in the wire,” taking an unsigned zone from the hidden primary, and sending out signed data on the other end to the secondary name servers. The steps described in this recipe may be used as part of a DNSSEC deployment strategy, since it requires only minimal changes made to the existing hidden DNS primary and DNS secondaries.</p> <figure class="align-default" id="id58"> <span id="dnssec-signing-2"></span><a class="reference internal image-reference" href="_images/dnssec-inline-signing-2.png"><img alt="DNSSEC Signing Recipe #2" src="_images/dnssec-inline-signing-2.png" style="width: 100.0%;" /></a> <figcaption> <p><span class="caption-text">DNSSEC Signing Recipe #2</span><a class="headerlink" href="#id58" title="Permalink to this image"></a></p> </figcaption> </figure> <p>It is important to remember that 192.168.1.1 in this case is a hidden primary not exposed to the world, and it must not be listed in the NS RRset. Otherwise the world will get conflicting answers: unsigned answers from the hidden primary and signed answers from the other name servers.</p> <p>The only configuration change needed on the hidden primary, 192.168.1.1, is to make sure it allows our middle box to perform a zone transfer:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="s2">"example.com"</span> <span class="n">IN</span> <span class="p">{</span> <span class="o">...</span> <span class="n">allow</span><span class="o">-</span><span class="n">transfer</span> <span class="p">{</span> <span class="mf">192.168.1.5</span><span class="p">;</span> <span class="p">};</span> <span class="o">...</span> <span class="p">};</span> </pre></div> </div> <p>On the middle box, 192.168.1.5, all the tasks described in <a class="reference internal" href="#easy-start-guide-for-authoritative-servers"><span class="std std-ref">Easy-Start Guide for Signing Authoritative Zones</span></a> still need to be performed, such as generating key pairs and uploading information to the parent zone. This server is configured as secondary to the hidden primary 192.168.1.1 to receive the unsigned data; then, using keys accessible to this middle box, to sign data on the fly; and finally, to send out the signed data via zone transfer to the other three DNS secondaries. Its <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a> zone statement looks like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span> <span class="p">{</span> <span class="nb">type</span> <span class="n">secondary</span><span class="p">;</span> <span class="n">primaries</span> <span class="p">{</span> <span class="mf">192.168.1.1</span><span class="p">;</span> <span class="p">};</span> <span class="n">file</span> <span class="s2">"db/example.com.db"</span><span class="p">;</span> <span class="n">key</span><span class="o">-</span><span class="n">directory</span> <span class="s2">"keys/example.com"</span><span class="p">;</span> <span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="n">default</span><span class="p">;</span> <span class="n">inline</span><span class="o">-</span><span class="n">signing</span> <span class="n">yes</span><span class="p">;</span> <span class="n">allow</span><span class="o">-</span><span class="n">transfer</span> <span class="p">{</span> <span class="mf">192.168.1.2</span><span class="p">;</span> <span class="mf">192.168.1.3</span><span class="p">;</span> <span class="mf">192.168.1.4</span><span class="p">;</span> <span class="p">};</span> <span class="p">};</span> </pre></div> </div> <p>(As before, the default policy has been selected here. See <a class="reference internal" href="#signing-custom-policy"><span class="std std-ref">Creating a Custom DNSSEC Policy</span></a> for instructions on how to define and use a custom policy.)</p> <p>Finally, on the three secondary servers, the configuration should be updated to receive a zone transfer from 192.168.1.5 (the middle box) instead of from 192.168.1.1 (the hidden primary). If using BIND, the <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a> file looks like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="s2">"example.com"</span> <span class="n">IN</span> <span class="p">{</span> <span class="nb">type</span> <span class="n">secondary</span><span class="p">;</span> <span class="n">file</span> <span class="s2">"db/example.com.db"</span><span class="p">;</span> <span class="n">primaries</span> <span class="p">{</span> <span class="mf">192.168.1.5</span><span class="p">;</span> <span class="p">};</span> <span class="c1"># this was 192.168.1.1 before!</span> <span class="p">};</span> </pre></div> </div> </section> </section> <section id="recipes-rollovers"> <span id="id48"></span><h3>Rollovers<a class="headerlink" href="#recipes-rollovers" title="Permalink to this headline"></a></h3> <p>If you are signing your zone using a <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement, this section is not really relevant to you. In the policy statement, you set how long you want your keys to be valid for, the time taken for information to propagate through your zone, the time it takes for your parent zone to register a new DS record, etc., and that’s more or less it. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> implements everything for you automatically, apart from uploading the new DS records to your parent zone - which is covered in <a class="reference internal" href="#signing-easy-start-upload-to-parent-zone"><span class="std std-ref">Uploading Information to the Parent Zone</span></a>. (Some screenshots from a session where a KSK is uploaded to the parent zone are presented here for convenience.) However, these recipes may be useful in describing what happens through the rollover process and what you should be monitoring.</p> <section id="zsk-rollover"> <span id="recipes-zsk-rollover"></span><h4>ZSK Rollover<a class="headerlink" href="#zsk-rollover" title="Permalink to this headline"></a></h4> <p>This recipe covers how to perform a ZSK rollover using what is known as the Pre-Publication method. For other ZSK rolling methods, please see <a class="reference internal" href="#zsk-rollover-methods"><span class="std std-ref">ZSK Rollover Methods</span></a> in <a class="reference internal" href="#dnssec-advanced-discussions"><span class="std std-ref">Advanced Discussions</span></a>.</p> <p>Below is a sample timeline for a ZSK rollover to occur on January 1, 2021:</p> <ol class="arabic simple"> <li><p>December 1, 2020 (one month before rollover)</p> <ul class="simple"> <li><p>Generate new ZSK</p></li> <li><p>Add DNSKEY for new ZSK to zone</p></li> </ul> </li> <li><p>January 1, 2021 (day of rollover)</p> <ul class="simple"> <li><p>New ZSK used to replace RRSIGs for the bulk of the zone</p></li> </ul> </li> <li><p>February 1, 2021 (one month after rollover)</p> <ul class="simple"> <li><p>Remove old ZSK DNSKEY RRset from zone</p></li> <li><p>DNSKEY signatures made with KSK are changed</p></li> </ul> </li> </ol> <p>The current active ZSK has the ID 17694 in the example below. For more information on key management and rollovers, please see <a class="reference internal" href="#advanced-discussions-key-management"><span class="std std-ref">Rollovers</span></a>.</p> <section id="one-month-before-zsk-rollover"> <h5>One Month Before ZSK Rollover<a class="headerlink" href="#one-month-before-zsk-rollover" title="Permalink to this headline"></a></h5> <p>On December 1, 2020, a month before the example rollover, you (as administrator) should change the parameters on the current key (17694). Set it to become inactive on January 1, 2021 and be deleted from the zone on February 1, 2021; also, generate a successor key (51623):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind/keys/example.com/</span> <span class="c1"># dnssec-settime -I 20210101 -D 20210201 Kexample.com.+008+17694</span> <span class="o">./</span><span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">008</span><span class="o">+</span><span class="mf">17694.</span><span class="n">key</span><span class="o">/</span><span class="n">GoDaddy</span> <span class="o">./</span><span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">008</span><span class="o">+</span><span class="mf">17694.</span><span class="n">private</span> <span class="c1"># dnssec-keygen -S Kexample.com.+008+17694</span> <span class="n">Generating</span> <span class="n">key</span> <span class="n">pair</span><span class="o">..++++++</span> <span class="o">...........++++++</span> <span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">008</span><span class="o">+</span><span class="mi">51623</span> </pre></div> </div> <p>The first command gets us into the key directory <code class="docutils literal notranslate"><span class="pre">/etc/bind/keys/example.com/</span></code>, where keys for <code class="docutils literal notranslate"><span class="pre">example.com</span></code> are stored.</p> <p>The second, <a class="reference internal" href="manpages.html#std-iscman-dnssec-settime"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-settime</span></code></a>, sets an inactive (<a class="reference internal" href="manpages.html#cmdoption-dnssec-settime-I"><code class="xref std std-option docutils literal notranslate"><span class="pre">-I</span></code></a>) date of January 1, 2021, and a deletion (<a class="reference internal" href="manpages.html#cmdoption-dnssec-settime-D"><code class="xref std std-option docutils literal notranslate"><span class="pre">-D</span></code></a>) date of February 1, 2021, for the current ZSK (<code class="docutils literal notranslate"><span class="pre">Kexample.com.+008+17694</span></code>).</p> <p>The third command, <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a>, creates a successor key, using the exact same parameters (algorithms, key sizes, etc.) as the current ZSK. The new ZSK created in our example is <code class="docutils literal notranslate"><span class="pre">Kexample.com.+008+51623</span></code>.</p> <p>Make sure the successor keys are readable by <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a>.</p> <p><a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a>’s logging messages indicate when the next key checking event is scheduled to occur, the frequency of which can be controlled by <a class="reference internal" href="reference.html#namedconf-statement-dnssec-loadkeys-interval" title="namedconf-statement-dnssec-loadkeys-interval"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-loadkeys-interval</span></code></a>. The log message looks like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="nb">next</span> <span class="n">key</span> <span class="n">event</span><span class="p">:</span> <span class="mi">01</span><span class="o">-</span><span class="n">Dec</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">00</span><span class="p">:</span><span class="mi">13</span><span class="p">:</span><span class="mf">05.385</span> </pre></div> </div> <p>And you can check the publish date of the key by looking at the key file:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind/keys/example.com</span> <span class="c1"># cat Kexample.com.+008+51623.key</span> <span class="p">;</span> <span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">zone</span><span class="o">-</span><span class="n">signing</span> <span class="n">key</span><span class="p">,</span> <span class="n">keyid</span> <span class="mi">11623</span><span class="p">,</span> <span class="k">for</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="p">;</span> <span class="n">Created</span><span class="p">:</span> <span class="mi">20201130160024</span> <span class="p">(</span><span class="n">Mon</span> <span class="n">Dec</span> <span class="mi">1</span> <span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">24</span> <span class="mi">2020</span><span class="p">)</span> <span class="p">;</span> <span class="n">Publish</span><span class="p">:</span> <span class="mi">20201202000000</span> <span class="p">(</span><span class="n">Fri</span> <span class="n">Dec</span> <span class="mi">2</span> <span class="mi">08</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span> <span class="mi">2020</span><span class="p">)</span> <span class="p">;</span> <span class="n">Activate</span><span class="p">:</span> <span class="mi">20210101000000</span> <span class="p">(</span><span class="n">Sun</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">08</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span> <span class="mi">2021</span><span class="p">)</span> <span class="o">...</span> </pre></div> </div> <p>Since the publish date is set to the morning of December 2, and our example scenario takes place on December 1, the next morning you will notice that your zone has gained a new DNSKEY record, but the new ZSK is not yet being used to generate signatures. Below is the abbreviated output - with shortened DNSKEY and RRSIG - when querying the authoritative name server, 192.168.1.13:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. DNSKEY +dnssec +multiline ... ;; ANSWER SECTION: example.com. 600 IN DNSKEY 257 3 8 ( AwEAAcWDps...lM3NRn/G/R ) ; KSK; alg = RSASHA256; key id = 6817 example.com. 600 IN DNSKEY 256 3 8 ( AwEAAbi6Vo...qBW5+iAqNz ) ; ZSK; alg = RSASHA256; key id = 51623 example.com. 600 IN DNSKEY 256 3 8 ( AwEAAcjGaU...0rzuu55If5 ) ; ZSK; alg = RSASHA256; key id = 17694 example.com. 600 IN RRSIG DNSKEY 8 2 600 ( 20210101000000 20201201230000 6817 example.com. LAiaJM26T7...FU9syh/TQ= ) example.com. 600 IN RRSIG DNSKEY 8 2 600 ( 20210101000000 20201201230000 17694 example.com. HK4EBbbOpj...n5V6nvAkI= ) ... </pre></div> </div> <p>For good measure, let’s take a look at the SOA record and its signature for this zone. Notice the RRSIG is signed by the current ZSK, 17694. This will come in handy later when you want to verify whether the new ZSK is in effect:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. SOA +dnssec +multiline ... ;; ANSWER SECTION: example.com. 600 IN SOA ns1.example.com. admin.example.com. ( 2020120102 ; serial 1800 ; refresh (30 minutes) 900 ; retry (15 minutes) 2419200 ; expire (4 weeks) 300 ; minimum (5 minutes) ) example.com. 600 IN RRSIG SOA 8 2 600 ( 20201230160109 20201130150109 17694 example.com. YUTC8rFULaWbW+nAHzbfGwNqzARHevpryzRIJMvZBYPo NAeejNk9saNAoCYKWxGJ0YBc2k+r5fYq1Mg4ll2JkBF5 buAsAYLw8vEOIxVpXwlArY+oSp9T1w2wfTZ0vhVIxaYX 6dkcz4I3wbDx2xmG0yngtA6A8lAchERx2EGy0RM= ) </pre></div> </div> <p>These are all the manual tasks you need to perform for a ZSK rollover. If you have followed the configuration examples in this guide of using <a class="reference internal" href="reference.html#namedconf-statement-inline-signing" title="namedconf-statement-inline-signing"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">inline-signing</span></code></a> and <a class="reference internal" href="reference.html#namedconf-statement-auto-dnssec" title="namedconf-statement-auto-dnssec"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">auto-dnssec</span></code></a>, everything else is automated for you by BIND.</p> </section> <section id="day-of-zsk-rollover"> <h5>Day of ZSK Rollover<a class="headerlink" href="#day-of-zsk-rollover" title="Permalink to this headline"></a></h5> <p>On the actual day of the rollover, although there is technically nothing for you to do, you should still keep an eye on the zone to make sure new signatures are being generated by the new ZSK (51623 in this example). The easiest way is to query the authoritative name server 192.168.1.13 for the SOA record as you did a month ago:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. SOA +dnssec +multiline ... ;; ANSWER SECTION: example.com. 600 IN SOA ns1.example.com. admin.example.com. ( 2020112011 ; serial 1800 ; refresh (30 minutes) 900 ; retry (15 minutes) 2419200 ; expire (4 weeks) 300 ; minimum (5 minutes) ) example.com. 600 IN RRSIG SOA 8 2 600 ( 20210131000000 20201231230000 51623 example.com. J4RMNpJPOmMidElyBugJp0RLqXoNqfvo/2AT6yAAvx9X zZRL1cuhkRcyCSLZ9Z+zZ2y4u2lvQGrNiondaKdQCor7 uTqH5WCPoqalOCBjqU7c7vlAM27O9RD11nzPNpVQ7xPs y5nkGqf83OXTK26IfnjU1jqiUKSzg6QR7+XpLk0= ) ... </pre></div> </div> <p>As you can see, the signature generated by the old ZSK (17694) has disappeared, replaced by a new signature generated from the new ZSK (51623).</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Not all signatures will disappear magically on the same day; it depends on when each one was generated. In the worst-case scenario, a new signature could have been signed by the old ZSK (17694) moments before it was deactivated, meaning that the signature could live for almost 30 more days, until just before February 1.</p> <p>This is why it is important to keep the old ZSK in the zone and not delete it right away.</p> </div> </section> <section id="one-month-after-zsk-rollover"> <h5>One Month After ZSK Rollover<a class="headerlink" href="#one-month-after-zsk-rollover" title="Permalink to this headline"></a></h5> <p>Again, technically there is nothing you need to do on this day, but it doesn’t hurt to verify that the old ZSK (17694) is now completely gone from your zone. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> will not touch <code class="docutils literal notranslate"><span class="pre">Kexample.com.+008+17694.private</span></code> and <code class="docutils literal notranslate"><span class="pre">Kexample.com.+008+17694.key</span></code> on your file system. Running the same <a class="reference internal" href="manpages.html#std-iscman-dig"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dig</span></code></a> command for DNSKEY should suffice:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. DNSKEY +multiline +dnssec ... ;; ANSWER SECTION: example.com. 600 IN DNSKEY 257 3 8 ( AwEAAcWDps...lM3NRn/G/R ) ; KSK; alg = RSASHA256; key id = 6817 example.com. 600 IN DNSKEY 256 3 8 ( AwEAAdeCGr...1DnEfX+Xzn ) ; ZSK; alg = RSASHA256; key id = 51623 example.com. 600 IN RRSIG DNSKEY 8 2 600 ( 20170203000000 20170102230000 6817 example.com. KHY8P0zE21...Y3szrmjAM= ) example.com. 600 IN RRSIG DNSKEY 8 2 600 ( 20170203000000 20170102230000 51623 example.com. G2g3crN17h...Oe4gw6gH8= ) ... </pre></div> </div> <p>Congratulations, the ZSK rollover is complete! As for the actual key files (the files ending in <code class="docutils literal notranslate"><span class="pre">.key</span></code> and <code class="docutils literal notranslate"><span class="pre">.private</span></code>), they may be deleted at this point, but they do not have to be.</p> </section> </section> <section id="ksk-rollover"> <span id="recipes-ksk-rollover"></span><h4>KSK Rollover<a class="headerlink" href="#ksk-rollover" title="Permalink to this headline"></a></h4> <p>This recipe describes how to perform KSK rollover using the Double-DS method. For other KSK rolling methods, please see <a class="reference internal" href="#ksk-rollover-methods"><span class="std std-ref">KSK Rollover Methods</span></a> in <a class="reference internal" href="#dnssec-advanced-discussions"><span class="std std-ref">Advanced Discussions</span></a>. The registrar used in this recipe is <a class="reference external" href="https://www.godaddy.com">GoDaddy</a>. Also for this recipe, we are keeping the number of DS records down to just one per active set using just SHA-1, for the sake of better clarity, although in practice most zone operators choose to upload two DS records as shown in <a class="reference internal" href="#working-with-parent-zone"><span class="std std-ref">Working With the Parent Zone</span></a>. For more information on key management and rollovers, please see <a class="reference internal" href="#advanced-discussions-key-management"><span class="std std-ref">Rollovers</span></a>.</p> <p>Below is a sample timeline for a KSK rollover to occur on January 1, 2021:</p> <ol class="arabic simple"> <li><p>December 1, 2020 (one month before rollover)</p> <ul class="simple"> <li><p>Change timer on the current KSK</p></li> <li><p>Generate new KSK and DS records</p></li> <li><p>Add DNSKEY for the new KSK to zone</p></li> <li><p>Upload new DS records to parent zone</p></li> </ul> </li> <li><p>January 1, 2021 (day of rollover)</p> <ul class="simple"> <li><p>Use the new KSK to sign all DNSKEY RRsets, which generates new RRSIGs</p></li> <li><p>Add new RRSIGs to the zone</p></li> <li><p>Remove RRSIG for the old ZSK from zone</p></li> <li><p>Start using the new KSK to sign DNSKEY</p></li> </ul> </li> <li><p>February 1, 2021 (one month after rollover)</p> <ul class="simple"> <li><p>Remove the old KSK DNSKEY from zone</p></li> <li><p>Remove old DS records from parent zone</p></li> </ul> </li> </ol> <p>The current active KSK has the ID 24828, and this is the DS record that has already been published by the parent zone:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># dnssec-dsfromkey -a SHA-1 Kexample.com.+007+24828.key</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">IN</span> <span class="n">DS</span> <span class="mi">24828</span> <span class="mi">7</span> <span class="mi">1</span> <span class="n">D4A33E8DD550A9567B4C4971A34AD6C4B80A6AD3</span> </pre></div> </div> <section id="one-month-before-ksk-rollover"> <span id="id49"></span><h5>One Month Before KSK Rollover<a class="headerlink" href="#one-month-before-ksk-rollover" title="Permalink to this headline"></a></h5> <p>On December 1, 2020, a month before the planned rollover, you (as administrator) should change the parameters on the current key. Set it to become inactive on January 1, 2021, and be deleted from the zone on February 1st, 2021; also generate a successor key (23550). Finally, generate a new DS record based on the new key, 23550:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind/keys/example.com/</span> <span class="c1"># dnssec-settime -I 20210101 -D 20210201 Kexample.com.+007+24828</span> <span class="o">./</span><span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">007</span><span class="o">+</span><span class="mf">24848.</span><span class="n">key</span> <span class="o">./</span><span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">007</span><span class="o">+</span><span class="mf">24848.</span><span class="n">private</span> <span class="c1"># dnssec-keygen -S Kexample.com.+007+24848</span> <span class="n">Generating</span> <span class="n">key</span> <span class="n">pair</span><span class="o">.......................................................................................++</span> <span class="o">...................................++</span> <span class="n">Kexample</span><span class="o">.</span><span class="n">com</span><span class="o">.+</span><span class="mi">007</span><span class="o">+</span><span class="mi">23550</span> <span class="c1"># dnssec-dsfromkey -a SHA-1 Kexample.com.+007+23550.key</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="n">IN</span> <span class="n">DS</span> <span class="mi">23550</span> <span class="mi">7</span> <span class="mi">1</span> <span class="mi">54</span><span class="n">FCF030AA1C79C0088FDEC1BD1C37DAA2E70DFB</span> </pre></div> </div> <p>The first command gets us into the key directory <code class="docutils literal notranslate"><span class="pre">/etc/bind/keys/example.com/</span></code>, where keys for <code class="docutils literal notranslate"><span class="pre">example.com</span></code> are stored.</p> <p>The second, <a class="reference internal" href="manpages.html#std-iscman-dnssec-settime"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-settime</span></code></a>, sets an inactive (<a class="reference internal" href="manpages.html#cmdoption-dnssec-settime-I"><code class="xref std std-option docutils literal notranslate"><span class="pre">-I</span></code></a>) date of January 1, 2021, and a deletion (<a class="reference internal" href="manpages.html#cmdoption-dnssec-settime-D"><code class="xref std std-option docutils literal notranslate"><span class="pre">-D</span></code></a>) date of February 1, 2021 for the current KSK (<code class="docutils literal notranslate"><span class="pre">Kexample.com.+007+24848</span></code>).</p> <p>The third command, <a class="reference internal" href="manpages.html#std-iscman-dnssec-keygen"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-keygen</span></code></a>, creates a successor key, using the exact same parameters (algorithms, key sizes, etc.) as the current KSK. The new key pair created in our example is <code class="docutils literal notranslate"><span class="pre">Kexample.com.+007+23550</span></code>.</p> <p>The fourth and final command, <a class="reference internal" href="manpages.html#std-iscman-dnssec-dsfromkey"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">dnssec-dsfromkey</span></code></a>, creates a DS record from the new KSK (23550), using SHA-1 as the digest type. Again, in practice most people generate two DS records for both supported digest types (SHA-1 and SHA-256), but for our example here we are only using one to keep the output small and hopefully clearer.</p> <p>Make sure the successor keys are readable by <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a>.</p> <p>The <a class="reference internal" href="reference.html#namedconf-statement-syslog" title="namedconf-statement-syslog"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">syslog</span></code></a> message indicates when the next key checking event is. The log message looks like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="nb">next</span> <span class="n">key</span> <span class="n">event</span><span class="p">:</span> <span class="mi">01</span><span class="o">-</span><span class="n">Dec</span><span class="o">-</span><span class="mi">2020</span> <span class="mi">00</span><span class="p">:</span><span class="mi">13</span><span class="p">:</span><span class="mf">05.385</span> </pre></div> </div> <p>You can check the publish date of the key by looking at the key file:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># cd /etc/bind/keys/example.com</span> <span class="c1"># cat Kexample.com.+007+23550.key</span> <span class="p">;</span> <span class="n">This</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">key</span><span class="o">-</span><span class="n">signing</span> <span class="n">key</span><span class="p">,</span> <span class="n">keyid</span> <span class="mi">23550</span><span class="p">,</span> <span class="k">for</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">.</span> <span class="p">;</span> <span class="n">Created</span><span class="p">:</span> <span class="mi">20201130160024</span> <span class="p">(</span><span class="n">Thu</span> <span class="n">Dec</span> <span class="mi">1</span> <span class="mi">00</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">24</span> <span class="mi">2020</span><span class="p">)</span> <span class="p">;</span> <span class="n">Publish</span><span class="p">:</span> <span class="mi">20201202000000</span> <span class="p">(</span><span class="n">Fri</span> <span class="n">Dec</span> <span class="mi">2</span> <span class="mi">08</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span> <span class="mi">2020</span><span class="p">)</span> <span class="p">;</span> <span class="n">Activate</span><span class="p">:</span> <span class="mi">20210101000000</span> <span class="p">(</span><span class="n">Sun</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">08</span><span class="p">:</span><span class="mi">00</span><span class="p">:</span><span class="mi">00</span> <span class="mi">2021</span><span class="p">)</span> <span class="o">...</span> </pre></div> </div> <p>Since the publish date is set to the morning of December 2, and our example scenario takes place on December 1, the next morning you will notice that your zone has gained a new DNSKEY record based on your new KSK, but with no corresponding RRSIG yet. Below is the abbreviated output - with shortened DNSKEY and RRSIG - when querying the authoritative name server, 192.168.1.13:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. DNSKEY +dnssec +multiline ... ;; ANSWER SECTION: example.com. 300 IN DNSKEY 256 3 7 ( AwEAAdYqAc...TiSlrma6Ef ) ; ZSK; alg = NSEC3RSASHA1; key id = 29747 example.com. 300 IN DNSKEY 257 3 7 ( AwEAAeTJ+w...O+Zy9j0m63 ) ; KSK; alg = NSEC3RSASHA1; key id = 24828 example.com. 300 IN DNSKEY 257 3 7 ( AwEAAc1BQN...Wdc0qoH21H ) ; KSK; alg = NSEC3RSASHA1; key id = 23550 example.com. 300 IN RRSIG DNSKEY 7 2 300 ( 20201206125617 20201107115617 24828 example.com. 4y1iPVJOrK...aC3iF9vgc= ) example.com. 300 IN RRSIG DNSKEY 7 2 300 ( 20201206125617 20201107115617 29747 example.com. g/gfmPjr+y...rt/S/xjPo= ) ... </pre></div> </div> <p>Anytime after generating the DS record, you can upload it; it is not necessary to wait for the DNSKEY to be published in your zone, since this new KSK is not active yet. You can do it immediately after the new DS record has been generated on December 1, or you can wait until the next day after you have verified that the new DNSKEY record is added to the zone. Below are some screenshots from GoDaddy’s web-based interface, used to add a new DS record. <a class="footnote-reference brackets" href="#godaddy-iface-note" id="id50">9</a></p> <ol class="arabic"> <li><p>After logging in, click the green “Launch” button next to the domain name you want to manage.</p> <figure class="align-default" id="id59"> <span id="add-ds-1"></span><a class="reference internal image-reference" href="_images/add-ds-1.png"><img alt="Upload DS Record Step #1" src="_images/add-ds-1.png" style="width: 70.0%;" /></a> <figcaption> <p><span class="caption-text">Upload DS Record Step #1</span><a class="headerlink" href="#id59" title="Permalink to this image"></a></p> </figcaption> </figure> </li> <li><p>Scroll down to the “DS Records” section and click “Manage.”</p> <figure class="align-default" id="id60"> <span id="add-ds-2"></span><a class="reference internal image-reference" href="_images/add-ds-2.png"><img alt="Upload DS Record Step #2" src="_images/add-ds-2.png" style="width: 40.0%;" /></a> <figcaption> <p><span class="caption-text">Upload DS Record Step #2</span><a class="headerlink" href="#id60" title="Permalink to this image"></a></p> </figcaption> </figure> </li> <li><p>A dialog appears, displaying the current key (24828). Click “Add DS Record.”</p> <figure class="align-default" id="id61"> <span id="add-ds-3"></span><a class="reference internal image-reference" href="_images/add-ds-3.png"><img alt="Upload DS Record Step #3" src="_images/add-ds-3.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Upload DS Record Step #3</span><a class="headerlink" href="#id61" title="Permalink to this image"></a></p> </figcaption> </figure> </li> <li><p>Enter the Key ID, algorithm, digest type, and the digest, then click “Next.”</p> <figure class="align-default" id="id62"> <span id="add-ds-4"></span><a class="reference internal image-reference" href="_images/add-ds-4.png"><img alt="Upload DS Record Step #4" src="_images/add-ds-4.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Upload DS Record Step #4</span><a class="headerlink" href="#id62" title="Permalink to this image"></a></p> </figcaption> </figure> </li> <li><p>Address any errors and click “Finish.”</p> <figure class="align-default" id="id63"> <span id="add-ds-5"></span><a class="reference internal image-reference" href="_images/add-ds-5.png"><img alt="Upload DS Record Step #5" src="_images/add-ds-5.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Upload DS Record Step #5</span><a class="headerlink" href="#id63" title="Permalink to this image"></a></p> </figcaption> </figure> </li> <li><p>Both DS records are shown. Click “Save.”</p> <figure class="align-default" id="id64"> <span id="add-ds-6"></span><a class="reference internal image-reference" href="_images/add-ds-6.png"><img alt="Upload DS Record Step #6" src="_images/add-ds-6.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Upload DS Record Step #6</span><a class="headerlink" href="#id64" title="Permalink to this image"></a></p> </figcaption> </figure> </li> </ol> <p>Finally, let’s verify that the registrar has published the new DS record. This may take anywhere from a few minutes to a few days, depending on your parent zone. You can verify whether your parent zone has published the new DS record by querying for the DS record of your zone. In the example below, the Google public DNS server 8.8.8.8 is used:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @8.8.8.8 example.com. DS ... ;; ANSWER SECTION: example.com. 21552 IN DS 24828 7 1 D4A33E8DD550A9567B4C4971A34AD6C4B80A6AD3 example.com. 21552 IN DS 23550 7 1 54FCF030AA1C79C0088FDEC1BD1C37DAA2E70DFB </pre></div> </div> <p>You can also query your parent zone’s authoritative name servers directly to see if these records have been published. DS records will not show up on your own authoritative zone, so you cannot query your own name servers for them. In this recipe, the parent zone is <code class="docutils literal notranslate"><span class="pre">.com</span></code>, so querying a few of the <code class="docutils literal notranslate"><span class="pre">.com</span></code> name servers is another appropriate verification.</p> </section> <section id="day-of-ksk-rollover"> <h5>Day of KSK Rollover<a class="headerlink" href="#day-of-ksk-rollover" title="Permalink to this headline"></a></h5> <p>If you have followed the examples in this document, as described in <a class="reference internal" href="#easy-start-guide-for-authoritative-servers"><span class="std std-ref">Easy-Start Guide for Signing Authoritative Zones</span></a>, there is technically nothing you need to do manually on the actual day of the rollover. However, you should still keep an eye on the zone to make sure new signature(s) are being generated by the new KSK (23550 in this example). The easiest way is to query the authoritative name server 192.168.1.13 for the same DNSKEY and signatures, as you did a month ago:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. DNSKEY +dnssec +multiline ... ;; ANSWER SECTION: example.com. 300 IN DNSKEY 256 3 7 ( AwEAAdYqAc...TiSlrma6Ef ) ; ZSK; alg = NSEC3RSASHA1; key id = 29747 example.com. 300 IN DNSKEY 257 3 7 ( AwEAAeTJ+w...O+Zy9j0m63 ) ; KSK; alg = NSEC3RSASHA1; key id = 24828 example.com. 300 IN DNSKEY 257 3 7 ( AwEAAc1BQN...Wdc0qoH21H ) ; KSK; alg = NSEC3RSASHA1; key id = 23550 example.com. 300 IN RRSIG DNSKEY 7 2 300 ( 20210201074900 20210101064900 23550 mydnssecgood.org. S6zTbBTfvU...Ib5eXkbtE= ) example.com. 300 IN RRSIG DNSKEY 7 2 300 ( 20210105074900 20201206064900 29747 mydnssecgood.org. VY5URQA2/d...OVKr1+KX8= ) ... </pre></div> </div> <p>As you can see, the signature generated by the old KSK (24828) has disappeared, replaced by a new signature generated from the new KSK (23550).</p> </section> <section id="one-month-after-ksk-rollover"> <h5>One Month After KSK Rollover<a class="headerlink" href="#one-month-after-ksk-rollover" title="Permalink to this headline"></a></h5> <p>While the removal of the old DNSKEY from the zone should be automated by <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a>, the removal of the DS record is manual. You should make sure the old DNSKEY record is gone from your zone first, by querying for the DNSKEY records of the zone; this time we expect not to see the key with an ID of 24828:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 example.com. DNSKEY +dnssec +multiline ... ;; ANSWER SECTION: example.com. 300 IN DNSKEY 256 3 7 ( AwEAAdYqAc...TiSlrma6Ef ) ; ZSK; alg = NSEC3RSASHA1; key id = 29747 example.com. 300 IN DNSKEY 257 3 7 ( AwEAAc1BQN...Wdc0qoH21H ) ; KSK; alg = NSEC3RSASHA1; key id = 23550 example.com. 300 IN RRSIG DNSKEY 7 2 300 ( 20210208000000 20210105230000 23550 mydnssecgood.org. Qw9Em3dDok...bNCS7KISw= ) example.com. 300 IN RRSIG DNSKEY 7 2 300 ( 20210208000000 20210105230000 29747 mydnssecgood.org. OuelpIlpY9...XfsKupQgc= ) ... </pre></div> </div> <p>Since the key with the ID 24828 is gone, you can now remove the old DS record for that key from our parent zone. Be careful to remove the correct DS record. If you accidentally remove the new DS record(s) with key ID 23550, it could lead to a problem called “security lameness,” as discussed in <a class="reference internal" href="#troubleshooting-security-lameness"><span class="std std-ref">Security Lameness</span></a>, and may cause users to be unable to resolve any names in the zone.</p> <ol class="arabic"> <li><p>After logging in (again, GoDaddy.com in our example) and launching the domain, scroll down to the “DS Records” section and click Manage.</p> <figure class="align-default" id="id65"> <span id="remove-ds-1"></span><a class="reference internal image-reference" href="_images/remove-ds-1.png"><img alt="Remove DS Record Step #1" src="_images/remove-ds-1.png" style="width: 40.0%;" /></a> <figcaption> <p><span class="caption-text">Remove DS Record Step #1</span><a class="headerlink" href="#id65" title="Permalink to this image"></a></p> </figcaption> </figure> </li> <li><p>A dialog appears, displaying both keys (24828 and 23550). Use the far right-hand X button to remove key 24828.</p> <figure class="align-default" id="id66"> <span id="remove-ds-2"></span><a class="reference internal image-reference" href="_images/remove-ds-2.png"><img alt="Remove DS Record Step #2" src="_images/remove-ds-2.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Remove DS Record Step #2</span><a class="headerlink" href="#id66" title="Permalink to this image"></a></p> </figcaption> </figure> </li> <li><p>Key 24828 now appears crossed out; click “Save” to complete the removal.</p> <figure class="align-default" id="id67"> <span id="remove-ds-3"></span><a class="reference internal image-reference" href="_images/remove-ds-3.png"><img alt="Remove DS Record Step #3" src="_images/remove-ds-3.png" style="width: 80.0%;" /></a> <figcaption> <p><span class="caption-text">Remove DS Record Step #3</span><a class="headerlink" href="#id67" title="Permalink to this image"></a></p> </figcaption> </figure> </li> </ol> <p>Congratulations, the KSK rollover is complete! As for the actual key files (ending in <code class="docutils literal notranslate"><span class="pre">.key</span></code> and <code class="docutils literal notranslate"><span class="pre">.private</span></code>), they may be deleted at this point, but they do not have to be.</p> <dl class="footnote brackets"> <dt class="label" id="godaddy-iface-note"><span class="brackets"><a class="fn-backref" href="#id50">9</a></span></dt> <dd><p>The screenshots were taken from GoDaddy’s interface at the time the original version of this guide was published (2015). It may have changed since then.</p> </dd> </dl> </section> </section> </section> <section id="nsec-and-nsec3"> <span id="recipes-nsec3"></span><h3>NSEC and NSEC3<a class="headerlink" href="#nsec-and-nsec3" title="Permalink to this headline"></a></h3> <section id="migrating-from-nsec-to-nsec3"> <span id="recipes-nsec-to-nsec3"></span><h4>Migrating from NSEC to NSEC3<a class="headerlink" href="#migrating-from-nsec-to-nsec3" title="Permalink to this headline"></a></h4> <p>This recipe describes how to transition from using NSEC to NSEC3, as described in <a class="reference internal" href="#advanced-discussions-proof-of-nonexistence"><span class="std std-ref">Proof of Non-Existence (NSEC and NSEC3)</span></a>. This recipe assumes that the zones are already signed, and that <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> is configured according to the steps described in <a class="reference internal" href="#easy-start-guide-for-authoritative-servers"><span class="std std-ref">Easy-Start Guide for Signing Authoritative Zones</span></a>.</p> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>If your zone is signed with RSASHA1 (algorithm 5), you cannot migrate to NSEC3 without also performing an algorithm rollover to RSASHA1-NSEC3-SHA1 (algorithm 7), as described in <a class="reference internal" href="#advanced-discussions-dnskey-algorithm-rollovers"><span class="std std-ref">Algorithm Rollovers</span></a>. This ensures that older validating resolvers that do not understand NSEC3 will fall back to treating the zone as unsecured (rather than “bogus”), as described in Section 2 of <span class="target" id="index-15"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc5155.html"><strong>RFC 5155</strong></a>.</p> </div> <p>To enable NSEC3, update your <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> and add the desired NSEC3 parameters. The example below enables NSEC3 for zones with the <code class="docutils literal notranslate"><span class="pre">standard</span></code> DNSSEC policy, using 0 additional iterations, no opt-out, and a zero-length salt:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="s2">"standard"</span> <span class="p">{</span> <span class="n">nsec3param</span> <span class="n">iterations</span> <span class="mi">0</span> <span class="n">optout</span> <span class="n">no</span> <span class="n">salt</span><span class="o">-</span><span class="n">length</span> <span class="mi">0</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p>Then reconfigure the server with <a class="reference internal" href="manpages.html#std-iscman-rndc"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">rndc</span></code></a>. You can tell that it worked if you see the following debug log messages:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Oct</span> <span class="mi">21</span> <span class="mi">13</span><span class="p">:</span><span class="mi">47</span><span class="p">:</span><span class="mi">21</span> <span class="n">received</span> <span class="n">control</span> <span class="n">channel</span> <span class="n">command</span> <span class="s1">'reconfig'</span> <span class="n">Oct</span> <span class="mi">21</span> <span class="mi">13</span><span class="p">:</span><span class="mi">47</span><span class="p">:</span><span class="mi">21</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span> <span class="p">(</span><span class="n">signed</span><span class="p">):</span> <span class="n">zone_addnsec3chain</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="n">CREATE</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="p">)</span> </pre></div> </div> <p>You can also verify that it worked by querying for a name that you know does not exist, and checking for the presence of the NSEC3 record. For example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 thereisnowaythisexists.example.com. A +dnssec +multiline ... 5A03TL362CS8VSIH69CVA4MJIKRHFQH3.example.com. 300 IN NSEC3 1 0 0 - ( TQ9QBEGA6CROHEOC8KIH1A2C06IVQ5ER NS SOA RRSIG DNSKEY NSEC3PARAM ) ... </pre></div> </div> <p>Our example used four parameters: 1, 0, 0, and -, in order. 1 represents the algorithm, 0 represents the opt-out flag, 0 represents the number of additional iterations, and - denotes no salt is used. To learn more about each of these parameters, please see <a class="reference internal" href="#advanced-discussions-nsec3param"><span class="std std-ref">NSEC3PARAM</span></a>.</p> </section> <section id="migrating-from-nsec3-to-nsec"> <span id="recipes-nsec3-to-nsec"></span><h4>Migrating from NSEC3 to NSEC<a class="headerlink" href="#migrating-from-nsec3-to-nsec" title="Permalink to this headline"></a></h4> <p>Migrating from NSEC3 back to NSEC is easy; just remove the <a class="reference internal" href="reference.html#namedconf-statement-nsec3param" title="namedconf-statement-nsec3param"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">nsec3param</span></code></a> configuration option from your <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> and reconfigure the name server. You can tell that it worked if you see these messages in the log:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">named</span><span class="p">[</span><span class="mi">14093</span><span class="p">]:</span> <span class="n">received</span> <span class="n">control</span> <span class="n">channel</span> <span class="n">command</span> <span class="s1">'reconfig'</span> <span class="n">named</span><span class="p">[</span><span class="mi">14093</span><span class="p">]:</span> <span class="n">zone</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">IN</span><span class="p">:</span> <span class="n">zone_addnsec3chain</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="n">REMOVE</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="p">)</span> </pre></div> </div> <p>You can also query for a name that you know does not exist, and you should no longer see any traces of NSEC3 records.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ dig @192.168.1.13 reieiergiuhewhiouwe.example.com. A +dnssec +multiline ... example.com. 300 IN NSEC aaa.example.com. NS SOA RRSIG NSEC DNSKEY ... ns1.example.com. 300 IN NSEC web.example.com. A RRSIG NSEC ... </pre></div> </div> </section> <section id="recipes-nsec3-optout"> <span id="id51"></span><h4>NSEC3 Opt-Out<a class="headerlink" href="#recipes-nsec3-optout" title="Permalink to this headline"></a></h4> <p>This recipe discusses how to enable and disable NSEC3 opt-out, and how to show the results of each action. As discussed in <a class="reference internal" href="#advanced-discussions-nsec3-optout"><span class="std std-ref">NSEC3 Opt-Out</span></a>, NSEC3 opt-out is a feature that can help conserve resources on parent zones with many delegations that have not yet been signed.</p> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>NSEC3 Opt-Out feature brings benefit only to _extremely_ large zones with lots of insecure delegations. It’s use is counterproductive in all other cases as it decreases tamper-resistance of the zone and also decreases efficiency of resolver cache (see <span class="target" id="index-16"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc8198.html"><strong>RFC 8198</strong></a>).</p> <p>In other words, don’t enable Opt-Out unless you are serving an equivalent of <code class="docutils literal notranslate"><span class="pre">com.</span></code> zone.</p> </div> <p>Because the NSEC3PARAM record does not keep track of whether opt-out is used, it is hard to check whether changes need to be made to the NSEC3 chain if the flag is changed. Similar to changing the NSEC3 salt, your best option is to change the value of <code class="docutils literal notranslate"><span class="pre">optout</span></code> together with another NSEC3 parameter, like <code class="docutils literal notranslate"><span class="pre">iterations</span></code>, and in a following step restore the <code class="docutils literal notranslate"><span class="pre">iterations</span></code> value.</p> <p>For this recipe we assume the zone <code class="docutils literal notranslate"><span class="pre">example.com</span></code> has the following four entries (for this example, it is not relevant what record types these entries are):</p> <ul class="simple"> <li><p><code class="docutils literal notranslate"><span class="pre">ns1.example.com</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">ftp.example.com</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">www.example.com</span></code></p></li> <li><p><code class="docutils literal notranslate"><span class="pre">web.example.com</span></code></p></li> </ul> <p>And the zone <code class="docutils literal notranslate"><span class="pre">example.com</span></code> has five delegations to five subdomains, only one of which is signed and has a valid DS RRset:</p> <ul class="simple"> <li><p><code class="docutils literal notranslate"><span class="pre">aaa.example.com</span></code>, not signed</p></li> <li><p><code class="docutils literal notranslate"><span class="pre">bbb.example.com</span></code>, signed</p></li> <li><p><code class="docutils literal notranslate"><span class="pre">ccc.example.com</span></code>, not signed</p></li> <li><p><code class="docutils literal notranslate"><span class="pre">ddd.example.com</span></code>, not signed</p></li> <li><p><code class="docutils literal notranslate"><span class="pre">eee.example.com</span></code>, not signed</p></li> </ul> <p>Before enabling NSEC3 opt-out, the zone <code class="docutils literal notranslate"><span class="pre">example.com</span></code> contains ten NSEC3 records; below is the list with the plain text name before the actual NSEC3 record:</p> <ul class="simple"> <li><p><em>aaa.example.com</em>: IFA1I3IE7EKCTPHM6R58URO3Q846I52M.example.com</p></li> <li><p><em>bbb.example.com</em>: ROJUF3VJSJO6LQ2LC1DNSJ5GBAUJPVHE.example.com</p></li> <li><p><em>ccc.example.com</em>: 0VPUT696LUVDPDS5NIHSHBH9KLV20V5K.example.com</p></li> <li><p><em>ddd.example.com</em>: UHPBD5U4HRGB84MLC2NQOVEFNAKJU0CA.example.com</p></li> <li><p><em>eee.example.com</em>: NF7I61FA4C2UEKPMEDSOC25FE0UJIMKT.example.com</p></li> <li><p><em>ftp.example.com</em>: 8P15KCUAT1RHCSDN46HBQVPI5T532IN1.example.com</p></li> <li><p><em>ns1.example.com</em>: GUFVRA2SFIO8RSFP7UO41E8AD1KR41FH.example.com</p></li> <li><p><em>web.example.com</em>: CVQ4LA4ALPQIAO2H3N2RB6IR8UHM91E7.example.com</p></li> <li><p><em>www.example.com</em>: MIFDNDT3NFF3OD53O7TLA1HRFF95JKUK.example.com</p></li> <li><p><em>example.com</em>: ONIB9MGUB9H0RML3CDF5BGRJ59DKJHVK.example.com</p></li> </ul> <p>We can enable NSEC3 opt-out with the following configuration, changing the <code class="docutils literal notranslate"><span class="pre">optout</span></code> configuration value from <code class="docutils literal notranslate"><span class="pre">no</span></code> to <code class="docutils literal notranslate"><span class="pre">yes</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="s2">"standard"</span> <span class="p">{</span> <span class="n">nsec3param</span> <span class="n">iterations</span> <span class="mi">0</span> <span class="n">optout</span> <span class="n">yes</span> <span class="n">salt</span><span class="o">-</span><span class="n">length</span> <span class="mi">0</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p>After NSEC3 opt-out is enabled, the number of NSEC3 records is reduced. Notice that the unsigned delegations <code class="docutils literal notranslate"><span class="pre">aaa</span></code>, <code class="docutils literal notranslate"><span class="pre">ccc</span></code>, <code class="docutils literal notranslate"><span class="pre">ddd</span></code>, and <code class="docutils literal notranslate"><span class="pre">eee</span></code> no longer have corresponding NSEC3 records.</p> <ul class="simple"> <li><p><em>bbb.example.com</em>: ROJUF3VJSJO6LQ2LC1DNSJ5GBAUJPVHE.example.com</p></li> <li><p><em>ftp.example.com</em>: 8P15KCUAT1RHCSDN46HBQVPI5T532IN1.example.com</p></li> <li><p><em>ns1.example.com</em>: GUFVRA2SFIO8RSFP7UO41E8AD1KR41FH.example.com</p></li> <li><p><em>web.example.com</em>: CVQ4LA4ALPQIAO2H3N2RB6IR8UHM91E7.example.com</p></li> <li><p><em>www.example.com</em>: MIFDNDT3NFF3OD53O7TLA1HRFF95JKUK.example.com</p></li> <li><p><em>example.com</em>: ONIB9MGUB9H0RML3CDF5BGRJ59DKJHVK.example.com</p></li> </ul> <p>To undo NSEC3 opt-out, change the configuration again:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">dnssec</span><span class="o">-</span><span class="n">policy</span> <span class="s2">"standard"</span> <span class="p">{</span> <span class="n">nsec3param</span> <span class="n">iterations</span> <span class="mi">0</span> <span class="n">optout</span> <span class="n">no</span> <span class="n">salt</span><span class="o">-</span><span class="n">length</span> <span class="mi">0</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <div class="admonition note"> <p class="admonition-title">Note</p> <p>NSEC3 hashes the plain text domain name, and we can compute our own hashes using the tool <a class="reference internal" href="manpages.html#std-iscman-nsec3hash"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">nsec3hash</span></code></a>. For example, to compute the hashed name for <code class="docutils literal notranslate"><span class="pre">www.example.com</span></code> using the parameters we listed above, we can execute this command:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># nsec3hash - 1 0 www.example.com.</span> <span class="n">MIFDNDT3NFF3OD53O7TLA1HRFF95JKUK</span> <span class="p">(</span><span class="n">salt</span><span class="o">=-</span><span class="p">,</span> <span class="nb">hash</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> </pre></div> </div> </div> </section> </section> <section id="reverting-to-unsigned"> <span id="revert-to-unsigned"></span><h3>Reverting to Unsigned<a class="headerlink" href="#reverting-to-unsigned" title="Permalink to this headline"></a></h3> <p>This recipe describes how to revert from a signed zone (DNSSEC) back to an unsigned (DNS) zone.</p> <p>Here is what <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a> looks like when it is signed:</p> <div class="highlight-none notranslate"><div class="highlight"><pre><span></span> zone "example.com" IN { type primary; file "db/example.com.db"; <span class="hll"> dnssec-policy "default"; </span> inline-signing yes; }; </pre></div> </div> <p>To indicate the reversion to unsigned, change the <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> line:</p> <div class="highlight-none notranslate"><div class="highlight"><pre><span></span> zone "example.com" IN { type primary; file "db/example.com.db"; <span class="hll"> dnssec-policy "insecure"; </span> inline-signing yes; }; </pre></div> </div> <p>Then use <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-reload"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">reload</span></code></a> to reload the zone.</p> <p>The “insecure” policy is a built-in policy (like “default”). It makes sure the zone is still DNSSEC-maintained, to allow for a graceful transition to unsigned. It also publishes the CDS and CDNSKEY DELETE records automatically at the appropriate time.</p> <p>If the parent zone allows management of DS records via CDS/CDNSKEY, as described in <span class="target" id="index-17"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc8078.html"><strong>RFC 8078</strong></a>, the DS record should be removed from the parent automatically.</p> <p>Otherwise, DS records can be removed via the registrar. Below is an example showing how to remove DS records using the <a class="reference external" href="https://www.godaddy.com">GoDaddy</a> web-based interface:</p> <ol class="arabic simple"> <li><p>After logging in, click the green “Launch” button next to the domain name you want to manage.</p></li> </ol> <blockquote id="unsign-1"> <div><figure class="align-default" id="id68"> <a class="reference internal image-reference" href="_images/unsign-1.png"><img alt="Revert to Unsigned Step #1" src="_images/unsign-1.png" style="width: 60.0%;" /></a> <figcaption> <p><span class="caption-text">Revert to Unsigned Step #1</span><a class="headerlink" href="#id68" title="Permalink to this image"></a></p> </figcaption> </figure> </div></blockquote> <ol class="arabic simple" start="2"> <li><p>Scroll down to the “DS Records” section and click Manage.</p></li> </ol> <blockquote id="unsign-2"> <div><figure class="align-default" id="id69"> <a class="reference internal image-reference" href="_images/unsign-2.png"><img alt="Revert to Unsigned Step #2" src="_images/unsign-2.png" style="width: 40.0%;" /></a> <figcaption> <p><span class="caption-text">Revert to Unsigned Step #2</span><a class="headerlink" href="#id69" title="Permalink to this image"></a></p> </figcaption> </figure> </div></blockquote> <ol class="arabic simple" start="3"> <li><p>A dialog appears, displaying all current keys. Use the far right-hand X button to remove each key.</p></li> </ol> <blockquote id="unsign-3"> <div><figure class="align-default" id="id70"> <a class="reference internal image-reference" href="_images/unsign-3.png"><img alt="Revert to Unsigned Step #3" src="_images/unsign-3.png" style="width: 70.0%;" /></a> <figcaption> <p><span class="caption-text">Revert to Unsigned Step #3</span><a class="headerlink" href="#id70" title="Permalink to this image"></a></p> </figcaption> </figure> </div></blockquote> <ol class="arabic simple" start="4"> <li><p>Click Save.</p></li> </ol> <blockquote id="unsign-4"> <div><figure class="align-default" id="id71"> <a class="reference internal image-reference" href="_images/unsign-4.png"><img alt="Revert to Unsigned Step #4" src="_images/unsign-4.png" style="width: 70.0%;" /></a> <figcaption> <p><span class="caption-text">Revert to Unsigned Step #4</span><a class="headerlink" href="#id71" title="Permalink to this image"></a></p> </figcaption> </figure> </div></blockquote> <p>When the DS records have been removed from the parent zone, use <a class="reference internal" href="manpages.html#cmdoption-rndc-arg-dnssec"><code class="xref std std-option docutils literal notranslate"><span class="pre">rndc</span> <span class="pre">dnssec</span> <span class="pre">-checkds</span> <span class="pre">-key</span> <span class="pre">id</span> <span class="pre">withdrawn</span> <span class="pre">example.com</span></code></a> to tell <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> that the DS is removed, and the remaining DNSSEC records will be removed in a timely manner. Or, if parental agents are configured, the DNSSEC records will be automatically removed after BIND has seen that the parental agents no longer serve the DS RRset for this zone.</p> <p>After a while, the zone is reverted back to the traditional, insecure DNS format. This can be verified by checking that all DNSKEY and RRSIG records have been removed from the zone.</p> <p>The <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> line can then be removed from <a class="reference internal" href="manpages.html#std-iscman-named.conf"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named.conf</span></code></a> and the zone reloaded. The zone will no longer be subject to any DNSSEC maintenance.</p> </section> </section> <section id="commonly-asked-questions"> <span id="dnssec-commonly-asked-questions"></span><h2>Commonly Asked Questions<a class="headerlink" href="#commonly-asked-questions" title="Permalink to this headline"></a></h2> <p>Below are some common questions and (hopefully) some answers that help.</p> <dl> <dt>Do I need IPv6 to have DNSSEC?</dt><dd><p>No. DNSSEC can be deployed without IPv6.</p> </dd> <dt>Does DNSSEC encrypt my DNS traffic, so others cannot eavesdrop on my DNS queries?</dt><dd><p>No. Although cryptographic keys and digital signatures are used in DNSSEC, they only provide authenticity and integrity, not privacy. Someone who sniffs network traffic can still see all the DNS queries and answers in plain text; DNSSEC just makes it very difficult for the eavesdropper to alter or spoof the DNS responses. For protection against eavesdropping, the preferred protocol is DNS-over-TLS. DNS-over-HTTPS can also do the job, but it is more complex.</p> </dd> <dt>If I deploy DNS-over-TLS/HTTPS, can I skip deploying DNSSEC?</dt><dd><p>No. DNS-over-encrypted-transport stops eavesdroppers on a network, but it does not protect against cache poisoning and answer manipulation in other parts of the DNS resolution chain. In other words, these technologies offer protection only for records when they are in transit between two machines; any compromised server can still redirect traffic elsewhere (or simply eavesdrop). However, DNSSEC provides integrity and authenticity for DNS <em>records</em>, even when these records are stored in caches and on disks.</p> </dd> <dt>Does DNSSEC protect the communication between my laptop and my name server?</dt><dd><p>Unfortunately, not at the moment. DNSSEC is designed to protect the communication between end clients (laptop) and name servers; however, there are few applications or stub resolver libraries as of mid-2020 that take advantage of this capability.</p> </dd> <dt>Does DNSSEC secure zone transfers?</dt><dd><p>No. You should consider using TSIG to secure zone transfers among your name servers.</p> </dd> <dt>Does DNSSEC protect my network from malicious websites?</dt><dd><p>DNSSEC makes it much more difficult for attackers to spoof DNS responses or perform cache poisoning. It cannot protect against users who visit a malicious website that an attacker owns and operates, or prevent users from mistyping a domain name; it will just become less likely that an attacker can hijack other domain names.</p> <p>In other words, DNSSEC is designed to provide confidence that when a DNS response is received for www.company.com over port 53, it really came from Company’s name servers and the answers are authentic. But that does not mean the web server a user visits over port 80 or port 443 is necessarily safe.</p> </dd> <dt>If I enable DNSSEC validation, will it break DNS lookup, since most domain names do not yet use DNSSEC?</dt><dd><p>No, DNSSEC is backwards-compatible to “standard” DNS. A DNSSEC-enabled validating resolver can still look up all of these domain names as it always has under standard DNS.</p> <p>There are four (4) categories of responses (see <span class="target" id="index-18"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc4035.html"><strong>RFC 4035</strong></a>):</p> <dl class="glossary simple"> <dt id="term-Secure">Secure<a class="headerlink" href="#term-Secure" title="Permalink to this term"></a></dt><dd><p>Domains that have DNSSEC deployed correctly.</p> </dd> <dt id="term-Insecure">Insecure<a class="headerlink" href="#term-Insecure" title="Permalink to this term"></a></dt><dd><p>Domains that have yet to deploy DNSSEC.</p> </dd> <dt id="term-Bogus">Bogus<a class="headerlink" href="#term-Bogus" title="Permalink to this term"></a></dt><dd><p>Domains that have deployed DNSSEC but have done it incorrectly.</p> </dd> <dt id="term-Indeterminate">Indeterminate<a class="headerlink" href="#term-Indeterminate" title="Permalink to this term"></a></dt><dd><p>Domains for which it is not possible to determine whether these domains use DNSSEC.</p> </dd> </dl> <p>A DNSSEC-enabled validating resolver still resolves <a class="reference internal" href="#term-Secure"><span class="xref std std-term">Secure</span></a> and <a class="reference internal" href="#term-Insecure"><span class="xref std std-term">Insecure</span></a>; only <a class="reference internal" href="#term-Bogus"><span class="xref std std-term">Bogus</span></a> and <a class="reference internal" href="#term-Indeterminate"><span class="xref std std-term">Indeterminate</span></a> result in a SERVFAIL. As of mid-2022, roughly one-third of users worldwide are using DNSSEC validation on their recursive name servers. Google public DNS (8.8.8.8) also has enabled DNSSEC validation.</p> </dd> <dt>Do I need to have special client software to use DNSSEC?</dt><dd><p>No. DNSSEC only changes the communication behavior among DNS servers, not between a DNS server (validating resolver) and a client (stub resolver). With DNSSEC validation enabled on your recursive server, if a domain name does not pass the checks, an error message (typically SERVFAIL) is returned to clients; to most client software today, it appears that the DNS query has failed or that the domain name does not exist.</p> </dd> <dt>Since DNSSEC uses public key cryptography, do I need Public Key Infrastructure (PKI) in order to use DNSSEC?</dt><dd><p>No, DNSSEC does not depend on an existing PKI. Public keys are stored within the DNS hierarchy; the trustworthiness of each zone is guaranteed by its parent zone, all the way back to the root zone. A copy of the trust anchor for the root zone is distributed with BIND 9.</p> </dd> <dt>Do I need to purchase SSL certificates from a Certificate Authority (CA) to use DNSSEC?</dt><dd><p>No. With DNSSEC, you generate and publish your own keys, and sign your own data as well. There is no need to pay someone else to do it for you.</p> </dd> <dt>My parent zone does not support DNSSEC; can I still sign my zone?</dt><dd><p>Technically, yes, but you will not get the full benefit of DNSSEC, as other validating resolvers are not able to validate your zone data. Without the DS record(s) in your parent zone, other validating resolvers treat your zone as an insecure (traditional) zone, and no actual verification is carried out. To the rest of the world, your zone still appears to be insecure, and it will continue to be insecure until your parent zone can host the DS record(s) for you and tell the rest of the world that your zone is signed.</p> </dd> <dt>Is DNSSEC the same thing as TSIG?</dt><dd><p>No. TSIG is typically used between primary and secondary name servers to secure zone transfers, while DNSSEC secures DNS lookup by validating answers. Even if you enable DNSSEC, zone transfers are still not validated; to secure the communication between your primary and secondary name servers, consider setting up TSIG or similar secure channels.</p> </dd> <dt>How are keys copied from primary to secondary server(s)?</dt><dd><p>DNSSEC uses public cryptography, which results in two types of keys: public and private. The public keys are part of the zone data, stored as DNSKEY record types. Thus the public keys are synchronized from primary to secondary server(s) as part of the zone transfer. The private keys are not, and should not be, stored anywhere other than secured on the primary server. See <a class="reference internal" href="#advanced-discussions-key-storage"><span class="std std-ref">Key Storage</span></a> for more information on key storage options and considerations.</p> </dd> <dt>Can I use the same key for multiple zones?</dt><dd><p>Yes and no. Good security practice suggests that you should use unique key pairs for each zone, just as you should have different passwords for your email account, social media login, and online banking credentials. On a technical level, it is completely feasible to reuse a key, but multiple zones are at risk if one key pair is compromised. However, if you have hundreds or thousands of zones to administer, a single key pair for all might be less error-prone to manage. You may choose to use the same approach as with password management: use unique passwords for your bank accounts and shopping sites, but use a standard password for your not-very-important logins. First, categorize your zones: high-value zones (or zones that have specific key rollover requirements) get their own key pairs, while other, more “generic” zones can use a single key pair for easier management. Note that at present (mid-2020), fully automatic signing (using the <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> clause in your <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> configuration file) does not support reuse of keys except when the same zone appears in multiple views (see next question). To use the same key for multiple zones, sign your zones using semi-automatic signing. Each zone wishing to use the key should point to the same key directory.</p> </dd> <dt>How do I sign the different instances of a zone that appears in multiple views?</dt><dd><p>Add a <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement to each <a class="reference internal" href="reference.html#namedconf-statement-zone" title="namedconf-statement-zone"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">zone</span></code></a> definition in the configuration file. To avoid problems when a single computer accesses different instances of the zone while information is still in its cache (e.g., a laptop moving from your office to a customer site), you should sign all instances with the same key. This means setting the same DNSSEC policy for all instances of the zone, and making sure that the key directory is the same for all instances of the zone.</p> </dd> <dt>Will there be any problems if I change the DNSSEC policy for a zone?</dt><dd><p>If you are using fully automatic signing, no. Just change the parameters in the <a class="reference internal" href="reference.html#namedconf-statement-dnssec-policy" title="namedconf-statement-dnssec-policy"><code class="xref any namedconf namedconf-ref docutils literal notranslate"><span class="pre">dnssec-policy</span></code></a> statement and reload the configuration file. <a class="reference internal" href="manpages.html#std-iscman-named"><code class="xref std std-iscman docutils literal notranslate"><span class="pre">named</span></code></a> makes a smooth transition to the new policy, ensuring that your zone remains valid at all times.</p> </dd> </dl> </section> </section> </div> </div> <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer"> <a href="changelog.html" class="btn btn-neutral float-left" title="Changelog" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> <a href="history.html" class="btn btn-neutral float-right" title="A Brief History of the DNS and BIND" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> </div> <hr/> <div role="contentinfo"> <p>© Copyright 2025, Internet Systems Consortium.</p> </div> Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. </footer> </div> </div> </section> </div> <script> jQuery(function () { SphinxRtdTheme.Navigation.enable(true); }); </script> </body> </html>
Close