From 1c75e628041ed9c0e680002dbc82380cf1b2b3c3 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Thu, 1 Apr 2021 12:06:14 +0200 Subject: [PATCH] - rpz-triggers, separate cache storage of RPZ records from network records. --- iterator/iterator.c | 2 ++ services/rpz.c | 9 ++++++++ testdata/rpz_nsip.rpl | 49 ++++++++++++++++++++++++++++++++++++++++ util/data/packed_rrset.h | 8 +++++++ 4 files changed, 68 insertions(+) diff --git a/iterator/iterator.c b/iterator/iterator.c index 0883b91b0..7099f05da 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -2478,6 +2478,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, qstate->ext_state[id] = module_finished; qstate->return_rcode = FLAGS_GET_RCODE(forged_response->rep->flags); qstate->return_msg = forged_response; + iq->response = forged_response; next_state(iq, FINISHED_STATE); if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { log_err("rpz, prepend rrsets: out of memory"); @@ -3041,6 +3042,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, qstate->ext_state[id] = module_finished; qstate->return_rcode = FLAGS_GET_RCODE(forged_response->rep->flags); qstate->return_msg = forged_response; + iq->response = forged_response; next_state(iq, FINISHED_STATE); if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { log_err("rpz after cname, prepend rrsets: out of memory"); diff --git a/services/rpz.c b/services/rpz.c index 2ab62581a..6a37cb9b3 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -1642,6 +1642,15 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs } rp->rk.dname = qi->qname; rp->rk.dname_len = qi->qname_len; + /* this rrset is from the rpz data, or synthesized. + * It is not actually from the network, so we flag it with this + * flags as a fake RRset. If later the cache is used to look up + * rrsets, then the fake ones are not returned (if you look without + * the flag). For like CNAME lookups from the iterator or A, AAAA + * lookups for nameserver targets, it would use the without flag + * actual data. So that the actual network data and fake data + * are kept track of separately. */ + rp->rk.flags |= PACKED_RRSET_RPZ; new_reply_info->rrsets[0] = rp; msg->rep = new_reply_info; return msg; diff --git a/testdata/rpz_nsip.rpl b/testdata/rpz_nsip.rpl index ac9e80b80..11d1999b6 100644 --- a/testdata/rpz_nsip.rpl +++ b/testdata/rpz_nsip.rpl @@ -131,6 +131,18 @@ SECTION ADDITIONAL ns1.ff. IN A 8.8.6.8 ENTRY_END +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +bar. IN A +SECTION AUTHORITY +bar. IN NS gotham.ff. +SECTION ADDITIONAL +gotham.ff. IN A 192.0.5.2 +ENTRY_END + RANGE_END ; com. ----------------------------------------------------------------------- @@ -385,4 +397,41 @@ SECTION ANSWER gotham.ff. IN A 127.0.0.1 ENTRY_END +; again with more cache items +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.ff. IN A +ENTRY_END + +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION ANSWER +gotham.ff. IN A 127.0.0.1 +ENTRY_END + +; query with a referral that tries to get the +; just faked A record as nameserver glue (from cache). +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.bar. IN A +ENTRY_END + +STEP 51 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +gotham.bar. IN A +SECTION ANSWER +gotham.bar. IN A 127.0.0.1 +ENTRY_END + SCENARIO_END diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h index ff95c0af0..e1feb22bb 100644 --- a/util/data/packed_rrset.h +++ b/util/data/packed_rrset.h @@ -61,6 +61,13 @@ typedef uint64_t rrset_id_type; * updated on encoding in a reply. This flag is not expected to be set in * cached data. */ #define PACKED_RRSET_FIXEDTTL 0x80000000 +/** This rrset is from RPZ. It is not real, it is synthesized data to block + * access. The flag makes lookups, from cache in iterator, ignore the fake + * items and only use actual data. Eg. when the iterator looksup NS, CNAME, + * A and AAAA types, it then gets items without this flag that are the + * actual network. But messages with these records in it can be stored in + * the cache and retrieved for a reply. */ +#define PACKED_RRSET_RPZ 0x8 /** number of rrs and rrsets for integer overflow protection. More than * this is not really possible (64K packet has much less RRs and RRsets) in @@ -88,6 +95,7 @@ struct packed_rrset_key { * o PACKED_RRSET_PARENT_SIDE * o PACKED_RRSET_SOA_NEG * o PACKED_RRSET_FIXEDTTL (not supposed to be cached) + * o PACKED_RRSET_RPZ */ uint32_t flags; /** the rrset type in network format */ -- 2.47.3