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

Add upstream cookie support #683

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
23e04d7
add functionality to store the client cookie and attach both client a…
May 16, 2022
44af84d
store complete cookie when receiving from downstream. Add function th…
May 19, 2022
10dee6c
create random cookies by creating and storing a random state in infra…
May 19, 2022
9a9f3e4
Merge branch 'master' of github.com:NLnetLabs/unbound into features/u…
May 30, 2022
e7b480a
add verification of the client cookie in the response and add cookie …
Jun 8, 2022
069660a
add unit test for server cookie init
Jun 14, 2022
d26c286
add the 3 teststeps for upstream cookies
Jun 15, 2022
69411ff
make upstream cookies configurable
Jun 15, 2022
a5ca385
fix memory alloc bug for the testcase and c89 style
Jun 17, 2022
303aa68
fix incorrect copy error
Jun 20, 2022
aebf1db
add step in rpl to verify the updated server cookie and fix bug with …
Jun 20, 2022
0d3823f
fix test and add mapage entry
Jul 1, 2022
b5acecc
implement @wcawijngaards' review comments
Jul 20, 2022
bb2d70c
Merge branch 'master' into features/upstream-cookies
Aug 8, 2022
730b55c
add privacy aware cookies. This breaks the rpl test
Sep 2, 2022
71f23ef
extended_error_encode() for extended errors
wtoorop Sep 28, 2022
75f3fbd
Downstream DNS Cookies a la RFC7873 and RFC9018
wtoorop Sep 28, 2022
bd2c202
The generated lexer and parser sources for configuring cookies
wtoorop Sep 28, 2022
eb85f34
intermediate commit
Oct 18, 2022
8df26b1
Merge branch 'master' into devel/merge-master-into-downstream-cookies
wtoorop Nov 7, 2022
11106a7
intermediate commit v2; now with seemingly working private cookies
Dec 9, 2022
5143108
add handover text and tests
Dec 9, 2022
b3ea58d
intermediate commit V3; Working up to test
Jan 31, 2023
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
8 changes: 5 additions & 3 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ util/config_file.c util/configlexer.c util/configparser.c \
util/shm_side/shm_main.c services/authzone.c \
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
util/rtt.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
util/rtt.c util/siphash.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
util/storage/lruhash.c util/storage/slabhash.c util/tcp_conn_limit.c \
util/timehist.c util/tube.c util/proxy_protocol.c \
util/ub_event.c util/ub_event_pluggable.c util/winsock_event.c \
Expand All @@ -145,7 +145,7 @@ as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo view.lo \
outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \
fptr_wlist.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
fptr_wlist.lo siphash.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
slabhash.lo tcp_conn_limit.lo timehist.lo tube.lo winsock_event.lo \
autotrust.lo val_anchor.lo rpz.lo proxy_protocol.lo \
Expand Down Expand Up @@ -915,7 +915,8 @@ config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/ut
configlexer.lo configlexer.o: util/configlexer.c config.h $(srcdir)/util/configyyrename.h \
$(srcdir)/util/config_file.h util/configparser.h
configparser.lo configparser.o: util/configparser.c config.h $(srcdir)/util/configyyrename.h \
$(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h
$(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/str2wire.h \
$(srcdir)/sldns/rrdef.h
shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/util/shm_side/shm_main.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
Expand Down Expand Up @@ -1006,6 +1007,7 @@ rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h $(srcdir)/itera
$(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h
siphash.lo siphash.o: $(srcdir)/util/siphash.c
edns.lo edns.o: $(srcdir)/util/edns.c config.h $(srcdir)/util/edns.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/regional.h \
Expand Down
2 changes: 2 additions & 0 deletions daemon/acl_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ parse_acl_access(const char* str, enum acl_access* control)
*control = acl_allow_snoop;
else if(strcmp(str, "allow_setrd") == 0)
*control = acl_allow_setrd;
else if (strcmp(str, "allow_cookie") == 0)
*control = acl_allow_cookie;
else {
log_err("access control type %s unknown", str);
return 0;
Expand Down
4 changes: 3 additions & 1 deletion daemon/acl_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ enum acl_access {
/** allow full access for all queries, recursion and cache snooping */
acl_allow_snoop,
/** allow full access for recursion queries and set RD flag regardless of request */
acl_allow_setrd
acl_allow_setrd,
/** allow full access if valid cookie present or stateful transport */
acl_allow_cookie
};

/**
Expand Down
62 changes: 46 additions & 16 deletions daemon/worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -1455,16 +1455,16 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
goto send_reply;
}
if((ret=parse_edns_from_query_pkt(c->buffer, &edns, worker->env.cfg, c,
worker->scratchpad)) != 0) {
if((ret=parse_edns_from_query_pkt(
c->buffer, &edns, worker->env.cfg, c, repinfo,
(worker->env.now ? *worker->env.now : time(NULL)),
worker->scratchpad)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
memset(&reply_edns, 0, sizeof(reply_edns));
reply_edns.edns_present = 1;
reply_edns.udp_size = EDNS_ADVERTISED_SIZE;
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), ret);
error_encode(c->buffer, ret, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), &reply_edns);
Expand All @@ -1473,23 +1473,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if(edns.edns_present) {
if(edns.edns_version != 0) {
edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4);
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.udp_size = EDNS_ADVERTISED_SIZE;
edns.bits &= EDNS_DO;
edns.opt_list_in = NULL;
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
verbose(VERB_ALGO, "query with bad edns version.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
log_addr( VERB_CLIENT, "from",&repinfo->remote_addr
, repinfo->remote_addrlen);
extended_error_encode(c->buffer, EDNS_RCODE_BADVERS, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
if(sldns_buffer_capacity(c->buffer) >=
sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
attach_edns_record(c->buffer, &edns);
sldns_buffer_read_u16_at(c->buffer, 2), 0, &edns);
regional_free_all(worker->scratchpad);
goto send_reply;
}
Expand All @@ -1502,6 +1494,44 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
edns.udp_size = NORMAL_UDP_SIZE;
}
}
/* "if, else if" sequence below deals with downstream DNS Cookies */
if (acl != acl_allow_cookie)
; /* pass; No cookie downstream processing whatsoever */

else if (edns.cookie_valid)
; /* pass; Valid cookie is good! */

else if (c->type != comm_udp)
; /* pass; Stateful transport */

else if (edns.cookie_present) {
/* Cookie present, but not valid: Cookie was bad! */
extended_error_encode(c->buffer,
LDNS_EXT_RCODE_BADCOOKIE, &qinfo,
*(uint16_t*)(void *)
sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2),
0, &edns);
regional_free_all(worker->scratchpad);
goto send_reply;
} else {
/* Cookie requered, but no cookie present on UDP */
verbose(VERB_ALGO, "worker request: "
"need cookie or stateful transport");
log_addr(VERB_ALGO, "from",&repinfo->remote_addr
, repinfo->remote_addrlen);
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
worker->scratchpad, LDNS_EDE_OTHER,
"DNS Cookie needed for UDP replies");
error_encode(c->buffer,
(LDNS_RCODE_REFUSED|BIT_TC), &qinfo,
*(uint16_t*)(void *)
sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2),
&edns);
regional_free_all(worker->scratchpad);
goto send_reply;
}
if(edns.udp_size > worker->daemon->cfg->max_udp_size &&
c->type == comm_udp) {
verbose(VERB_QUERY,
Expand Down
32 changes: 29 additions & 3 deletions doc/unbound.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,15 @@ Enable udp upstream even if do-udp is no. Default is no, and this does not
change anything. Useful for TLS service providers, that want no udp downstream
but use udp to fetch data upstream.
.TP
.B upstream-cookies: \fI<yes or no>
Enable EDNS cookies from upstream connections. DNS Cookies, as specified in
RFC 7873 and 9018 provide a limited-protection transaction security mechanism.
Once a cookie has been exchanged, the resolver and upstream are known to each
other and requests to the upstream can be exempted from rate limiting, for
example. Note that RFC9018 specifies that cookies should not be reused for
multiple outgoing interfaces, which is not supported at this time. The default
is no.
.TP
.B tls\-upstream: \fI<yes or no>
Enabled or disable whether the upstream queries use TLS only for transport.
Default is no. Useful in tunneling scenarios. The TLS contains plain DNS in
Expand Down Expand Up @@ -684,9 +693,9 @@ This option is experimental at this time.
.B access\-control: \fI<IP netblock> <action>
The netblock is given as an IP4 or IP6 address with /size appended for a
classless network block. The action can be \fIdeny\fR, \fIrefuse\fR,
\fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIdeny_non_local\fR or
\fIrefuse_non_local\fR.
The most specific netblock match is used, if none match \fIrefuse\fR is used.
\fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIallow_cookie\fR,
\fIdeny_non_local\fR or \fIrefuse_non_local\fR.
The most specific netblock match is used, if none match \fIdeny\fR is used.
The order of the access\-control statements therefore does not matter.
.IP
The action \fIdeny\fR stops queries from hosts from that netblock.
Expand Down Expand Up @@ -721,6 +730,14 @@ the cache contents (for malicious acts). However, nonrecursive queries can
also be a valuable debugging tool (when you want to examine the cache
contents). In that case use \fIallow_snoop\fR for your administration host.
.IP
When the \fBanswer\-cookie\fR option is enabled, the \fIallow_cookie\fR action
will allow access to UDP queries that contain a valid Server Cookie as
specified in RFC 7873 and RFC9018. UDP queries containing only a Client Cookie
and no Server Cookie, will receive a BADCOOKIE response including a Server
Cookie, allow clients to retry with that Server Cookie. The \fIallow_cookie\fR
will also accept requests over statefull transports, regardless of the precence
of a Cookie and regardless the \fBanswer\-cookie\fR setting.
.IP
By default only localhost is \fIallow\fRed, the rest is \fIrefuse\fRd.
The default is \fIrefuse\fRd, because that is protocol\-friendly. The DNS
protocol is not designed to handle dropped packets due to policy, and
Expand Down Expand Up @@ -1835,6 +1852,15 @@ Set the number of servers that should be used for fast server selection. Only
use the fastest specified number of servers with the fast\-server\-permil
option, that turns this on or off. The default is to use the fastest 3 servers.
.TP 5
.B answer\-cookie: \fI<yes or no>
Enable to answer to requests containig DNS Cookies as specified in RFC7873 and
RFC9018. Default is no.
.TP 5
.B cookie\-secret: \fI<128 bit hex string>
Server's in an Anycast deployment need to be able to verify each other's
Server Cookies. For this they need to share the secret used to construct
and verify the Server Cookies.
Default is a 128 bits random secret generated at startup time.
.B edns\-client\-string: \fI<IP netblock> <string>
Include an EDNS0 option containing configured ascii string in queries with
destination address matching the configured IP netblock. This configuration
Expand Down
Loading