RPZ: implement stubs for rpz-tcp-only actions.

This commit is contained in:
mb 2020-10-29 15:58:13 +01:00
parent d104727c91
commit dd70c2ef9a
6 changed files with 111 additions and 18 deletions

View file

@ -807,7 +807,6 @@ respip_nodata_answer(uint16_t qtype, enum respip_action action,
* is explicitly specified. */ * is explicitly specified. */
int rcode = (action == respip_always_nxdomain)? int rcode = (action == respip_always_nxdomain)?
LDNS_RCODE_NXDOMAIN:LDNS_RCODE_NOERROR; LDNS_RCODE_NXDOMAIN:LDNS_RCODE_NOERROR;
/* We should empty the answer section except for any preceding /* We should empty the answer section except for any preceding
* CNAMEs (in that case rrset_id > 0). Type-ANY case is * CNAMEs (in that case rrset_id > 0). Type-ANY case is
* special as noted in respip_data_answer(). */ * special as noted in respip_data_answer(). */

View file

@ -1514,6 +1514,15 @@ local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo,
return (lr == NULL); return (lr == NULL);
} }
static inline int
local_zone_is_udp_query(struct comm_reply* repinfo) {
return repinfo != NULL
? (repinfo->c != NULL
? repinfo->c->type == comm_udp
: 0)
: 0;
}
int int
local_zones_zone_answer(struct local_zone* z, struct module_env* env, local_zones_zone_answer(struct local_zone* z, struct module_env* env,
struct query_info* qinfo, struct edns_data* edns, struct query_info* qinfo, struct edns_data* edns,
@ -1536,7 +1545,9 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
lz_type == local_zone_redirect || lz_type == local_zone_redirect ||
lz_type == local_zone_inform_redirect || lz_type == local_zone_inform_redirect ||
lz_type == local_zone_always_nxdomain || lz_type == local_zone_always_nxdomain ||
lz_type == local_zone_always_nodata) { lz_type == local_zone_always_nodata ||
(lz_type == local_zone_truncate
&& local_zone_is_udp_query(repinfo))) {
/* for static, reply nodata or nxdomain /* for static, reply nodata or nxdomain
* for redirect, reply nodata */ * for redirect, reply nodata */
/* no additional section processing, /* no additional section processing,
@ -1546,8 +1557,10 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
*/ */
int rcode = (ld || lz_type == local_zone_redirect || int rcode = (ld || lz_type == local_zone_redirect ||
lz_type == local_zone_inform_redirect || lz_type == local_zone_inform_redirect ||
lz_type == local_zone_always_nodata)? lz_type == local_zone_always_nodata ||
lz_type == local_zone_truncate)?
LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN; LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
rcode = lz_type == local_zone_truncate ? (rcode|BIT_TC) : rcode;
if(z->soa) if(z->soa)
return local_encode(qinfo, env, edns, repinfo, buf, temp, return local_encode(qinfo, env, edns, repinfo, buf, temp,
z->soa, 0, rcode); z->soa, 0, rcode);
@ -1763,6 +1776,7 @@ const char* local_zone_type2str(enum localzone_type t)
case local_zone_always_nodata: return "always_nodata"; case local_zone_always_nodata: return "always_nodata";
case local_zone_always_deny: return "always_deny"; case local_zone_always_deny: return "always_deny";
case local_zone_noview: return "noview"; case local_zone_noview: return "noview";
case local_zone_truncate: return "truncate";
case local_zone_invalid: return "invalid"; case local_zone_invalid: return "invalid";
} }
return "badtyped"; return "badtyped";
@ -1800,6 +1814,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
*t = local_zone_always_deny; *t = local_zone_always_deny;
else if(strcmp(type, "noview") == 0) else if(strcmp(type, "noview") == 0)
*t = local_zone_noview; *t = local_zone_noview;
else if(strcmp(type, "truncate") == 0)
*t = local_zone_truncate;
else if(strcmp(type, "nodefault") == 0) else if(strcmp(type, "nodefault") == 0)
*t = local_zone_nodefault; *t = local_zone_nodefault;
else return 0; else return 0;

View file

@ -98,6 +98,8 @@ enum localzone_type {
local_zone_always_deny, local_zone_always_deny,
/** answer not from the view, but global or no-answer */ /** answer not from the view, but global or no-answer */
local_zone_noview, local_zone_noview,
/** truncate the response; client should retry via tcp */
local_zone_truncate,
/** Invalid type, cannot be used to generate answer */ /** Invalid type, cannot be used to generate answer */
local_zone_invalid local_zone_invalid
}; };
@ -556,6 +558,8 @@ enum respip_action {
respip_always_nodata = local_zone_always_nodata, respip_always_nodata = local_zone_always_nodata,
/** answer with nodata response */ /** answer with nodata response */
respip_always_deny = local_zone_always_deny, respip_always_deny = local_zone_always_deny,
/** RPZ: truncate answer in order to force switch to tcp */
respip_truncate = local_zone_truncate,
/* The rest of the values are only possible as /* The rest of the values are only possible as
* access-control-tag-action */ * access-control-tag-action */

View file

@ -213,8 +213,8 @@ rpz_action_to_localzone_type(enum rpz_action a)
case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent; case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent;
case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect; case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect;
case RPZ_TCP_ONLY_ACTION: return local_zone_truncate;
case RPZ_INVALID_ACTION: /* fallthrough */ case RPZ_INVALID_ACTION: /* fallthrough */
case RPZ_TCP_ONLY_ACTION: /* fallthrough */
default: return local_zone_invalid; default: return local_zone_invalid;
} }
} }
@ -229,8 +229,8 @@ rpz_action_to_respip_action(enum rpz_action a)
case RPZ_PASSTHRU_ACTION: return respip_always_transparent; case RPZ_PASSTHRU_ACTION: return respip_always_transparent;
case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect; case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect;
case RPZ_TCP_ONLY_ACTION: return respip_truncate;
case RPZ_INVALID_ACTION: /* fallthrough */ case RPZ_INVALID_ACTION: /* fallthrough */
case RPZ_TCP_ONLY_ACTION: /* fallthrough */
default: return respip_invalid; default: return respip_invalid;
} }
} }
@ -244,6 +244,7 @@ localzone_type_to_rpz_action(enum localzone_type lzt)
case local_zone_always_deny: return RPZ_DROP_ACTION; case local_zone_always_deny: return RPZ_DROP_ACTION;
case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION; case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION;
case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION; case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION;
case local_zone_truncate: return RPZ_TCP_ONLY_ACTION;
case local_zone_invalid: case local_zone_invalid:
default: default:
return RPZ_INVALID_ACTION; return RPZ_INVALID_ACTION;
@ -259,6 +260,7 @@ respip_action_to_rpz_action(enum respip_action a)
case respip_always_deny: return RPZ_DROP_ACTION; case respip_always_deny: return RPZ_DROP_ACTION;
case respip_always_transparent: return RPZ_PASSTHRU_ACTION; case respip_always_transparent: return RPZ_PASSTHRU_ACTION;
case respip_redirect: return RPZ_LOCAL_DATA_ACTION; case respip_redirect: return RPZ_LOCAL_DATA_ACTION;
case respip_truncate: return RPZ_TCP_ONLY_ACTION;
case respip_invalid: case respip_invalid:
default: default:
return RPZ_INVALID_ACTION; return RPZ_INVALID_ACTION;
@ -478,13 +480,17 @@ rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
char* rrstr; char* rrstr;
int newzone = 0; int newzone = 0;
if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION) { if(a == RPZ_INVALID_ACTION) {
verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s", verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s",
rpz_action_to_string(a)); rpz_action_to_string(a));
free(dname); free(dname);
return; return;
} }
if(a == RPZ_TCP_ONLY_ACTION) {
verbose(VERB_ALGO, "RPZ: insert qname trigger: tcp-only");
}
lock_rw_wrlock(&r->local_zones->lock); lock_rw_wrlock(&r->local_zones->lock);
/* exact match */ /* exact match */
z = local_zones_find(r->local_zones, dname, dnamelen, dnamelabs, z = local_zones_find(r->local_zones, dname, dnamelen, dnamelabs,
@ -550,13 +556,16 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
char* rrstr; char* rrstr;
enum respip_action respa = rpz_action_to_respip_action(a); enum respip_action respa = rpz_action_to_respip_action(a);
if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION || if(a == RPZ_INVALID_ACTION || respa == respip_invalid) {
respa == respip_invalid) {
verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s", verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s",
rpz_action_to_string(a)); rpz_action_to_string(a));
return 0; return 0;
} }
if(a == RPZ_TCP_ONLY_ACTION) {
verbose(VERB_ALGO, "RPZ: insert respip trigger: tcp-only");
}
if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
return 0; return 0;
@ -984,6 +993,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
lock_rw_unlock(&a->lock); /* not found in this auth_zone */ lock_rw_unlock(&a->lock); /* not found in this auth_zone */
} }
lock_rw_unlock(&az->rpz_lock); lock_rw_unlock(&az->rpz_lock);
if(!z) if(!z)
return 0; /* not holding auth_zone.lock anymore */ return 0; /* not holding auth_zone.lock anymore */
@ -1032,7 +1042,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
lock_rw_unlock(&a->lock); lock_rw_unlock(&a->lock);
return !qinfo->local_alias; return !qinfo->local_alias;
} }
verbose(VERB_ALGO, "xxxxxx repinfo=%p is_udp=%d", repinfo, repinfo->c->type == comm_udp);
ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
0 /* no local data used */, lzt); 0 /* no local data used */, lzt);
if(r->log) if(r->log)

View file

@ -38,6 +38,7 @@ d TXT "local data 2nd zone"
e CNAME *.a.example. e CNAME *.a.example.
*.e CNAME *.b.example. *.e CNAME *.b.example.
drop CNAME rpz-drop. drop CNAME rpz-drop.
tcp CNAME rpz-tcp-only.
TEMPFILE_END TEMPFILE_END
stub-zone: stub-zone:
@ -295,10 +296,45 @@ something.e.b.example. IN TXT "*.b.example. answer from upstream ns"
ENTRY_END ENTRY_END
; deny zone ; deny zone
STEP 90 QUERY ;STEP 90 QUERY
;ENTRY_BEGIN
;SECTION QUESTION
;drop. IN TXT
;ENTRY_END
; tcp-only action
STEP 95 QUERY
ENTRY_BEGIN ENTRY_BEGIN
SECTION QUESTION SECTION QUESTION
drop. IN TXT tcp. IN TXT
ENTRY_END ENTRY_END
STEP 96 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA AA TC NOERROR
SECTION QUESTION
tcp. IN TXT
SECTION ANSWER
ENTRY_END
STEP 97 QUERY
ENTRY_BEGIN
MATCH TCP
SECTION QUESTION
tcp. IN TXT
ENTRY_END
STEP 98 CHECK_ANSWER
ENTRY_BEGIN
MATCH all TCP
REPLY QR RD RA AA NOERROR
SECTION QUESTION
tcp. IN TXT
SECTION ANSWER
tcp. IN TXT "local tcp data 2nd zone"
ENTRY_END
; no answer is checked at exit of testbound. ; no answer is checked at exit of testbound.
SCENARIO_END SCENARIO_END

View file

@ -20,6 +20,7 @@ $ORIGIN rpz.example.com.
16.0.0.10.10.rpz-ip CNAME . 16.0.0.10.10.rpz-ip CNAME .
24.0.10.10.10.rpz-ip CNAME rpz-drop. 24.0.10.10.10.rpz-ip CNAME rpz-drop.
32.10.10.10.10.rpz-ip CNAME rpz-passthru. 32.10.10.10.10.rpz-ip CNAME rpz-passthru.
32.1.1.1.10.rpz-ip CNAME rpz-tcp-only.
32.zz.db8.2001.rpz-ip CNAME *. 32.zz.db8.2001.rpz-ip CNAME *.
48.zz.aa.db8.2001.rpz-ip CNAME . 48.zz.aa.db8.2001.rpz-ip CNAME .
64.zz.bb.aa.db8.2001.rpz-ip CNAME rpz-drop. 64.zz.bb.aa.db8.2001.rpz-ip CNAME rpz-drop.
@ -217,6 +218,16 @@ SECTION ANSWER
h. IN AAAA 2001:db8:aa:bb:cc::124 h. IN AAAA 2001:db8:aa:bb:cc::124
ENTRY_END ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
y. IN A
SECTION ANSWER
y. IN A 10.1.1.1
ENTRY_END
RANGE_END RANGE_END
STEP 1 QUERY STEP 1 QUERY
@ -446,4 +457,21 @@ SECTION QUESTION
e. IN AAAA e. IN AAAA
ENTRY_END ENTRY_END
STEP 29 TIME_PASSES ELAPSE 12 STEP 29 TIME_PASSES ELAPSE 12
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
y. IN A
ENTRY_END
STEP 31 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR TC RD RA NOERROR
SECTION QUESTION
y. IN A
SECTION ANSWER
ENTRY_END
SCENARIO_END SCENARIO_END