diff options
author | Vladimír Čunát <vladimir.cunat@nic.cz> | 2023-05-19 09:09:06 +0200 |
---|---|---|
committer | Vladimír Čunát <vladimir.cunat@nic.cz> | 2023-06-12 10:32:57 +0200 |
commit | 6f1d9b6140f0ec39eccbf976f4a7ad15bd9378c7 (patch) | |
tree | 4b798b65f52ad523061335688335edec90e168e4 /modules | |
parent | lib/rules: split key construction from insert_trivial_zone() (diff) | |
download | knot-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.lua | 52 |
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]') |