From: Marek Vavrusa Date: Mon, 18 Apr 2016 03:34:31 +0000 (-0700) Subject: daemon: mode(strict|normal|permissive) X-Git-Tag: v1.0.0~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e61c48efba458d0997efb9a79943d01bbf1d692b;p=thirdparty%2Fknot-resolver.git daemon: mode(strict|normal|permissive) the daemon has now three modes of strictness checking from strict to permissive. it reflects the tradeoff between resolving the query in as few steps as possible and security for insecure zones --- diff --git a/daemon/README.rst b/daemon/README.rst index 952d12ba6..794e7f496 100644 --- a/daemon/README.rst +++ b/daemon/README.rst @@ -335,6 +335,23 @@ Environment :return: Toggle verbose logging. +.. function:: mode('strict' | 'normal' | 'permissive') + + :return: Change resolver strictness checking level. + + By default, resolver runs in *normal* mode. There are possibly many small adjustments + hidden behind the mode settings, but the main idea is that in *permissive* mode, the resolver + tries to resolve a name with as few lookups as possible, while in *strict* mode it spends much + more effort resolving and checking referral path. However, if majority of the traffic is covered + by DNSSEC, some of the strict checking actions are counter-productive. + + .. csv-table:: + :header: "Action", "Modes" + + "Use mandatory glue", "strict, normal, permissive" + "Use in-bailiwick glue", "normal, permissive" + "Use any glue records", "permissive" + .. function:: user(name, [group]) :param string name: user name diff --git a/daemon/engine.c b/daemon/engine.c index 4c0e0c50c..70fda1156 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -66,6 +66,7 @@ static int l_help(lua_State *L) "user(name[, group])\n change process user (and group)\n" "verbose(true|false)\n toggle verbose mode\n" "option(opt[, new_val])\n get/set server option\n" + "mode(strict|normal|permissive)\n set resolver strictness level\n" "resolve(name, type[, class, flags, callback])\n resolve query, callback when it's finished\n" "todname(name)\n convert name to wire format\n" "net\n network configuration\n" diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua index 0db2790da..f633d9b87 100644 --- a/daemon/lua/kres.lua +++ b/daemon/lua/kres.lua @@ -106,6 +106,8 @@ struct query_flag { static const int DNSSEC_INSECURE = 1 << 16; static const int STUB = 1 << 17; static const int ALWAYS_CUT = 1 << 18; + static const int PERMISSIVE = 1 << 20; + static const int STRICT = 1 << 21; }; /* diff --git a/daemon/lua/sandbox.lua b/daemon/lua/sandbox.lua index 320e93f7f..d1ca36633 100644 --- a/daemon/lua/sandbox.lua +++ b/daemon/lua/sandbox.lua @@ -18,6 +18,19 @@ if rawget(kres, 'str2dname') ~= nil then todname = kres.str2dname end +-- Resolver mode of operation +local current_mode = 'normal' +local mode_table = { normal=0, strict=1, permissive=2 } +function mode(m) + if not m then return current_mode end + if not mode_table[m] then error('unsupported mode: '..m) end + -- Update current operation mode + current_mode = m + option('STRICT', current_mode == 'strict') + option('PERMISSIVE', current_mode == 'permissive') + return true +end + -- Function aliases -- `env.VAR returns os.getenv(VAR)` env = {} diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c index 6a0393264..d28184597 100644 --- a/lib/layer/iterate.c +++ b/lib/layer/iterate.c @@ -173,17 +173,26 @@ static int update_answer(const knot_rrset_t *rr, unsigned hint, knot_pkt_t *answ return KNOT_STATE_DONE; } -static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, struct kr_query *qry) +static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, struct kr_request *req) { + bool used_glue = false; for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) { const knot_pktsection_t *sec = knot_pkt_section(pkt, i); for (unsigned k = 0; k < sec->count; ++k) { const knot_rrset_t *rr = knot_pkt_rr(sec, k); if (knot_dname_is_equal(ns, rr->owner)) { - (void) update_nsaddr(rr, qry); + (void) update_nsaddr(rr, req->current_query); + used_glue = true; } } } + WITH_DEBUG { + char name_str[KNOT_DNAME_MAXLEN]; + knot_dname_to_str(name_str, ns, sizeof(name_str)); + if (used_glue) { + DEBUG_MSG("<= using glue for '%s'\n", name_str); + } + } } /** Attempt to find glue for given nameserver name (best effort). */ @@ -252,9 +261,17 @@ static int update_cut(knot_pkt_t *pkt, const knot_rrset_t *rr, struct kr_request continue; } kr_zonecut_add(cut, ns_name, NULL); - /* Use glue only in permissive mode or when in bailiwick. */ - if ((qry->flags & QUERY_PERMISSIVE) || knot_dname_in(current_cut, ns_name)) { - fetch_glue(pkt, ns_name, qry); + /* Choose when to use glue records. */ + if (qry->flags & QUERY_PERMISSIVE) { + fetch_glue(pkt, ns_name, req); + } else if (qry->flags & QUERY_STRICT) { + /* Strict mode uses only mandatory glue. */ + if (knot_dname_in(cut->name, ns_name)) + fetch_glue(pkt, ns_name, req); + } else { + /* Normal mode uses in-bailiwick glue. */ + if (knot_dname_in(current_cut, ns_name)) + fetch_glue(pkt, ns_name, req); } } diff --git a/lib/rplan.h b/lib/rplan.h index 69a58fa3b..a804658b1 100644 --- a/lib/rplan.h +++ b/lib/rplan.h @@ -45,7 +45,8 @@ X(STUB, 1 << 17) /**< Stub resolution, accept received answer as solved. */ \ X(ALWAYS_CUT, 1 << 18) /**< Always recover zone cut (even if cached). */ \ X(DNSSEC_WEXPAND, 1 << 19) /**< Query response has wildcard expansion. */ \ - X(PERMISSIVE, 1 << 20) /**< Permissive referral path resolution. */ + X(PERMISSIVE, 1 << 20) /**< Permissive resolver mode. */ \ + X(STRICT, 1 << 21) /**< Strict resolver mode. */ /** Query flags */ enum kr_query_flag {