Commit 3839252c authored by Filip Široký's avatar Filip Široký Committed by Daniel Salzman

semantic-check: add more DNSSEC-related checks, refactoring

parent 9da902d0
......@@ -1032,6 +1032,8 @@ Mandatory checks:
.IP \(bu 2
An extra record together with CNAME record (except for RRSIG and DS)
.IP \(bu 2
Multiple CNAME records with the same owner
.IP \(bu 2
SOA record missing in the zone (RFC 1034)
.IP \(bu 2
DNAME records having records under it (DNAME children) (RFC 2672)
......@@ -1063,6 +1065,12 @@ Signer name in RRSIG RR not the same as in DNSKEY
Signed RRSIG
.IP \(bu 2
Wrong key flags or wrong key in RRSIG record (not the same as ZSK)
.IP \(bu 2
Invalid NSEC3PARAM flags or digest algorithm
.IP \(bu 2
Invalid DS algorithm or digest length
.IP \(bu 2
Not corresponding CDS and CDNSKEY records
.UNINDENT
.sp
\fIDefault:\fP off
......
......@@ -1184,6 +1184,7 @@ logged only.
Mandatory checks:
- An extra record together with CNAME record (except for RRSIG and DS)
- Multiple CNAME records with the same owner
- SOA record missing in the zone (RFC 1034)
- DNAME records having records under it (DNAME children) (RFC 2672)
......@@ -1201,6 +1202,9 @@ Extra checks:
- Signer name in RRSIG RR not the same as in DNSKEY
- Signed RRSIG
- Wrong key flags or wrong key in RRSIG record (not the same as ZSK)
- Invalid NSEC3PARAM flags or digest algorithm
- Invalid DS algorithm or digest length
- Not corresponding CDS and CDNSKEY records
*Default:* off
......
/* Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -15,22 +15,11 @@
*/
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "contrib/wire_ctx.h"
#include "dnssec/error.h"
#include "dnssec/key.h"
#include "dnssec/sign.h"
#include "knot/dnssec/rrset-sign.h"
#include "libknot/attribute.h"
#include "libknot/descriptor.h"
#include "libknot/libknot.h"
#include "libknot/packet/rrset-wire.h"
#include "libknot/packet/wire.h"
#include "libknot/rrset.h"
#include "libknot/rrtype/rrsig.h"
#define RRSIG_RDATA_SIGNER_OFFSET 18
......@@ -189,24 +178,14 @@ static int sign_ctx_add_records(dnssec_sign_ctx_t *ctx, const knot_rrset_t *cove
return result;
}
/*!
* \brief Add all data covered by signature into signing context.
*
* RFC 4034: The signature covers RRSIG RDATA field (excluding the signature)
* and all matching RR records, which are ordered canonically.
*
* Requires all DNAMEs in canonical form and all RRs ordered canonically.
*
* \param ctx Signing context.
* \param rrsig_rdata RRSIG RDATA with populated fields except signature.
* \param covered Covered RRs.
*
* \return Error code, KNOT_EOK if successful.
*/
static int sign_ctx_add_data(dnssec_sign_ctx_t *ctx,
const uint8_t *rrsig_rdata,
const knot_rrset_t *covered)
int knot_sign_ctx_add_data(dnssec_sign_ctx_t *ctx,
const uint8_t *rrsig_rdata,
const knot_rrset_t *covered)
{
if (!ctx || !rrsig_rdata || knot_rrset_empty(covered)) {
return KNOT_EINVAL;
}
int result = sign_ctx_add_self(ctx, rrsig_rdata);
if (result != KNOT_EOK) {
return result;
......@@ -259,7 +238,7 @@ static int rrsigs_create_rdata(knot_rrset_t *rrsigs, dnssec_sign_ctx_t *ctx,
return res;
}
res = sign_ctx_add_data(ctx, header, covered);
res = knot_sign_ctx_add_data(ctx, header, covered);
if (res != KNOT_EOK) {
return res;
}
......@@ -385,7 +364,7 @@ int knot_check_signature(const knot_rrset_t *covered,
return result;
}
result = sign_ctx_add_data(sign_ctx, rdata, covered);
result = knot_sign_ctx_add_data(sign_ctx, rdata, covered);
if (result != KNOT_EOK) {
return result;
}
......
/* Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -13,23 +13,9 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file rrset-sign.h
*
* \author Jan Vcelak <jan.vcelak@nic.cz>
*
* \brief Interface for DNSSEC signing of RR sets.
*
* \addtogroup dnssec
* @{
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "dnssec/key.h"
#include "dnssec/sign.h"
#include "knot/dnssec/context.h"
......@@ -54,6 +40,24 @@ int knot_sign_rrset(knot_rrset_t *rrsigs,
const kdnssec_ctx_t *dnssec_ctx,
knot_mm_t *mm);
/*!
* \brief Add all data covered by signature into signing context.
*
* RFC 4034: The signature covers RRSIG RDATA field (excluding the signature)
* and all matching RR records, which are ordered canonically.
*
* Requires all DNAMEs in canonical form and all RRs ordered canonically.
*
* \param ctx Signing context.
* \param rrsig_rdata RRSIG RDATA with populated fields except signature.
* \param covered Covered RRs.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_sign_ctx_add_data(dnssec_sign_ctx_t *ctx,
const uint8_t *rrsig_rdata,
const knot_rrset_t *covered);
/*!
* \brief Creates new RRS using \a rrsig_rrs as a source. Only those RRs that
* cover given \a type are copied into \a out_sig
......@@ -88,5 +92,3 @@ int knot_check_signature(const knot_rrset_t *covered,
const dnssec_key_t *key,
dnssec_sign_ctx_t *sign_ctx,
const kdnssec_ctx_t *dnssec_ctx);
/*! @} */
......@@ -16,15 +16,11 @@
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
#include <time.h>
#include "dnssec/error.h"
#include "dnssec/keystore.h"
#include "knot/common/log.h"
#include "knot/dnssec/zone-keys.h"
#include "libknot/libknot.h"
#include "libknot/rrtype/dnskey.h"
dynarray_define(keyptr, zone_key_t *, DYNARRAY_VISIBILITY_PUBLIC)
......
......@@ -13,25 +13,12 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file zone-keys.h
*
* \brief Loading of zone keys.
*
* \addtogroup dnssec
* @{
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include "contrib/dynarray.h"
#include "dnssec/keystore.h"
#include "dnssec/sign.h"
#include "knot/dnssec/kasp/kasp_zone.h"
#include "knot/dnssec/kasp/policy.h"
#include "knot/dnssec/context.h"
......@@ -160,5 +147,3 @@ knot_time_t knot_get_next_zone_key_event(const zone_keyset_t *keyset);
* \return Error code, KNOT_EOK if successful.
*/
int zone_key_calculate_ds(zone_key_t *for_key, dnssec_binary_t *out_donotfree);
/*! @} */
......@@ -156,9 +156,11 @@ static time_t bootstrap_next(const zone_timers_t *timers)
static int xfr_validate(zone_contents_t *zone, struct refresh_data *data)
{
err_handler_logger_t handler;
handler._cb.cb = err_handler_logger;
int ret = zone_do_sem_checks(zone, false, &handler._cb, time(NULL));
err_handler_t handler = {
.cb = err_handler_logger
};
int ret = zone_do_sem_checks(zone, false, &handler, time(NULL));
if (ret != KNOT_EOK) {
// error is logged by the error handler
return ret;
......
This diff is collapsed.
......@@ -23,7 +23,7 @@
*\brief Internal error constants. General errors are added for convenience,
* so that code does not have to change if new errors are added.
*/
enum zonechecks_errors {
typedef enum {
ZC_ERR_UNKNOWN = -50,
ZC_ERR_MISSING_SOA,
......@@ -34,66 +34,78 @@ enum zonechecks_errors {
ZC_ERR_RRSIG_RDATA_TYPE_COVERED,
ZC_ERR_RRSIG_RDATA_TTL,
ZC_ERR_RRSIG_RDATA_EXPIRATION,
ZC_ERR_RRSIG_RDATA_INCEPTION,
ZC_ERR_RRSIG_RDATA_LABELS,
ZC_ERR_RRSIG_RDATA_DNSKEY_OWNER,
ZC_ERR_RRSIG_RDATA_OWNER,
ZC_ERR_RRSIG_NO_RRSIG,
ZC_ERR_RRSIG_SIGNED,
ZC_ERR_RRSIG_TTL,
ZC_ERR_RRSIG_UNVERIFIABLE,
ZC_ERR_RRSIG_GENERAL_ERROR, /* RRSIG error delimiter. */
ZC_ERR_NO_NSEC,
ZC_ERR_NSEC_NONE,
ZC_ERR_NSEC_RDATA_BITMAP,
ZC_ERR_NSEC_RDATA_MULTIPLE,
ZC_ERR_NSEC_RDATA_CHAIN,
ZC_ERR_NSEC_GENERAL_ERROR, /* NSEC error delimiter. */
ZC_ERR_NSEC3_NOT_FOUND,
ZC_ERR_NSEC3_NONE,
ZC_ERR_NSEC3_INSECURE_DELEGATION_OPT,
ZC_ERR_NSEC3_TTL,
ZC_ERR_NSEC3_RDATA_CHAIN,
ZC_ERR_NSEC3_EXTRA_RECORD,
ZC_ERR_NSEC3_RDATA_TTL,
ZC_ERR_NSEC3_RDATA_CHAIN,
ZC_ERR_NSEC3_RDATA_BITMAP,
ZC_ERR_NSEC3_RDATA_FLAGS,
ZC_ERR_NSEC3_RDATA_SALT,
ZC_ERR_NSEC3_RDATA_ALG,
ZC_ERR_NSEC3_RDATA_ITERS,
ZC_ERR_NSEC3_PARAM_RDATA_FLAGS,
ZC_ERR_NSEC3_PARAM_RDATA_ALG,
ZC_ERR_NSEC3_GENERAL_ERROR, /* NSEC3 error delimiter. */
ZC_ERR_CNAME_EXTRA_RECORDS,
ZC_ERR_DNAME_CHILDREN,
ZC_ERR_CNAME_MULTIPLE,
ZC_ERR_DNAME_MULTIPLE,
ZC_ERR_CNAME_WILDCARD_SELF,
ZC_ERR_DNAME_WILDCARD_SELF,
ZC_ERR_DNAME_CHILDREN,
ZC_ERR_CNAME_GENERAL_ERROR, /* CNAME/DNAME error delimiter. */
ZC_ERR_GLUE_RECORD,
ZC_ERR_DS_RDATA_ALG,
ZC_ERR_DS_RDATA_DIGLEN,
ZC_ERR_INVALID_KEY,
ZC_ERR_CDS_CDNSKEY,
ZC_ERR_LAST,
};
} zc_error_t;
const char *semantic_check_error_msg(int ecode);
/*!
* \brief Structure for handling semantic errors.
*/
typedef struct err_handler err_handler_t;
/*!
* \brief Callback for handle error.
*
* Return KNOT_EOK to continue in semantic checks.
* Return other KNOT_E* to stop semantic check with error.
*/
typedef int (*error_cb) (err_handler_t *ctx, const zone_contents_t *zone,
const zone_node_t *node, int error, const char *data);
typedef void (*error_cb) (err_handler_t *ctx, const zone_contents_t *zone,
const zone_node_t *node, zc_error_t error, const char *data);
struct err_handler {
error_cb cb;
bool fatal_error;
};
/*!
* \brief Check zone for semantic errors.
*
......
......@@ -32,28 +32,24 @@ int zone_load_contents(conf_t *conf, const knot_dname_t *zone_name,
return KNOT_EINVAL;
}
zloader_t zl;
char *zonefile = conf_zonefile(conf, zone_name);
conf_val_t val = conf_zone_get(conf, C_SEM_CHECKS, zone_name);
int ret = zonefile_open(&zl, zonefile, zone_name, conf_bool(&val), time(NULL));
err_handler_logger_t handler;
memset(&handler, 0, sizeof(handler));
handler._cb.cb = err_handler_logger;
zl.err_handler = (err_handler_t *) &handler;
zloader_t zl;
int ret = zonefile_open(&zl, zonefile, zone_name, conf_bool(&val), time(NULL));
free(zonefile);
if (ret != KNOT_EOK) {
return ret;
}
/* Set the zone type (master/slave). If zone has no master set, we
* are the primary master for this zone (i.e. zone type = master).
*/
err_handler_t handler = {
.cb = err_handler_logger
};
zl.err_handler = &handler;
zl.creator->master = !zone_load_can_bootstrap(conf, zone_name);
*contents = zonefile_load(&zl);
zonefile_close(&zl);
if (*contents == NULL) {
return KNOT_ERROR;
......
......@@ -254,7 +254,9 @@ zone_contents_t *zonefile_load(zloader_t *loader)
}
if (!node_rrtype_exists(loader->creator->z->apex, KNOT_RRTYPE_SOA)) {
loader->err_handler->cb(loader->err_handler, zc->z, NULL, ZC_ERR_MISSING_SOA, NULL);
loader->err_handler->fatal_error = true;
loader->err_handler->cb(loader->err_handler, zc->z, NULL,
ZC_ERR_MISSING_SOA, NULL);
goto fail;
}
......@@ -266,7 +268,7 @@ zone_contents_t *zonefile_load(zloader_t *loader)
}
ret = zone_do_sem_checks(zc->z, loader->semantic_checks,
loader->err_handler, loader->time);
loader->err_handler, loader->time);
if (ret != KNOT_EOK) {
ERROR(zname, "failed to load zone, file '%s' (%s)",
......@@ -350,29 +352,25 @@ void zonefile_close(zloader_t *loader)
free(loader->creator);
}
int err_handler_logger(err_handler_t *handler, const zone_contents_t *zone,
const zone_node_t *node, int error, const char *data)
void err_handler_logger(err_handler_t *handler, const zone_contents_t *zone,
const zone_node_t *node, zc_error_t error, const char *data)
{
assert(handler != NULL);
assert(zone != NULL);
err_handler_logger_t *h = (err_handler_logger_t *) handler;
const char *errmsg = semantic_check_error_msg(error);
if (node == NULL) { // zone error
log_zone_warning(zone->apex->owner, "semantic check, %s%s%s",
errmsg, data ? ", " : "", data ? data : "");
} else {
char buff[KNOT_DNAME_TXT_MAXLEN + 1];
char *name = knot_dname_to_str(buff, node->owner, sizeof(buff));
log_zone_warning(zone->apex->owner,
"semantic check, record '%s', %s%s%s",
name ? name : "", errmsg,
data ? ", " : "", data ? data : "");
char buff[KNOT_DNAME_TXT_MAXLEN + 1] = "";
if (node != NULL) {
(void)knot_dname_to_str(buff, node->owner, sizeof(buff));
}
h->error_count++;
return KNOT_EOK;
log_fmt_zone(handler->fatal_error ? LOG_ERR : LOG_WARNING,
LOG_SOURCE_ZONE, zone->apex->owner,
"check%s%s, %s%s%s",
(node != NULL ? ", node " : ""),
(node != NULL ? buff : ""),
semantic_check_error_msg(error),
(data != NULL ? " " : ""),
(data != NULL ? data : ""));
}
#undef ERROR
......
......@@ -34,7 +34,7 @@ typedef struct zcreator {
/*!
* \brief Zone loader structure.
*/
typedef struct zloader {
typedef struct {
char *source; /*!< Zone source file. */
bool semantic_checks; /*!< Do semantic checks. */
err_handler_t *err_handler; /*!< Semantic checks error handler. */
......@@ -43,14 +43,8 @@ typedef struct zloader {
time_t time; /*!< time for zone check. */
} zloader_t;
typedef struct {
err_handler_t _cb;
unsigned error_count; /*!< Error count for limitng output. */
} err_handler_logger_t;
int err_handler_logger(err_handler_t *handler, const zone_contents_t *zone,
const zone_node_t *node, int error, const char *data);
void err_handler_logger(err_handler_t *handler, const zone_contents_t *zone,
const zone_node_t *node, zc_error_t error, const char *data);
/*!
* \brief Open zone file for loading.
......
......@@ -76,7 +76,7 @@ int main(int argc, char *argv[])
case 't':
if (knot_time_parse("YMDhms|#|+-#U|+-#",
optarg, &check_time) != KNOT_EOK) {
fprintf(stderr, "Unknown time format.\n");
fprintf(stderr, "Unknown time format\n");
return EXIT_FAILURE;
}
break;
......@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
/* Check if there's at least one remaining non-option. */
if (optind >= argc) {
fprintf(stderr, "Expected zone file name.\n");
fprintf(stderr, "Expected zone file name\n");
print_help();
return EXIT_FAILURE;
}
......@@ -109,14 +109,13 @@ int main(int argc, char *argv[])
zonename = strdup(origin);
}
/* TODO: Remove logging from zone loading. */
log_init();
log_levels_set(LOG_TARGET_STDOUT, LOG_SOURCE_ANY, LOG_MASK(LOG_ERR));
log_levels_set(LOG_TARGET_STDOUT, LOG_SOURCE_ANY, 0);
log_levels_set(LOG_TARGET_STDERR, LOG_SOURCE_ANY, 0);
log_levels_set(LOG_TARGET_SYSLOG, LOG_SOURCE_ANY, 0);
log_flag_set(LOG_FLAG_NOTIMESTAMP | LOG_FLAG_NOINFO);
if (verbose) {
log_levels_add(LOG_TARGET_STDOUT, LOG_SOURCE_ANY, LOG_MASK(LOG_DEBUG));
log_levels_add(LOG_TARGET_STDOUT, LOG_SOURCE_ANY, LOG_UPTO(LOG_DEBUG));
}
knot_dname_t *dname = knot_dname_from_str_alloc(zonename);
......@@ -129,17 +128,20 @@ int main(int argc, char *argv[])
switch (ret) {
case KNOT_EOK:
if (verbose) {
fprintf(stdout, "No semantic error found.\n");
fprintf(stdout, "No semantic error found\n");
}
return EXIT_SUCCESS;
case KNOT_EZONEINVAL:
fprintf(stdout, "Serious semantic error detected\n");
// FALLTHROUGH
case KNOT_ESEMCHECK:
return EXIT_FAILURE;
case KNOT_EACCES:
case KNOT_EFILE:
fprintf(stderr, "Failed to load the zone file.\n");
fprintf(stderr, "Failed to load the zone file\n");
return EXIT_FAILURE;
default:
fprintf(stderr, "Failed to run semantic checks (%s).\n", knot_strerror(ret));
fprintf(stderr, "Failed to run semantic checks (%s)\n", knot_strerror(ret));
return EXIT_FAILURE;
}
}
......@@ -22,55 +22,38 @@
#include "utils/kzonecheck/zone_check.h"
typedef struct {
err_handler_t _cb;
err_handler_t handler;
FILE *outfile;
unsigned errors[(-ZC_ERR_UNKNOWN) + 1]; /*!< Counting errors by type */
unsigned error_count; /*!< Total error count */
} err_handler_stats_t;
int err_handler_printf(err_handler_t *handler, const zone_contents_t *zone,
const zone_node_t *node, int error, const char *data)
static void err_callback(err_handler_t *handler, const zone_contents_t *zone,
const zone_node_t *node, zc_error_t error, const char *data)
{
assert(handler != NULL);
assert(zone != NULL);
err_handler_stats_t *h = (err_handler_stats_t *)handler;
err_handler_stats_t *stats = (err_handler_stats_t *)handler;
const char *errmsg = semantic_check_error_msg(error);
char buff[KNOT_DNAME_TXT_MAXLEN + 1] = "";
(void)knot_dname_to_str(buff, (node != NULL ? node->owner : zone->apex->owner),
sizeof(buff));
const char *type = node ? "record" : "zone";
char *name = NULL;
if (node) {
name = knot_dname_to_str_alloc(node->owner);
} else if (zone && zone->apex) {
name = knot_dname_to_str_alloc(zone->apex->owner);
}
if (name) {
// trim terminating dot
int len = strlen(name);
if (len > 1) {
name[len - 1] = '\0';
}
}
fprintf(stats->outfile, "[%s] %s%s%s\n",
buff, semantic_check_error_msg(error),
(data != NULL ? " " : ""),
(data != NULL ? data : ""));
fprintf(h->outfile, "%s '%s': %s%s%s%s\n", type, name ? name : "?",
errmsg, (data ? " (" : ""), (data ? data : ""), (data ? ")" : ""));
free(name);
h->errors[-error]++;
h->error_count++;
return KNOT_EOK;
stats->errors[-error]++;
stats->error_count++;
}
static void print_statistics(err_handler_stats_t *handler)
static void print_statistics(err_handler_stats_t *stats)
{
err_handler_stats_t *h = (err_handler_stats_t *)handler;
fprintf(h->outfile, "\nERROR SUMMARY:\n\tCount\tError\n");
fprintf(stats->outfile, "\nError summary:\n");
for(int i = ZC_ERR_UNKNOWN; i < ZC_ERR_LAST; ++i) {
if (h->errors[-i] > 0) {
fprintf(h->outfile, "\t%u\t%s\n", h->errors[-i],
if (stats->errors[-i] > 0) {
fprintf(stats->outfile, "%4u\t%s\n", stats->errors[-i],
semantic_check_error_msg(i));
}
}
......@@ -79,34 +62,30 @@ static void print_statistics(err_handler_stats_t *handler)
int zone_check(const char *zone_file, const knot_dname_t *zone_name,
FILE *outfile, time_t time)
{
err_handler_stats_t stats = {
.handler = { .cb = err_callback },
.outfile = outfile
};
zloader_t zl;
int ret = zonefile_open(&zl, zone_file, zone_name, true, time);
if (ret != KNOT_EOK) {
return ret;
}
err_handler_stats_t handler;
memset(&handler, 0, sizeof(handler));
handler._cb.cb = err_handler_printf;
handler.outfile = outfile;
zl.err_handler = (err_handler_t *)&handler;
zl.err_handler = (err_handler_t *)&stats;
zl.creator->master = true;
zone_contents_t *contents;
contents = zonefile_load(&zl);
if (handler.error_count > 0) {
ret = KNOT_ESEMCHECK;
print_statistics(&handler);
}
zone_contents_t *contents = zonefile_load(&zl);
zonefile_close(&zl);
if (contents == NULL) {
if (contents == NULL && !stats.handler.fatal_error) {
return KNOT_ERROR;
}
zone_contents_deep_free(&contents);
return ret;
if (stats.error_count > 0) {
print_statistics(&stats);
return stats.handler.fatal_error ? KNOT_EZONEINVAL : KNOT_ESEMCHECK;
} else {
return KNOT_EOK;
}
}
;; Zone dump (Knot DNS 2.5.0-dev)
example.com. 3600 SOA dns2.example.com. hostmaster.example.com. 2010135808 10800 3600 1209600 7200
example.com. 3600 NS dns2.example.com.
example.com. 3600 MX 10 mail.example.com.
example.com. 0 NSEC3PARAM 1 0 250 662455DF6C5AB542
example.com. 3600 DNSKEY 256 3 8 AwEAAdKraxDdGTL4HDOkXTDI1Md1UdHuYhVwYkB+u2umVjTJ1H9Qb2oBryqwXI+gklnuCqrH1znkDvzGEAeHRQUCbtKbjmqErTAcRRHW3D+6jsOGXzbyGCfbyzRBwsbNCLWr3ONpPi5JOWEeCUJfyc/mRXcmh5uYl1JvzAM1zprtljZt
example.com. 3600 DNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 DNSKEY 257 3 8 AwEAAetE6qfN/GbtMmvM0PXUTyskauES2FKfjqLVz7EQlfS8iAFWLi1eHjHXDkueZ1OYRzQ4IBy6MIsce4XVXLQoS8njtfaU7c5NZvktH5la7JuH32KYr3PdWL5KDsUdED3GSxfNV+DbcYU80AZxTxy6Bm6EP+DztL1dpYrmqr8JRl+qlSbmLIrPemZFUEQzhiepcYMWviDUz+ixSVzjEzpMCLsrNxA30Ziiq9GKA8KKlFHdAmxuNcH0TzRndpo6bu5nKyJHiREIazHVuPBEzUmHtcWETCDs9UVsbji2Z2ozqLz9cqnfYV/kOD+OZBAqvZ0n/4lgdSiBtvByLCXoWEYIGRs=
example.com. 3600 CDNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 CDS 53851 8 2 6F8129D687EC387C948E6F4B0AC9AA01481CCEBF7570AFEC582897E7725122D6
dns2.example.com. 3600 A 192.0.2.1
;; Zone dump (Knot DNS 2.5.0-dev)
example.com. 3600 SOA dns2.example.com. hostmaster.example.com. 2010135808 10800 3600 1209600 7200
example.com. 3600 NS dns2.example.com.
example.com. 3600 MX 10 mail.example.com.
example.com. 0 NSEC3PARAM 1 0 250 662455DF6C5AB542
example.com. 3600 DNSKEY 256 3 8 AwEAAdKraxDdGTL4HDOkXTDI1Md1UdHuYhVwYkB+u2umVjTJ1H9Qb2oBryqwXI+gklnuCqrH1znkDvzGEAeHRQUCbtKbjmqErTAcRRHW3D+6jsOGXzbyGCfbyzRBwsbNCLWr3ONpPi5JOWEeCUJfyc/mRXcmh5uYl1JvzAM1zprtljZt
example.com. 3600 DNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 DNSKEY 257 3 8 AwEAAetE6qfN/GbtMmvM0PXUTyskauES2FKfjqLVz7EQlfS8iAFWLi1eHjHXDkueZ1OYRzQ4IBy6MIsce4XVXLQoS8njtfaU7c5NZvktH5la7JuH32KYr3PdWL5KDsUdED3GSxfNV+DbcYU80AZxTxy6Bm6EP+DztL1dpYrmqr8JRl+qlSbmLIrPemZFUEQzhiepcYMWviDUz+ixSVzjEzpMCLsrNxA30Ziiq9GKA8KKlFHdAmxuNcH0TzRndpo6bu5nKyJHiREIazHVuPBEzUmHtcWETCDs9UVsbji2Z2ozqLz9cqnfYV/kOD+OZBAqvZ0n/4lgdSiBtvByLCXoWEYIGRs=
example.com. 3600 CDNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 CDS 53851 8 2 668159D684EC387C948E6F4B0AC9AA01481CCEBF7570AFEC582897E7725122D6
dns2.example.com. 3600 A 192.0.2.1
;; Zone dump (Knot DNS 2.5.0-dev)
example.com. 3600 SOA dns2.example.com. hostmaster.example.com. 2010135808 10800 3600 1209600 7200
example.com. 3600 NS dns2.example.com.
example.com. 3600 MX 10 mail.example.com.
example.com. 0 NSEC3PARAM 1 0 250 662455DF6C5AB542
example.com. 3600 DNSKEY 256 3 8 AwEAAdKraxDdGTL4HDOkXTDI1Md1UdHuYhVwYkB+u2umVjTJ1H9Qb2oBryqwXI+gklnuCqrH1znkDvzGEAeHRQUCbtKbjmqErTAcRRHW3D+6jsOGXzbyGCfbyzRBwsbNCLWr3ONpPi5JOWEeCUJfyc/mRXcmh5uYl1JvzAM1zprtljZt
example.com. 3600 DNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 DNSKEY 257 3 8 AwEAAetE6qfN/GbtMmvM0PXUTyskauES2FKfjqLVz7EQlfS8iAFWLi1eHjHXDkueZ1OYRzQ4IBy6MIsce4XVXLQoS8njtfaU7c5NZvktH5la7JuH32KYr3PdWL5KDsUdED3GSxfNV+DbcYU80AZxTxy6Bm6EP+DztL1dpYrmqr8JRl+qlSbmLIrPemZFUEQzhiepcYMWviDUz+ixSVzjEzpMCLsrNxA30Ziiq9GKA8KKlFHdAmxuNcH0TzRndpo6bu5nKyJHiREIazHVuPBEzUmHtcWETCDs9UVsbji2Z2ozqLz9cqnfYV/kOD+OZBAqvZ0n/4lgdSiBtvByLCXoWEYIGRs=
example.com. 3600 CDNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 CDS 53851 4 2 6F8129D687EC387C948E6F4B0AC9AA01481CCEBF7570AFEC582897E7725122D6
dns2.example.com. 3600 A 192.0.2.1
;; Zone dump (Knot DNS 2.5.0-dev)
example.com. 3600 SOA dns2.example.com. hostmaster.example.com. 2010135808 10800 3600 1209600 7200
example.com. 3600 NS dns2.example.com.
example.com. 3600 MX 10 mail.example.com.
example.com. 0 NSEC3PARAM 1 0 250 662455DF6C5AB542
example.com. 3600 DNSKEY 256 3 8 AwEAAdKraxDdGTL4HDOkXTDI1Md1UdHuYhVwYkB+u2umVjTJ1H9Qb2oBryqwXI+gklnuCqrH1znkDvzGEAeHRQUCbtKbjmqErTAcRRHW3D+6jsOGXzbyGCfbyzRBwsbNCLWr3ONpPi5JOWEeCUJfyc/mRXcmh5uYl1JvzAM1zprtljZt
example.com. 3600 DNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 DNSKEY 257 3 8 AwEAAetE6qfN/GbtMmvM0PXUTyskauES2FKfjqLVz7EQlfS8iAFWLi1eHjHXDkueZ1OYRzQ4IBy6MIsce4XVXLQoS8njtfaU7c5NZvktH5la7JuH32KYr3PdWL5KDsUdED3GSxfNV+DbcYU80AZxTxy6Bm6EP+DztL1dpYrmqr8JRl+qlSbmLIrPemZFUEQzhiepcYMWviDUz+ixSVzjEzpMCLsrNxA30Ziiq9GKA8KKlFHdAmxuNcH0TzRndpo6bu5nKyJHiREIazHVuPBEzUmHtcWETCDs9UVsbji2Z2ozqLz9cqnfYV/kOD+OZBAqvZ0n/4lgdSiBtvByLCXoWEYIGRs=
example.com. 3600 CDS 53851 8 2 6F8129D687EC387C948E6F4B0AC9AA01481CCEBF7570AFEC582897E7725122D6
dns2.example.com. 3600 A 192.0.2.1
;; Zone dump (Knot DNS 2.5.0-dev)
example.com. 3600 SOA dns2.example.com. hostmaster.example.com. 2010135808 10800 3600 1209600 7200
example.com. 3600 NS dns2.example.com.
example.com. 3600 MX 10 mail.example.com.
example.com. 0 NSEC3PARAM 1 0 250 662455DF6C5AB542
example.com. 3600 DNSKEY 256 3 8 AwEAAdKraxDdGTL4HDOkXTDI1Md1UdHuYhVwYkB+u2umVjTJ1H9Qb2oBryqwXI+gklnuCqrH1znkDvzGEAeHRQUCbtKbjmqErTAcRRHW3D+6jsOGXzbyGCfbyzRBwsbNCLWr3ONpPi5JOWEeCUJfyc/mRXcmh5uYl1JvzAM1zprtljZt
example.com. 3600 DNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 DNSKEY 257 3 8 AwEAAetE6qfN/GbtMmvM0PXUTyskauES2FKfjqLVz7EQlfS8iAFWLi1eHjHXDkueZ1OYRzQ4IBy6MIsce4XVXLQoS8njtfaU7c5NZvktH5la7JuH32KYr3PdWL5KDsUdED3GSxfNV+DbcYU80AZxTxy6Bm6EP+DztL1dpYrmqr8JRl+qlSbmLIrPemZFUEQzhiepcYMWviDUz+ixSVzjEzpMCLsrNxA30Ziiq9GKA8KKlFHdAmxuNcH0TzRndpo6bu5nKyJHiREIazHVuPBEzUmHtcWETCDs9UVsbji2Z2ozqLz9cqnfYV/kOD+OZBAqvZ0n/4lgdSiBtvByLCXoWEYIGRs=
example.com. 3600 CDNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
dns2.example.com. 3600 A 192.0.2.1
;; Zone dump (Knot DNS 2.5.0-dev)
example.com. 3600 SOA dns2.example.com. hostmaster.example.com. 2010135808 10800 3600 1209600 7200
example.com. 3600 NS dns2.example.com.
example.com. 3600 MX 10 mail.example.com.
example.com. 0 NSEC3PARAM 1 0 250 662455DF6C5AB542
example.com. 3600 DNSKEY 256 3 8 AwEAAdKraxDdGTL4HDOkXTDI1Md1UdHuYhVwYkB+u2umVjTJ1H9Qb2oBryqwXI+gklnuCqrH1znkDvzGEAeHRQUCbtKbjmqErTAcRRHW3D+6jsOGXzbyGCfbyzRBwsbNCLWr3ONpPi5JOWEeCUJfyc/mRXcmh5uYl1JvzAM1zprtljZt
example.com. 3600 DNSKEY 257 3 8 AwEAAetE6qfN/GbtMmvM0PXUTyskauES2FKfjqLVz7EQlfS8iAFWLi1eHjHXDkueZ1OYRzQ4IBy6MIsce4XVXLQoS8njtfaU7c5NZvktH5la7JuH32KYr3PdWL5KDsUdED3GSxfNV+DbcYU80AZxTxy6Bm6EP+DztL1dpYrmqr8JRl+qlSbmLIrPemZFUEQzhiepcYMWviDUz+ixSVzjEzpMCLsrNxA30Ziiq9GKA8KKlFHdAmxuNcH0TzRndpo6bu5nKyJHiREIazHVuPBEzUmHtcWETCDs9UVsbji2Z2ozqLz9cqnfYV/kOD+OZBAqvZ0n/4lgdSiBtvByLCXoWEYIGRs=
example.com. 3600 CDNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 CDS 53851 8 2 6F8129D687EC387C948E6F4B0AC9AA01481CCEBF7570AFEC582897E7725122D6
dns2.example.com. 3600 A 192.0.2.1
;; Zone dump (Knot DNS 2.5.0-dev)
example.com. 3600 SOA dns2.example.com. hostmaster.example.com. 2010135808 10800 3600 1209600 7200
example.com. 3600 NS dns2.example.com.
example.com. 3600 MX 10 mail.example.com.
example.com. 0 NSEC3PARAM 1 0 250 662455DF6C5AB542
example.com. 3600 DNSKEY 256 3 8 AwEAAdKraxDdGTL4HDOkXTDI1Md1UdHuYhVwYkB+u2umVjTJ1H9Qb2oBryqwXI+gklnuCqrH1znkDvzGEAeHRQUCbtKbjmqErTAcRRHW3D+6jsOGXzbyGCfbyzRBwsbNCLWr3ONpPi5JOWEeCUJfyc/mRXcmh5uYl1JvzAM1zprtljZt
example.com. 3600 DNSKEY 257 3 8 AwEAAcQ1EqTPebcJyUnpxO3Xjx6ehRtsiZYToARoJsJG12XR6Ci9yy4SCCsejtaWIFO4XVfM2BHzFWqmABtQHtN7AazXAFMLsrSE4DYbgk5WmnQv5Jloi6jhhmmXwr8EOi3HR2jdG0gVq/Tax7ztNNZsflJrs3rZs2TVO00BkyyOkmO35jCNbGPUwm5cW1vse137BMa7jAcMyNLPIiQubj1/mJcIyzF2duvfpjBTgEmSvNcXqLfYFjK8lG4NodQG8AcK0MvWqN4mxW/hK0U9nMSjhCnfzPg5tjyqdheWRyhkLGjM/mR7gBhtqoSPMr+2KMJQEHYAd/AP8YgaovS8N1fJyh0=
example.com. 3600 DNSKEY 257 3 8 AwEAAetE6qfN/GbtMmvM0PXUTyskauES2FKfjqLVz7EQlfS8iAFWLi1eHjHXDkueZ1OYRzQ4IBy6MIsce4XVXLQoS8njtfaU7c5NZvktH5la7JuH32KYr3PdWL5KDsUdED3GSxfNV+DbcYU80AZxTxy6Bm6EP+DztL1dpYrmqr8JRl+qlSbmLIrPemZFUEQzhiepcYMWviDUz+ixSVzjEzpMCLsrNxA30Ziiq9GKA8KKlFHdAmxuNcH0TzRndpo6bu5nKyJHiREIazHVuPBEzUmHtcWETCDs9UVsbji2Z2ozqLz9cqnfYV/kOD+OZBAqvZ0n/4lgdSiBtvByLCXoWEYIGRs=