Commit 20a79130 authored by Vitezslav Kriz's avatar Vitezslav Kriz Committed by Petr Špaček

time_skew: Detect time skew during kresd start.

This module is enabled by default, but disabled in Deckard tests.
parent 4f79b91d
......@@ -1226,6 +1226,10 @@ static int wrk_resolve(lua_State *L)
if (options->DNSSEC_WANT) {
knot_edns_set_do(pkt->opt_rr);
}
if (options->DNSSEC_CD) {
knot_wire_set_cd(pkt->wire);
}
if (lua_isfunction(L, 5)) {
/* Store callback in registry */
lua_pushvalue(L, 5);
......
......@@ -77,6 +77,7 @@ struct kr_qflags {
_Bool DNSSEC_WANT : 1;
_Bool DNSSEC_BOGUS : 1;
_Bool DNSSEC_INSECURE : 1;
_Bool DNSSEC_CD : 1;
_Bool STUB : 1;
_Bool ALWAYS_CUT : 1;
_Bool DNSSEC_WEXPAND : 1;
......@@ -217,6 +218,8 @@ void knot_rrset_init_empty(knot_rrset_t *);
uint32_t knot_rrset_ttl(const knot_rrset_t *);
int knot_rrset_txt_dump(const knot_rrset_t *, char **, size_t *, const knot_dump_style_t *);
int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, const knot_dump_style_t *);
uint32_t knot_rrsig_sig_expiration(const knot_rdataset_t *, size_t);
uint32_t knot_rrsig_sig_inception(const knot_rdataset_t *, size_t);
const knot_dname_t *knot_pkt_qname(const knot_pkt_t *);
uint16_t knot_pkt_qtype(const knot_pkt_t *);
uint16_t knot_pkt_qclass(const knot_pkt_t *);
......
......@@ -96,6 +96,8 @@ printf "\tchar _stub[];\n};\n"
knot_rrset_ttl
knot_rrset_txt_dump
knot_rrset_txt_dump_data
knot_rrsig_sig_expiration
knot_rrsig_sig_inception
# Packet
knot_pkt_qname
knot_pkt_qtype
......
......@@ -205,6 +205,7 @@ end
-- Load embedded modules
modules.load('ta_signal_query')
modules.load('priming')
modules.load('detect_time_skew')
-- Interactive command evaluation
function eval_cmd(line, raw)
......
......@@ -27,3 +27,4 @@ Knot DNS Resolver modules
.. include:: ../modules/dnstap/README.rst
.. include:: ../modules/ta_signal_query/README.rst
.. include:: ../modules/priming/README.rst
.. include:: ../modules/detect_time_skew/README.rst
......@@ -44,6 +44,7 @@ struct kr_qflags {
* i.e. knot_wire_set_cd(request->answer->wire). */
bool DNSSEC_BOGUS : 1; /**< Query response is DNSSEC bogus. */
bool DNSSEC_INSECURE : 1;/**< Query response is DNSSEC insecure. */
bool DNSSEC_CD : 1; /**< CD bit in query */
bool STUB : 1; /**< Stub resolution, accept received answer as solved. */
bool ALWAYS_CUT : 1; /**< Always recover zone cut (even if cached). */
bool DNSSEC_WEXPAND : 1; /**< Query response has wildcard expansion. */
......
.. _mod-detect_time_skew:
System time skew detector
-------------------------
This module compares local system time with inception and expiration time
bounds in DNSSEC signatures for `. NS` records. If the local system time is
outside of these bounds, it is likely a misconfiguration which will cause
all DNSSEC validation (and resolution) to fail.
In case of mismatch, a warning message will be logged to help with
further diagnostics.
.. warning:: Information printed by this module can be forged by a network attacker!
System administrator MUST verify values printed by this module and
fix local system time using a trusted source.
This module is useful for debugging purposes. It runs only once during resolver
start does not anything after that. It is enabled by default.
You may disable the module by appending
`modules.unload('detect_time_skew')` to your configuration.
-- Module interface
local ffi = require('ffi')
local knot = ffi.load(libknot_SONAME)
local mod = {}
local event_id = nil
-- Resolve callback
-- Check time validity of RRSIGs in priming query
-- luacheck: no unused args
local function check_time_callback(pkt, req)
pkt = kres.pkt_t(pkt)
if pkt:rcode() ~= kres.rcode.NOERROR then
warn("[detect_time_skew] cannot resolve '.' NS")
return nil
end
local valid_rrsigs = 0
local section = pkt:rrsets(kres.section.ANSWER)
local now = os.time()
local time_diff = 0
local inception = 0
local expiration = 0
for i = 1, #section do
local rr = section[i]
if rr.type == kres.type.RRSIG then
for k = 0, rr.rrs.rr_count - 1 do
inception = knot.knot_rrsig_sig_inception(rr.rrs, k)
expiration = knot.knot_rrsig_sig_expiration(rr.rrs, k)
if now > expiration then
-- possitive value = in the future
time_diff = now - expiration
elseif now < inception then
-- negative value = in the past
time_diff = now - inception
else
valid_rrsigs = valid_rrsigs + 1
end
end
end
end
if valid_rrsigs == 0 then
warn("[detect_time_skew] Local system time %q seems to be at "..
"least %u seconds in the %s. DNSSEC signatures for '.' NS "..
"are not valid %s. Please check your system clock!",
os.date("%c", now),
math.abs(time_diff),
time_diff > 0 and "future" or "past",
time_diff > 0 and "yet" or "anymore")
elseif verbose() then
log("[detect_time_skew] Local system time %q is within "..
"RRSIG validity interval <%q,%q>.", os.date("%c", now),
os.date("%c", inception), os.date("%c", expiration))
end
end
-- Make priming query and check time validty of RRSIGs.
local function check_time()
resolve(".", kres.type.NS, kres.class.IN, {"DNSSEC_WANT", "DNSSEC_CD"},
check_time_callback)
end
function mod.init()
if event_id then
error("Module is already loaded.")
else
event_id = event.after(0 , check_time)
end
end
function mod.deinit()
if event_id then
event.cancel(event_id)
event_id = nil
end
end
return mod
detect_time_skew_SOURCES := detect_time_skew.lua
$(call make_lua_module,detect_time_skew)
......@@ -34,7 +34,8 @@ modules_TARGETS += etcd \
workarounds \
version \
ta_signal_query \
priming
priming \
detect_time_skew
endif
# Make C module
......
Subproject commit fcfade5d1805b7c1151523991e4d5ea68db03f03
Subproject commit a5cd67c98836690e00ab76b7bd220023f7993ee9
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment