From: Ralph Dolmans Date: Fri, 22 Nov 2019 04:56:24 +0000 (+0800) Subject: processing RPZ review feedback X-Git-Tag: release-1.10.0rc1~28^2~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bbb737ca5a3ed357fbe0736b2db625aa13a45b9d;p=thirdparty%2Funbound.git processing RPZ review feedback --- diff --git a/doc/example.conf.in b/doc/example.conf.in index bd6c0e03e..b30dca513 100644 --- a/doc/example.conf.in +++ b/doc/example.conf.in @@ -1009,12 +1009,15 @@ remote-control: # Response Policy Zones # RPZ policies. Applied in order of configuration. QNAME and Response IP # Address trigger are the only supported triggers. Supported actions are: -# NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. Polices can be loaded from -# file or using zone transfer. The respip module needs to be added to the -# module-config, e.g.: module-config: "respip validator iterator". +# NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. Policies can be loaded from +# file, using zone transfer, or using HTTP. The respip module needs to be added +# to the module-config, e.g.: module-config: "respip validator iterator". # rpz: # name: "rpz.example.com" # zonefile: "rpz.example.com" +# master: 192.0.2.0 +# allow-notify: 192.0.2.0/32 +# url: http://www.example.com/rpz.example.org.zone # rpz-action-override: cname # rpz-cname-override: www.example.org # rpz-log: yes diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index 6ea40009c..37f88abf7 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -660,6 +660,11 @@ Number of queries that got an answer that contained EDNS client subnet data. Number of queries answered from the edns client subnet cache. These are counted as cachemiss by the main counters, but hit the client subnet specific cache, after getting processed by the edns client subnet module. +.TP +.I num.rpz.action. +Number of queries answered using configured RPZ policy, per RPZ action type. +Possible actions are: nxdomain, nodata, passthru, drop, local_data, disabled, +and cname_override. .SH "FILES" .TP .I @ub_conf_file@ diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index 0a7e75db4..3a649f450 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -2100,6 +2100,17 @@ Name of the authority zone. Where to download a copy of the zone from, with AXFR and IXFR. Multiple masters can be specified. They are all tried if one fails. .TP +.B url: \fI +Where to download a zonefile for the zone. With http or https. An example +for the url is "http://www.example.com/example.org.zone". Multiple url +statements can be given, they are tried in turn. If only urls are given +the SOA refresh timer is used to wait for making new downloads. If also +masters are listed, the masters are first probed with UDP SOA queries to +see if the SOA serial number has changed, reducing the number of downloads. +If none of the urls work, the masters are tried with IXFR and AXFR. +For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used +to authenticate the connection. +.TP .B allow\-notify: \fI With allow\-notify you can specify additional sources of notifies. When notified, the server attempts to first probe and then zone transfer. @@ -2122,7 +2133,7 @@ The CNAME target domain to use if the cname action is configured for \fBrpz\-action\-override\fR. .TP .B rpz\-log: \fI -Log all applied RPZ actions. Default is no. +Log all applied RPZ actions for this RPZ zone. Default is no. .TP .B rpz\-log\-name: \fI Specify a string to be part of the log line, for easy referencing. diff --git a/libunbound/context.c b/libunbound/context.c index d96722263..6d62e32b5 100644 --- a/libunbound/context.c +++ b/libunbound/context.c @@ -55,7 +55,7 @@ int context_finalize(struct ub_ctx* ctx) { - int is_rpz; + int is_rpz = 0; struct config_file* cfg = ctx->env->cfg; verbosity = cfg->verbosity; if(ctx_logfile_overridden && !ctx->logfile_override) { diff --git a/respip/respip.c b/respip/respip.c index 5da60ad0e..e9baa6292 100644 --- a/respip/respip.c +++ b/respip/respip.c @@ -845,10 +845,11 @@ static int respip_use_rpz(struct resp_addr* raddr, struct rpz* r, enum respip_action* action, struct ub_packed_rrset_key** data, int* rpz_log, char** log_name, - int* rpz_cname_override, struct regional* region) + int* rpz_cname_override, struct regional* region, int* is_rpz) { if(r->action_override == RPZ_DISABLED_ACTION) { - return 0; + *is_rpz = 0; + return 1; } else if(r->action_override == RPZ_NO_OVERRIDE_ACTION) *action = raddr->action; @@ -861,7 +862,9 @@ respip_use_rpz(struct resp_addr* raddr, struct rpz* r, } *rpz_log = r->log; if(r->log_name) - *log_name = regional_strdup(region, r->log_name); + if(!(*log_name = regional_strdup(region, r->log_name))) + return 0; + *is_rpz = 1; return 1; } @@ -945,12 +948,16 @@ respip_rewrite_reply(const struct query_info* qinfo, if(raddr) { if(!respip_use_rpz(raddr, r, &action, &data, &rpz_log, &log_name, &rpz_cname_override, - region)) { + region, &rpz_used)) { + log_err("out of memory"); + lock_rw_unlock(&raddr->lock); + return 0; + } + if(!rpz_used) { lock_rw_unlock(&raddr->lock); raddr = NULL; actinfo->rpz_disabled++; } - rpz_used = 1; } } } @@ -1263,7 +1270,7 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname, unsigned port; struct respip_addr_info* respip_addr = respip_actinfo->addrinfo; size_t txtlen = 0; - char* actionstr = NULL; + const char* actionstr = NULL; if(local_alias) qname = local_alias->rrset->rk.dname; @@ -1277,12 +1284,12 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname, txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s", "RPZ applied "); if(respip_actinfo->rpz_cname_override) - actionstr = strdup( - rpz_action_to_string(RPZ_CNAME_OVERRIDE_ACTION)); + actionstr = rpz_action_to_string( + RPZ_CNAME_OVERRIDE_ACTION); else - actionstr = strdup(rpz_action_to_string( + actionstr = rpz_action_to_string( respip_action_to_rpz_action( - respip_actinfo->action))); + respip_actinfo->action)); } if(respip_actinfo->log_name) { txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, @@ -1291,7 +1298,5 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname, snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s/%d %s %s@%u", respip, respip_addr->net, (actionstr) ? actionstr : "inform", srcip, port); - if(actionstr) - free(actionstr); log_nametypeclass(0, txt, qname, qtype, qclass); } diff --git a/respip/respip.h b/respip/respip.h index 4a56b8d29..bbd471421 100644 --- a/respip/respip.h +++ b/respip/respip.h @@ -270,7 +270,7 @@ respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* socklen_t addrlen, int net, int create, const char* ipstr); /** - * Add RR to resp_addr's RRset. Create RRset is not existing. + * Add RR to resp_addr's RRset. Create RRset if not existing. * @param region: region to alloc RR(set). * @param raddr: resp_addr containing RRset. Must hold write lock. * @param rrtype: RR type. @@ -290,7 +290,7 @@ respip_enter_rr(struct regional* region, struct resp_addr* raddr, /** * Delete resp_addr node from tree. * @param set: struct containing tree. Must hold write lock. - * @param node: node to delete. Must hold write lock. + * @param node: node to delete. Not locked. */ void respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node); diff --git a/services/rpz.c b/services/rpz.c index b9fc03211..d36f2268e 100644 --- a/services/rpz.c +++ b/services/rpz.c @@ -791,12 +791,9 @@ rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, enum rpz_action a, delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl, rdatalen); } - if(delete_respip) { - /* delete + reset parent pointers */ + lock_rw_unlock(&node->lock); + if(delete_respip) respip_sockaddr_delete(r->respip_set, node); - } else { - lock_rw_unlock(&node->lock); - } lock_rw_unlock(&r->respip_set->lock); } diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index 01e2385fa..c5aae7a8c 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -62,6 +62,7 @@ #include "daemon/stats.h" #include "sldns/wire2str.h" #include "sldns/pkthdr.h" +#include "services/rpz.h" #ifdef HAVE_SYS_IPC_H #include "sys/ipc.h" @@ -372,6 +373,14 @@ static void print_extended(struct ub_stats_info* s) PR_UL("rrset.cache.count", s->svr.rrset_cache_count); PR_UL("infra.cache.count", s->svr.infra_cache_count); PR_UL("key.cache.count", s->svr.key_cache_count); + /* applied RPZ actions */ + for(i=0; isvr.rpz_action[i] == RPZ_NO_OVERRIDE_ACTION) + continue; + if(inhibit_zero && s->svr.rpz_action[i] == 0) + continue; + PR_UL_SUB("num.rpz.action", rpz_action_to_string(i), s->svr.rpz_action[i]); + } #ifdef USE_DNSCRYPT PR_UL("dnscrypt_shared_secret.cache.count", s->svr.shared_secret_cache_count);