diff --git a/doc/modules.rst b/doc/modules.rst index bb7128eb85773c3ad9d4e90c582fbb25244d7abb..349763c2364164322dbd4ab073b56acdd1491636 100644 --- a/doc/modules.rst +++ b/doc/modules.rst @@ -19,3 +19,4 @@ Knot DNS Resolver modules .. include:: ../modules/ketcd/README.rst .. include:: ../modules/cachectl/README.rst .. include:: ../modules/tinyweb/README.rst +.. include:: ../modules/dns64/README.rst diff --git a/lib/utils.h b/lib/utils.h index 279ab1f7bd1e32fbdc2f0599f4236e9dccda27e8..523f731534f4e702ce3c922a2cf5f6c2a53be7d9 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -72,9 +72,10 @@ static inline long time_diff(struct timeval *begin, struct timeval *end) { return res.tv_sec * 1000 + res.tv_usec / 1000; } -/** @internal Array types */ +/** @cond Array types */ struct kr_context; typedef array_t(knot_rrset_t *) rr_array_t; +/* @endcond */ /** @internal Next RDATA shortcut. */ #define kr_rdataset_next(rd) (rd + knot_rdata_array_size(knot_rdata_rdlen(rd))) diff --git a/modules/dns64/README.rst b/modules/dns64/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..30b434bb133b2ee2da70500b3a0e5c1ed84f5ef7 --- /dev/null +++ b/modules/dns64/README.rst @@ -0,0 +1,22 @@ +.. _mod-dns64: + +DNS64 +----- + +The module for :rfc:`6147` DNS64 AAAA-from-A record synthesis, it is used to enable client-server communication between an IPv6-only client and an IPv4-only server. See the well written `introduction`_ in the PowerDNS documentation. + +.. tip:: The A record sub-requests will be DNSSEC secured, but the synthetic AAAA records can't be. Make sure the last mile between stub and resolver is secure to avoid spoofing. + +Example configuration +^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: lua + + -- Load the module with a NAT64 address + modules = { dns64 = 'fe80::21b:77ff:0:0' } + -- Reconfigure later + dns64.config('fe80::21b:aabb:0:0') + + +.. _RPZ: https://dnsrpz.info/ +.. _introduction: https://doc.powerdns.com/md/recursor/dns64 \ No newline at end of file diff --git a/modules/dns64/dns64.lua b/modules/dns64/dns64.lua new file mode 100644 index 0000000000000000000000000000000000000000..2a98b0997bc7308a2281ceefb1d47e3821685b8c --- /dev/null +++ b/modules/dns64/dns64.lua @@ -0,0 +1,46 @@ +-- Module interface +local ffi = require('ffi') +local bit = require('bit') +local mod = {} +local MARK_DNS64 = bit.lshift(1, 31) +-- Config +function mod.config (confstr) + if confstr == nil then return end + mod.proxy = kres.str2ip(confstr) + if mod.proxy == nil then error('[dns64] "'..confstr..'" is not a valid address') end +end +-- Layers +mod.layer = { + consume = function (state, req, pkt) + pkt = kres.pkt_t(pkt) + req = kres.request_t(req) + qry = req:current() + -- Observe only authoritative answers + if mod.proxy == nil or bit.band(qry.flags, kres.query.RESOLVED) == 0 then + return state + end + -- Synthetic AAAA from marked A responses + local answer = pkt:section(kres.section.ANSWER) + if bit.band(qry.flags, MARK_DNS64) ~= 0 then -- Marked request + for i = 1, #answer do + local rr = answer[i] + -- Synthesise address + local rdata = ffi.new('char [16]') + ffi.copy(rdata, mod.proxy) + ffi.copy(rdata + 12, rr.rdata, 4) + rdata = ffi.string(rdata, 16) + -- Write to answer + req.answer:put(rr.owner, rr.ttl, rr.class, kres.type.AAAA, rdata) + end + return state + end + -- Observe AAAA NODATA responses + local is_nodata = (pkt:rcode() == kres.rcode.NOERROR) and (#answer == 0) + if pkt:qtype() == kres.type.AAAA and is_nodata and pkt:qname() == qry:name() then + local next = req:push(pkt:qname(), kres.type.A, kres.class.IN, 0, qry) + next.flags = bit.band(qry.flags, kres.query.DNSSEC_WANT) + kres.query.AWAIT_CUT + MARK_DNS64 + end + return state + end +} +return mod diff --git a/modules/dns64/dns64.mk b/modules/dns64/dns64.mk new file mode 100644 index 0000000000000000000000000000000000000000..948188cbb40b265ee62b0d30d025406d04457c8a --- /dev/null +++ b/modules/dns64/dns64.mk @@ -0,0 +1,2 @@ +dns64_SOURCES := dns64.lua +$(call make_lua_module,dns64) diff --git a/modules/modules.mk b/modules/modules.mk index c6821a344943d41683ac25a68235e5fd3727f9c5..5028924591e7350f580d95569dbcec4ddb5ead18 100644 --- a/modules/modules.mk +++ b/modules/modules.mk @@ -18,7 +18,8 @@ modules_TARGETS += ketcd \ graphite \ policy \ view \ - predict + predict \ + dns64 endif # List of Golang modules