mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-02-03 20:29:28 -05:00
- caps-whitelist in unbound.conf allows whitelist of loadbalancers
that cannot work with caps-for-id or its fallback. git-svn-id: file:///svn/unbound/trunk@3420 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
b8eb1713e0
commit
f03d3b870e
16 changed files with 2074 additions and 1944 deletions
|
|
@ -691,7 +691,7 @@ iter_utils.lo iter_utils.o: $(srcdir)/iterator/iter_utils.c config.h $(srcdir)/i
|
|||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_sigcrypt.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h
|
||||
listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
1 May 2015: Wouter
|
||||
- caps-whitelist in unbound.conf allows whitelist of loadbalancers
|
||||
that cannot work with caps-for-id or its fallback.
|
||||
|
||||
30 April 2015: Wouter
|
||||
- Unit test for type ANY synthesis.
|
||||
|
||||
|
|
|
|||
|
|
@ -296,6 +296,10 @@ server:
|
|||
# Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
# This feature is an experimental implementation of draft dns-0x20.
|
||||
# use-caps-for-id: no
|
||||
|
||||
# Domains (and domains in them) without support for dns-0x20 and
|
||||
# the fallback fails because they keep sending different answers.
|
||||
# caps-whitelist: "licdn.com"
|
||||
|
||||
# Enforce privacy of these addresses. Strips them away from answers.
|
||||
# It may cause DNSSEC validation to additionally mark it as bogus.
|
||||
|
|
|
|||
|
|
@ -574,6 +574,12 @@ authority servers and checks if the reply still has the correct casing.
|
|||
Disabled by default.
|
||||
This feature is an experimental implementation of draft dns\-0x20.
|
||||
.TP
|
||||
.B caps\-whitelist: \fI<domain>
|
||||
Whitelist the domain so that it does not receive caps\-for\-id perturbed
|
||||
queries. For domains that do not support 0x20 and also fail with fallback
|
||||
because they keep sending different answers, like some load balancers.
|
||||
Can be given multiple times, for different domains.
|
||||
.TP
|
||||
.B private\-address: \fI<IP address or subnet>
|
||||
Give IPv4 of IPv6 addresses or classless subnets. These are addresses
|
||||
on your private network, and are not allowed to be returned for public
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
#include "validator/val_utils.h"
|
||||
#include "validator/val_sigcrypt.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
/** time when nameserver glue is said to be 'recent' */
|
||||
#define SUSPICION_RECENT_EXPIRY 86400
|
||||
|
|
@ -105,6 +106,35 @@ read_fetch_policy(struct iter_env* ie, const char* str)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** apply config caps whitelist items to name tree */
|
||||
static int
|
||||
caps_white_apply_cfg(rbtree_t* ntree, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p=cfg->caps_whitelist; p; p=p->next) {
|
||||
struct name_tree_node* n;
|
||||
size_t len;
|
||||
uint8_t* nm = sldns_str2wire_dname(p->str, &len);
|
||||
if(!nm) {
|
||||
log_err("could not parse %s", p->str);
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)calloc(1, sizeof(*n));
|
||||
n->node.key = n;
|
||||
n->name = nm;
|
||||
n->len = len;
|
||||
n->labs = dname_count_labels(nm);
|
||||
n->dclass = LDNS_RR_CLASS_IN;
|
||||
if(!name_tree_insert(ntree, n, nm, len, n->labs, n->dclass)) {
|
||||
/* duplicate element ignored, idempotent */
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
name_tree_init_parents(ntree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
{
|
||||
|
|
@ -128,6 +158,16 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
|||
log_err("Could not set private addresses");
|
||||
return 0;
|
||||
}
|
||||
if(cfg->caps_whitelist) {
|
||||
if(!iter_env->caps_white)
|
||||
iter_env->caps_white = rbtree_create(name_tree_compare);
|
||||
if(!iter_env->caps_white || !caps_white_apply_cfg(
|
||||
iter_env->caps_white, cfg)) {
|
||||
log_err("Could not set capsforid whitelist");
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||
iter_env->supports_ipv4 = cfg->do_ip4;
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,16 @@ iter_init(struct module_env* env, int id)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** delete caps_whitelist element */
|
||||
static void
|
||||
caps_free(struct rbnode_t* n, void* ATTR_UNUSED(d))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct name_tree_node*)n)->name);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
iter_deinit(struct module_env* env, int id)
|
||||
{
|
||||
|
|
@ -94,6 +104,10 @@ iter_deinit(struct module_env* env, int id)
|
|||
free(iter_env->target_fetch_policy);
|
||||
priv_delete(iter_env->priv);
|
||||
donotq_delete(iter_env->donotq);
|
||||
if(iter_env->caps_white) {
|
||||
traverse_postorder(iter_env->caps_white, caps_free, NULL);
|
||||
free(iter_env->caps_white);
|
||||
}
|
||||
free(iter_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
|
@ -459,6 +473,16 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** see if target name is caps-for-id whitelisted */
|
||||
static int
|
||||
is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq)
|
||||
{
|
||||
if(!ie->caps_white) return 0; /* no whitelist, or no capsforid */
|
||||
return name_tree_lookup(ie->caps_white, iq->qchase.qname,
|
||||
iq->qchase.qname_len, dname_count_labels(iq->qchase.qname),
|
||||
iq->qchase.qclass) != NULL;
|
||||
}
|
||||
|
||||
/** create target count structure for this query */
|
||||
static void
|
||||
target_count_create(struct iter_qstate* iq)
|
||||
|
|
@ -1965,8 +1989,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
iq->qchase.qname, iq->qchase.qname_len,
|
||||
iq->qchase.qtype, iq->qchase.qclass,
|
||||
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
|
||||
iq->dnssec_expected, iq->caps_fallback, &target->addr,
|
||||
target->addrlen, iq->dp->name, iq->dp->namelen, qstate);
|
||||
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
|
||||
ie, iq), &target->addr, target->addrlen, iq->dp->name,
|
||||
iq->dp->namelen, qstate);
|
||||
if(!outq) {
|
||||
log_addr(VERB_DETAIL, "error sending query to auth server",
|
||||
&target->addr, target->addrlen);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ struct iter_forwards;
|
|||
struct iter_donotq;
|
||||
struct iter_prep_list;
|
||||
struct iter_priv;
|
||||
struct rbtree_t;
|
||||
|
||||
/** max number of targets spawned for a query and its subqueries */
|
||||
#define MAX_TARGET_COUNT 32
|
||||
|
|
@ -96,6 +97,9 @@ struct iter_env {
|
|||
/** private address space and private domains */
|
||||
struct iter_priv* priv;
|
||||
|
||||
/** whitelist for capsforid names */
|
||||
struct rbtree_t* caps_white;
|
||||
|
||||
/** The maximum dependency depth that this resolver will pursue. */
|
||||
int max_dependency_depth;
|
||||
|
||||
|
|
|
|||
|
|
@ -1510,7 +1510,8 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
|||
log_assert(rem); /* should have been present */
|
||||
sq->to_be_deleted = 1;
|
||||
verbose(VERB_ALGO, "svcd callbacks start");
|
||||
if(sq->outnet->use_caps_for_id && error == NETEVENT_NOERROR && c) {
|
||||
if(sq->outnet->use_caps_for_id && error == NETEVENT_NOERROR && c &&
|
||||
!sq->nocaps) {
|
||||
/* noerror and nxdomain must have a qname in reply */
|
||||
if(sldns_buffer_read_u16_at(c->buffer, 4) == 0 &&
|
||||
(LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer))
|
||||
|
|
|
|||
BIN
testdata/fwd_capsid_white.tpkg
vendored
Normal file
BIN
testdata/fwd_capsid_white.tpkg
vendored
Normal file
Binary file not shown.
|
|
@ -173,6 +173,7 @@ config_create(void)
|
|||
cfg->harden_referral_path = 0;
|
||||
cfg->harden_algo_downgrade = 1;
|
||||
cfg->use_caps_bits_for_id = 0;
|
||||
cfg->caps_whitelist = NULL;
|
||||
cfg->private_address = NULL;
|
||||
cfg->private_domain = NULL;
|
||||
cfg->unwanted_threshold = 0;
|
||||
|
|
@ -416,6 +417,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||
else S_YNO("harden-referral-path:", harden_referral_path)
|
||||
else S_YNO("harden-algo-downgrade:", harden_algo_downgrade)
|
||||
else S_YNO("use-caps-for-id", use_caps_bits_for_id)
|
||||
else S_STRLIST("caps-whitelist:", caps_whitelist)
|
||||
else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold)
|
||||
else S_STRLIST("private-address:", private_address)
|
||||
else S_STRLIST("private-domain:", private_domain)
|
||||
|
|
@ -685,6 +687,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
|||
else O_YNO(opt, "harden-referral-path", harden_referral_path)
|
||||
else O_YNO(opt, "harden-algo-downgrade", harden_algo_downgrade)
|
||||
else O_YNO(opt, "use-caps-for-id", use_caps_bits_for_id)
|
||||
else O_LST(opt, "caps-whitelist", caps_whitelist)
|
||||
else O_DEC(opt, "unwanted-reply-threshold", unwanted_threshold)
|
||||
else O_YNO(opt, "do-not-query-localhost", donotquery_localhost)
|
||||
else O_STR(opt, "module-config", module_conf)
|
||||
|
|
@ -918,6 +921,7 @@ config_delete(struct config_file* cfg)
|
|||
free(cfg->version);
|
||||
free(cfg->module_conf);
|
||||
free(cfg->outgoing_avail_ports);
|
||||
config_delstrlist(cfg->caps_whitelist);
|
||||
config_delstrlist(cfg->private_address);
|
||||
config_delstrlist(cfg->private_domain);
|
||||
config_delstrlist(cfg->auto_trust_anchor_file_list);
|
||||
|
|
|
|||
|
|
@ -179,6 +179,8 @@ struct config_file {
|
|||
int harden_algo_downgrade;
|
||||
/** use 0x20 bits in query as random ID bits */
|
||||
int use_caps_bits_for_id;
|
||||
/** 0x20 whitelist, domains that do not use capsforid */
|
||||
struct config_strlist* caps_whitelist;
|
||||
/** strip away these private addrs from answers, no DNS Rebinding */
|
||||
struct config_strlist* private_address;
|
||||
/** allow domain (and subdomains) to use private address space */
|
||||
|
|
|
|||
2680
util/configlexer.c
2680
util/configlexer.c
File diff suppressed because it is too large
Load diff
|
|
@ -259,6 +259,7 @@ harden-below-nxdomain{COLON} { YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) }
|
|||
harden-referral-path{COLON} { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) }
|
||||
harden-algo-downgrade{COLON} { YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) }
|
||||
use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
|
||||
private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) }
|
||||
private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
|
||||
|
|
|
|||
1222
util/configparser.c
1222
util/configparser.c
File diff suppressed because it is too large
Load diff
|
|
@ -201,7 +201,8 @@ extern int yydebug;
|
|||
VAR_RATELIMIT_SIZE = 410,
|
||||
VAR_RATELIMIT_FOR_DOMAIN = 411,
|
||||
VAR_RATELIMIT_BELOW_DOMAIN = 412,
|
||||
VAR_RATELIMIT_FACTOR = 413
|
||||
VAR_RATELIMIT_FACTOR = 413,
|
||||
VAR_CAPS_WHITELIST = 414
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
|
@ -361,6 +362,7 @@ extern int yydebug;
|
|||
#define VAR_RATELIMIT_FOR_DOMAIN 411
|
||||
#define VAR_RATELIMIT_BELOW_DOMAIN 412
|
||||
#define VAR_RATELIMIT_FACTOR 413
|
||||
#define VAR_CAPS_WHITELIST 414
|
||||
|
||||
|
||||
|
||||
|
|
@ -374,7 +376,7 @@ typedef union YYSTYPE
|
|||
|
||||
|
||||
/* Line 2058 of yacc.c */
|
||||
#line 378 "util/configparser.h"
|
||||
#line 380 "util/configparser.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
|
||||
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
|
||||
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN VAR_RATELIMIT_FACTOR
|
||||
%token VAR_CAPS_WHITELIST
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
|
|
@ -183,7 +184,8 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||
server_infra_cache_min_rtt | server_harden_algo_downgrade |
|
||||
server_ip_transparent | server_ratelimit | server_ratelimit_slabs |
|
||||
server_ratelimit_size | server_ratelimit_for_domain |
|
||||
server_ratelimit_below_domain | server_ratelimit_factor
|
||||
server_ratelimit_below_domain | server_ratelimit_factor |
|
||||
server_caps_whitelist
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
|
|
@ -882,6 +884,13 @@ server_use_caps_for_id: VAR_USE_CAPS_FOR_ID STRING_ARG
|
|||
free($2);
|
||||
}
|
||||
;
|
||||
server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_caps_whitelist:%s)\n", $2));
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->caps_whitelist, $2))
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_private_address:%s)\n", $2));
|
||||
|
|
|
|||
Loading…
Reference in a new issue