summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorVladimír Čunát <vladimir.cunat@nic.cz>2023-05-19 09:09:06 +0200
committerVladimír Čunát <vladimir.cunat@nic.cz>2023-06-12 10:32:57 +0200
commit6f1d9b6140f0ec39eccbf976f4a7ad15bd9378c7 (patch)
tree4b798b65f52ad523061335688335edec90e168e4 /modules
parentlib/rules: split key construction from insert_trivial_zone() (diff)
downloadknot-resolver-6f1d9b6140f0ec39eccbf976f4a7ad15bd9378c7.tar.xz
knot-resolver-6f1d9b6140f0ec39eccbf976f4a7ad15bd9378c7.zip
lib/rules: implement forwarding
Typical use cases should work now, briefly tested: - forwarding all to a resolver - forwarding a subtree downgraded to insecure (to resolver or auth) - forwarding a subtree to auth without changing DNSSEC chain (atypical) In some places we need to repeat kr_make_query() The issue is that some of its inputs (e.g. STUB/FORWARD, zone cut) are now not known at the beginning of PRODUCE yet. Also, checking that QNAME matches is useless on a cached reply.
Diffstat (limited to 'modules')
-rw-r--r--modules/policy/policy.lua52
1 files changed, 52 insertions, 0 deletions
diff --git a/modules/policy/policy.lua b/modules/policy/policy.lua
index cc77e487..b4030375 100644
--- a/modules/policy/policy.lua
+++ b/modules/policy/policy.lua
@@ -856,6 +856,58 @@ function policy.TAGS_ASSIGN(names)
return 'policy.tags_assign_bitmap(' .. tostring(bitmap) .. ')'
end
+--[[ Insert a forwarding rule, i.e. override upstream for one DNS subtree.
+
+Throws lua exceptions when detecting something fishy.
+
+\param subtree plain string
+\param options
+ .auth targets are authoritative (false by default = resolver)
+ .tls use DoT (false by default, only for resolvers)
+ .dnssec if overridden to false, don't validate DNSSEC locally
+ - for resolvers we still do *not* send CD=1 upstream,
+ i.e. we trust their DNSSEC validation.
+ - for auths this inserts a negative trust anchor
+ Beware that setting .set_insecure() *later* would override that.
+\param targets same format as policy.TLS_FORWARD()
+--]]
+function policy.rule_forward_add(subtree, options, targets)
+ local port_default = 53
+ if options.tls or false then
+ port_default = 853
+ -- lots of code; easiest to just call it this way; checks and throws
+ policy.TLS_FORWARD(targets)
+ end
+
+ local targets_2 = {}
+ for _, target in ipairs(targets) do
+ -- this also throws on failure
+ local sock = addr2sock(target[1], port_default)
+ if options.auth then
+ local port = ffi.C.kr_inaddr_port(sock)
+ assert(not options.tls and port == port_default)
+ end
+ table.insert(targets_2, sock)
+ end
+ local targets_3 = ffi.new('const struct sockaddr * [?]', #targets_2 + 1, targets_2)
+ targets_3[#targets_2] = nil
+
+ local subtree_dname = todname(subtree)
+ assert(ffi.C.kr_rule_forward(subtree_dname,
+ { is_tcp = options.tls
+ , is_nods = options.dnssec == false
+ , is_auth = options.auth
+ },
+ targets_3
+ ) == 0)
+
+ -- Probably the best way to turn off DNSSEC validation for auth is negative TA.
+ if options.auth and options.dnssec == false then
+ local ntas = kres.context().negative_anchors
+ assert(ffi.C.kr_ta_add(ntas, subtree_dname, kres.type.DS, 0, nil, 0) == 0)
+ end
+end
+
local view_action_buf = ffi.new('knot_db_val_t[1]')