Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rpz #73

Merged
merged 59 commits into from
Jan 30, 2020
Merged

Rpz #73

Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b43b8d4
Merge pull request #3 from NLnetLabs/master
ralphdolmans Apr 5, 2019
9274d26
Initial RPZ commit
ralphdolmans Apr 5, 2019
c66e47c
Initial RPZ commit - now with all files
ralphdolmans Apr 5, 2019
edcf2dd
- Fix locking issue
ralphdolmans Apr 10, 2019
74f11b8
- apply chroot to auth-zone zonefile in unbound-checkconf
ralphdolmans Apr 11, 2019
186c9e8
Merge pull request #5 from NLnetLabs/master
ralphdolmans Apr 25, 2019
ba67920
- IXFR/AXFR support for RPZ
ralphdolmans Apr 25, 2019
46acf0f
Merge branch 'feature/rpz' of github.com:ralphdolmans/unbound into fe…
ralphdolmans Apr 25, 2019
83bf2fd
- locking issues
ralphdolmans Apr 25, 2019
8dac8c0
- Don't attempt an RPZ delete for unsupported actions
ralphdolmans Apr 25, 2019
a7f6886
- Make IXFR deletion more robust
ralphdolmans Apr 25, 2019
b0b6932
- Added RPZ action overrides
ralphdolmans May 16, 2019
268580f
Added RPZ log name and stats
ralphdolmans Jun 3, 2019
bc83e0b
fix double free issue
ralphdolmans Jun 4, 2019
a77c35e
Add RPZ config options to unbound.conf man page.
ralphdolmans Jun 4, 2019
3021e32
Only strdup rpz_log_name when configured
ralphdolmans Jun 5, 2019
395d83c
Procedures to parse RPZ ip address notation.
ralphdolmans Jun 24, 2019
a8d6147
- Added RPZ response IP support
ralphdolmans Jul 16, 2019
9ce7045
- Fix doxygen issue
ralphdolmans Jul 16, 2019
1c5d081
- Add RPZ response IP override option, logging, and statistics
ralphdolmans Aug 1, 2019
0987a82
Add statistics support for disabled (action override) response IP RPZ
ralphdolmans Aug 7, 2019
abbb5c0
Update RPZ man page and example.conf
ralphdolmans Aug 7, 2019
4eb7771
- Added RPZ/QNAME trigger test
ralphdolmans Aug 8, 2019
401fc15
- Extend RPZ/QNAME trigger test
ralphdolmans Aug 8, 2019
7180284
- Add RPZ/QNAME override test
ralphdolmans Aug 8, 2019
88fce79
- Add RPZ respip test
ralphdolmans Aug 12, 2019
4cbf4f4
- Add RPZ response IP override test
ralphdolmans Aug 12, 2019
965f16c
- Add RPZ AXFR test
ralphdolmans Aug 13, 2019
a16111d
Prevent potential double free
ralphdolmans Aug 16, 2019
ccb576f
- add always_deny action, use this one for RPZ
ralphdolmans Aug 23, 2019
bc39217
Don't pass along unused parameter
ralphdolmans Aug 23, 2019
2b5cd8e
Merge remote-tracking branch 'ralph/feature/rpz' into rpz
ralphdolmans Sep 9, 2019
4ac33aa
- Merge clean up
ralphdolmans Sep 9, 2019
9843b83
Merge branch 'master' into rpz
ralphdolmans Sep 9, 2019
f3dfb4d
Typo fix, reported by jpmens
ralphdolmans Sep 9, 2019
bbb737c
processing RPZ review feedback
ralphdolmans Nov 22, 2019
ae4f6a2
Proccess more review feedback
ralphdolmans Dec 23, 2019
2abaca7
- Fix dname_has_label() code review changes
ralphdolmans Dec 23, 2019
e098285
- Implement RPZ CNAME target wildcard synthesis
ralphdolmans Jan 15, 2020
14913d7
- processed RPZ review feedback
ralphdolmans Jan 15, 2020
344f12d
- fix compiler warnings
ralphdolmans Jan 15, 2020
1654373
- Fix doxygen issue
ralphdolmans Jan 15, 2020
627285a
- Fix faulty assert
ralphdolmans Jan 15, 2020
9877e52
Merge branch 'master' of github.com:NLnetLabs/unbound into rpz
ralphdolmans Jan 15, 2020
53d85f9
try to understand travis
ralphdolmans Jan 15, 2020
fd6456d
attemp to get more info out of travis
ralphdolmans Jan 15, 2020
72c4c6b
- Fix the dname_has_label fix
ralphdolmans Jan 16, 2020
24131ca
Revert travis verbosity
ralphdolmans Jan 16, 2020
b783732
- Add cname target wc synth. to testbound test
ralphdolmans Jan 16, 2020
bda4c4a
- improve dname_has_label(), add unit test
ralphdolmans Jan 16, 2020
e00ce7e
- extend rpz_respip.rpl with ipv6 without zz label case
ralphdolmans Jan 16, 2020
9df07b4
- Address review feedback
ralphdolmans Jan 28, 2020
ef12073
- Fix RPZ's get_tld_label maxdnamelen check
ralphdolmans Jan 29, 2020
1d91852
- Make dname_has_label's dnamelen check work with 0 length
ralphdolmans Jan 29, 2020
7da16fe
- Use consistent dname buffer sizes for RPZ
ralphdolmans Jan 29, 2020
88a706a
- Add extra dnamelen checks to ipdnametoaddr and netblockdnametoaddr
ralphdolmans Jan 29, 2020
3609287
- Fix RPZ stats RPZ_NO_OVERRIDE_ACTION check
ralphdolmans Jan 30, 2020
833c4b1
- Revert addition of cscope.out to project .gitignore, should be in
ralphdolmans Jan 30, 2020
b9c9fc0
- Fix RPZ locking issues on error conditions
ralphdolmans Jan 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.lo
*.o
cscope.out
/.libs/
/Makefile
/autom4te.cache/
Expand Down
357 changes: 174 additions & 183 deletions Makefile.in

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion daemon/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,8 @@ daemon_fork(struct daemon* daemon)
have_view_respip_cfg;

/* read auth zonefiles */
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1))
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
&daemon->use_rpz))
fatal_exit("auth_zones could not be setup");

/* setup modules */
Expand All @@ -631,6 +632,12 @@ daemon_fork(struct daemon* daemon)
if(daemon->use_response_ip &&
modstack_find(&daemon->mods, "respip") < 0)
fatal_exit("response-ip options require respip module");
/* RPZ response ip triggers don't work as expected without the respip
* module. To avoid run-time operational surprise we reject such
* configuration. */
if(daemon->use_rpz &&
modstack_find(&daemon->mods, "respip") < 0)
fatal_exit("RPZ requires the respip module");

/* first create all the worker structures, so we can pass
* them to the newly created threads.
Expand Down
2 changes: 2 additions & 0 deletions daemon/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ struct daemon {
struct respip_set* respip_set;
/** some response-ip tags or actions are configured if true */
int use_response_ip;
/** some RPZ policies are configured */
int use_rpz;
#ifdef USE_DNSCRYPT
/** the dnscrypt environment */
struct dnsc_env* dnscenv;
Expand Down
11 changes: 11 additions & 0 deletions daemon/remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include "services/mesh.h"
#include "services/localzone.h"
#include "services/authzone.h"
#include "services/rpz.h"
#include "util/storage/slabhash.h"
#include "util/fptr_wlist.h"
#include "util/data/dname.h"
Expand Down Expand Up @@ -1045,6 +1046,16 @@ print_ext(RES* ssl, struct ub_stats_info* s)
(unsigned)s->svr.infra_cache_count)) return 0;
if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n",
(unsigned)s->svr.key_cache_count)) return 0;
/* applied RPZ actions */
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++) {
if((enum rpz_action)s->svr.rpz_action[i] == RPZ_NO_OVERRIDE_ACTION)
continue;
if(inhibit_zero && s->svr.rpz_action[i] == 0)
continue;
if(!ssl_printf(ssl, "num.rpz.action.%s"SQ"%lu\n",
rpz_action_to_string(i),
(unsigned long)s->svr.rpz_action[i])) return 0;
}
#ifdef USE_DNSCRYPT
if(!ssl_printf(ssl, "dnscrypt_shared_secret.cache.count"SQ"%u\n",
(unsigned)s->svr.shared_secret_cache_count)) return 0;
Expand Down
6 changes: 5 additions & 1 deletion daemon/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
for(i=0; i<16; i++)
for(i=0; i<UB_STATS_RCODE_NUM; i++)
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
timehist_export(worker->env.mesh->histogram, s->svr.hist,
NUM_BUCKETS_HIST);
/* values from outside network */
Expand Down Expand Up @@ -446,6 +448,8 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
for(i=0; i<NUM_BUCKETS_HIST; i++)
total->svr.hist[i] += a->svr.hist[i];
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
total->svr.rpz_action[i] += a->svr.rpz_action[i];
}

total->mesh_num_states += a->mesh_num_states;
Expand Down
45 changes: 36 additions & 9 deletions daemon/worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "services/authzone.h"
#include "services/mesh.h"
#include "services/localzone.h"
#include "services/rpz.h"
#include "util/data/msgparse.h"
#include "util/data/msgencode.h"
#include "util/data/dname.h"
Expand Down Expand Up @@ -572,17 +573,18 @@ static int
apply_respip_action(struct worker* worker, const struct query_info* qinfo,
struct respip_client_info* cinfo, struct reply_info* rep,
struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
struct reply_info** encode_repp)
struct reply_info** encode_repp, struct auth_zones* az)
{
struct respip_action_info actinfo = {respip_none, NULL};
struct respip_action_info actinfo = {0};
actinfo.action = respip_none;

if(qinfo->qtype != LDNS_RR_TYPE_A &&
qinfo->qtype != LDNS_RR_TYPE_AAAA &&
qinfo->qtype != LDNS_RR_TYPE_ANY)
return 1;

if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
alias_rrset, 0, worker->scratchpad))
alias_rrset, 0, worker->scratchpad, az))
return 0;

/* xxx_deny actions mean dropping the reply, unless the original reply
Expand All @@ -595,9 +597,20 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
/* If address info is returned, it means the action should be an
* 'inform' variant and the information should be logged. */
if(actinfo.addrinfo) {
respip_inform_print(actinfo.addrinfo, qinfo->qname,
respip_inform_print(&actinfo, qinfo->qname,
qinfo->qtype, qinfo->qclass, qinfo->local_alias,
repinfo);

if(worker->stats.extended && actinfo.rpz_used) {
if(actinfo.rpz_disabled)
worker->stats.rpz_action[RPZ_DISABLED_ACTION] +=
actinfo.rpz_disabled;
if(actinfo.rpz_cname_override)
worker->stats.rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
else
worker->stats.rpz_action[
respip_action_to_rpz_action(actinfo.action)]++;
}
}

return 1;
Expand Down Expand Up @@ -709,13 +722,15 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
(int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
goto bail_out;
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
if(worker->daemon->use_response_ip && !partial_rep &&
!apply_respip_action(worker, qinfo, cinfo, rep, repinfo, alias_rrset,
&encode_rep)) {
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
!partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
repinfo, alias_rrset,
&encode_rep, worker->env.auth_zones)) {
goto bail_out;
} else if(partial_rep &&
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
must_validate, &encode_rep, worker->scratchpad)) {
must_validate, &encode_rep, worker->scratchpad,
worker->env.auth_zones)) {
goto bail_out;
}
if(encode_rep != rep)
Expand Down Expand Up @@ -1364,6 +1379,18 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
if(worker->env.auth_zones &&
rpz_apply_qname_trigger(worker->env.auth_zones,
&worker->env, &qinfo, &edns, c->buffer, worker->scratchpad,
repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) {
regional_free_all(worker->scratchpad);
if(sldns_buffer_limit(c->buffer) == 0) {
comm_point_drop_reply(repinfo);
return 0;
}
server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
if(worker->env.auth_zones &&
auth_zones_answer(worker->env.auth_zones, &worker->env,
&qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
Expand Down Expand Up @@ -1434,7 +1461,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/* If we may apply IP-based actions to the answer, build the client
* information. As this can be expensive, skip it if there is
* absolutely no possibility of it. */
if(worker->daemon->use_response_ip &&
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
(qinfo.qtype == LDNS_RR_TYPE_A ||
qinfo.qtype == LDNS_RR_TYPE_AAAA ||
qinfo.qtype == LDNS_RR_TYPE_ANY)) {
Expand Down
17 changes: 17 additions & 0 deletions doc/example.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -1006,3 +1006,20 @@ remote-control:
# name-v6: "list-v6"
#

# 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. 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
# rpz-log-name: "example policy"
# tags: "example"
5 changes: 5 additions & 0 deletions doc/unbound-control.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -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.<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@
Expand Down
64 changes: 64 additions & 0 deletions doc/unbound.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,70 @@ If this timeout expires Unbound closes the connection, treats it as
if the Redis server does not have the requested data, and will try to
re-establish a new connection later.
This option defaults to 100 milliseconds.
.SS Response Policy Zone Options
.LP
Response Policy Zones are configured with \fBrpz:\fR, and each one must have a
\fBname:\fR. There can be multiple ones, by listing multiple rpz clauses, each
with a different name. RPZ clauses are applied in order of configuration. The
\fBrespip\fR module needs to be added to the \fBmodule-config\fR, e.g.:
\fBmodule-config: "respip validator iterator"\fR.
.P
Only the QNAME and Response IP Address triggers are supported. The supported RPZ
actions are: NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. RPZ QNAME triggers
are applied after
\fBlocal-zones\fR and before \fBauth-zones\fR.
.TP
.B name: \fI<zone name>
Name of the authority zone.
.TP
.B master: \fI<IP address or host name>
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<url to zonefile>
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<IP address or host name or netblockIP/prefix>
With allow\-notify you can specify additional sources of notifies.
When notified, the server attempts to first probe and then zone transfer.
If the notify is from a master, it first attempts that master. Otherwise
other masters are attempted. If there are no masters, but only urls, the
file is downloaded when notified. The masters from master: statements are
allowed notify by default.
.TP
.B zonefile: \fI<filename>
The filename where the zone is stored. If not given then no zonefile is used.
If the file does not exist or is empty, unbound will attempt to fetch zone
data (eg. from the master servers).
.TP
.B rpz\-action\-override: \fI<action>
Always use this RPZ action for matching triggers from this zone. Possible action
are: nxdomain, nodata, passthru, drop, disabled and cname.
.TP
.B rpz\-cname\-override: \fI<domain>
The CNAME target domain to use if the cname action is configured for
\fBrpz\-action\-override\fR.
.TP
.B rpz\-log: \fI<yes or no>
Log all applied RPZ actions for this RPZ zone. Default is no.
.TP
.B rpz\-log\-name: \fI<name>
Specify a string to be part of the log line, for easy referencing.
.TP
.B tags: \fI<list of tags>
Limit the policies from this RPZ clause to clients with a matching tag. Tags
need to be defined in \fBdefine\-tag\fR and can be assiged to client addresses
using \fBaccess\-control\-tag\fR. Enclose list of tags in quotes ("") and put
spaces between tags. If no tags are specified the policies from this clause will
be applied for all clients.
.SH "MEMORY CONTROL EXAMPLE"
In the example config settings below memory usage is reduced. Some service
levels are lower, notable very large data and a high TCP load are no longer
Expand Down
3 changes: 2 additions & 1 deletion libunbound/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
int
context_finalize(struct ub_ctx* ctx)
{
int is_rpz = 0;
struct config_file* cfg = ctx->env->cfg;
verbosity = cfg->verbosity;
if(ctx_logfile_overridden && !ctx->logfile_override) {
Expand All @@ -76,7 +77,7 @@ context_finalize(struct ub_ctx* ctx)
return UB_NOMEM;
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
return UB_INITFAIL;
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1))
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz))
return UB_INITFAIL;
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
cfg->msg_cache_slabs)) {
Expand Down
4 changes: 4 additions & 0 deletions libunbound/unbound.h
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,8 @@ struct ub_shm_stat_info {
#define UB_STATS_OPCODE_NUM 16
/** number of histogram buckets */
#define UB_STATS_BUCKET_NUM 40
/** number of RPZ actions */
#define UB_STATS_RPZ_ACTION_NUM 10

/** per worker statistics. */
struct ub_server_stats {
Expand Down Expand Up @@ -785,6 +787,8 @@ struct ub_server_stats {
long long mem_stream_wait;
/** number of TLS connection resume */
long long qtls_resume;
/** RPZ action stats */
long long rpz_action[UB_STATS_RPZ_ACTION_NUM];
};

/**
Expand Down
Loading