diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2019-01-27 12:40:55 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2019-01-27 12:40:55 +0000 |
commit | 9f897e4c10474010ceaa248eee1de3023025d521 (patch) | |
tree | 191aebb47394ee632046a333c492e7e92bcd5b23 | |
parent | 1f503548dc5c612a2465358b408a748d14bd22db (diff) |
Implement DNS over TLS (DoT).
-rw-r--r-- | sbin/unwind/frontend.c | 12 | ||||
-rw-r--r-- | sbin/unwind/printconf.c | 36 | ||||
-rw-r--r-- | sbin/unwind/resolver.c | 61 | ||||
-rw-r--r-- | sbin/unwind/resolver.h | 6 | ||||
-rw-r--r-- | sbin/unwind/unwind.c | 25 | ||||
-rw-r--r-- | sbin/unwind/unwind.conf.5 | 11 | ||||
-rw-r--r-- | sbin/unwind/unwind.h | 4 | ||||
-rw-r--r-- | sbin/unwind/uw_parse.y | 77 |
8 files changed, 214 insertions, 18 deletions
diff --git a/sbin/unwind/frontend.c b/sbin/unwind/frontend.c index 4e2c3eb0277..7bf8f3733a4 100644 --- a/sbin/unwind/frontend.c +++ b/sbin/unwind/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.4 2019/01/27 07:46:49 florian Exp $ */ +/* $OpenBSD: frontend.c,v 1.5 2019/01/27 12:40:54 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -298,6 +298,7 @@ frontend_dispatch_main(int fd, short event, void *bula) fatal(NULL); memcpy(nconf, imsg.data, sizeof(struct unwind_conf)); SIMPLEQ_INIT(&nconf->unwind_forwarder_list); + SIMPLEQ_INIT(&nconf->unwind_dot_forwarder_list); break; case IMSG_RECONF_FORWARDER: if ((unwind_forwarder = malloc(sizeof(struct @@ -308,6 +309,15 @@ frontend_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INSERT_TAIL(&nconf->unwind_forwarder_list, unwind_forwarder, entry); break; + case IMSG_RECONF_DOT_FORWARDER: + if ((unwind_forwarder = malloc(sizeof(struct + unwind_forwarder))) == NULL) + fatal(NULL); + memcpy(unwind_forwarder, imsg.data, sizeof(struct + unwind_forwarder)); + SIMPLEQ_INSERT_TAIL(&nconf->unwind_dot_forwarder_list, + unwind_forwarder, entry); + break; case IMSG_RECONF_END: merge_config(frontend_conf, nconf); nconf = NULL; diff --git a/sbin/unwind/printconf.c b/sbin/unwind/printconf.c index 81e170f3b01..e6c70fa45ba 100644 --- a/sbin/unwind/printconf.c +++ b/sbin/unwind/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.2 2019/01/27 07:46:49 florian Exp $ */ +/* $OpenBSD: printconf.c,v 1.3 2019/01/27 12:40:54 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -22,10 +22,12 @@ #include <event.h> #include <imsg.h> #include <stdio.h> +#include <string.h> #include "unwind.h" const char* yesno(int); +void print_forwarder(char *); const char* yesno(int flag) @@ -34,17 +36,43 @@ yesno(int flag) } void +print_forwarder(char *name) +{ + char *pos; + + pos = strchr(name, '@'); + + if (pos != NULL) { + *pos = '\0'; + printf("%s port %s", name, pos + 1); + *pos = '@'; + } else + printf("%s", name); + +} + +void print_config(struct unwind_conf *conf) { struct unwind_forwarder *unwind_forwarder; printf("strict %s\n", yesno(conf->unwind_options)); - if (!SIMPLEQ_EMPTY(&conf->unwind_forwarder_list)) { + if (!SIMPLEQ_EMPTY(&conf->unwind_forwarder_list) || + !SIMPLEQ_EMPTY(&conf->unwind_dot_forwarder_list)) { printf("forwarder {\n"); SIMPLEQ_FOREACH(unwind_forwarder, &conf->unwind_forwarder_list, - entry) - printf("\t%s\n", unwind_forwarder->name); + entry) { + printf("\t"); + print_forwarder(unwind_forwarder->name); + printf("\n"); + } + SIMPLEQ_FOREACH(unwind_forwarder, + &conf->unwind_dot_forwarder_list, entry) { + printf("\t"); + print_forwarder(unwind_forwarder->name); + printf(" DoT\n"); + } printf("}\n"); } } diff --git a/sbin/unwind/resolver.c b/sbin/unwind/resolver.c index b030ca40022..9cd7f24d442 100644 --- a/sbin/unwind/resolver.c +++ b/sbin/unwind/resolver.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolver.c,v 1.10 2019/01/27 07:46:49 florian Exp $ */ +/* $OpenBSD: resolver.c,v 1.11 2019/01/27 12:40:54 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -85,6 +85,7 @@ void parse_dhcp_forwarders(char *); void new_recursor(void); void new_forwarders(void); void new_static_forwarders(void); +void new_static_dot_forwarders(void); struct unwind_resolver *create_resolver(enum unwind_resolver_type); void free_resolver(struct unwind_resolver *); void set_forwarders(struct unwind_resolver *, @@ -123,6 +124,7 @@ struct imsgev *iev_frontend; struct imsgev *iev_main; struct unwind_forwarder_head dhcp_forwarder_list; struct unwind_resolver *recursor, *forwarder, *static_forwarder; +struct unwind_resolver *static_dot_forwarder; struct timeval resolver_check_pause = { 30, 0}; struct event_base *ev_base; @@ -376,6 +378,7 @@ resolver_dispatch_main(int fd, short event, void *bula) struct imsgbuf *ibuf; ssize_t n; int shut = 0, forwarders_changed; + int dot_forwarders_changed; ibuf = &iev->ibuf; @@ -433,6 +436,7 @@ resolver_dispatch_main(int fd, short event, void *bula) fatal(NULL); memcpy(nconf, imsg.data, sizeof(struct unwind_conf)); SIMPLEQ_INIT(&nconf->unwind_forwarder_list); + SIMPLEQ_INIT(&nconf->unwind_dot_forwarder_list); break; case IMSG_RECONF_FORWARDER: if ((unwind_forwarder = malloc(sizeof(struct @@ -443,16 +447,32 @@ resolver_dispatch_main(int fd, short event, void *bula) SIMPLEQ_INSERT_TAIL(&nconf->unwind_forwarder_list, unwind_forwarder, entry); break; + case IMSG_RECONF_DOT_FORWARDER: + if ((unwind_forwarder = malloc(sizeof(struct + unwind_forwarder))) == NULL) + fatal(NULL); + memcpy(unwind_forwarder, imsg.data, sizeof(struct + unwind_forwarder)); + SIMPLEQ_INSERT_TAIL(&nconf->unwind_dot_forwarder_list, + unwind_forwarder, entry); + break; case IMSG_RECONF_END: forwarders_changed = check_forwarders_changed( &resolver_conf->unwind_forwarder_list, &nconf->unwind_forwarder_list); + dot_forwarders_changed = check_forwarders_changed( + &resolver_conf->unwind_dot_forwarder_list, + &nconf->unwind_dot_forwarder_list); merge_config(resolver_conf, nconf); nconf = NULL; if (forwarders_changed) { log_debug("static forwarders changed"); new_static_forwarders(); } + if (dot_forwarders_changed) { + log_debug("static DoT forwarders changed"); + new_static_dot_forwarders(); + } break; default: log_debug("%s: unexpected imsg %d", __func__, @@ -620,6 +640,25 @@ new_static_forwarders(void) check_resolver(static_forwarder); } +void +new_static_dot_forwarders(void) +{ + free_resolver(static_dot_forwarder); + + if (SIMPLEQ_EMPTY(&resolver_conf->unwind_dot_forwarder_list)) { + static_dot_forwarder = NULL; + return; + } + + log_debug("%s: create_resolver", __func__); + static_dot_forwarder = create_resolver(STATIC_DOT_FORWARDER); + set_forwarders(static_dot_forwarder, + &resolver_conf->unwind_dot_forwarder_list); + ub_ctx_set_tls(static_dot_forwarder->ctx, 1); + + check_resolver(static_dot_forwarder); +} + struct unwind_resolver * create_resolver(enum unwind_resolver_type type) { @@ -742,6 +781,11 @@ check_resolver(struct unwind_resolver *res) set_forwarders(check_res, &resolver_conf->unwind_forwarder_list); break; + case STATIC_DOT_FORWARDER: + set_forwarders(check_res, + &resolver_conf->unwind_dot_forwarder_list); + ub_ctx_set_tls(check_res->ctx, 1); + break; case RESOLVER_NONE: fatalx("type NONE"); break; @@ -945,6 +989,11 @@ best_resolver(void) unwind_resolver_type_str[static_forwarder->type], unwind_resolver_state_str[static_forwarder->state]); + if (static_dot_forwarder != NULL) + log_debug("%s: %s state: %s", __func__, + unwind_resolver_type_str[static_dot_forwarder->type], + unwind_resolver_state_str[static_dot_forwarder->state]); + if (forwarder != NULL) log_debug("%s: %s state: %s", __func__, unwind_resolver_type_str[forwarder->type], @@ -952,6 +1001,9 @@ best_resolver(void) res = recursor; + if (resolver_cmp(res, static_dot_forwarder) < 0) + res = static_dot_forwarder; + if (resolver_cmp(res, static_forwarder) < 0) res = static_forwarder; @@ -1004,6 +1056,8 @@ show_status(enum unwind_resolver_type type, pid_t pid) send_resolver_info(forwarder, forwarder == best, pid); send_resolver_info(static_forwarder, static_forwarder == best, pid); + send_resolver_info(static_dot_forwarder, static_dot_forwarder + == best, pid); break; case RECURSOR: send_resolver_info(recursor, recursor == best, pid); @@ -1018,6 +1072,11 @@ show_status(enum unwind_resolver_type type, pid_t pid) pid); send_detailed_resolver_info(static_forwarder, pid); break; + case STATIC_DOT_FORWARDER: + send_resolver_info(static_dot_forwarder, static_dot_forwarder + == best, pid); + send_detailed_resolver_info(static_dot_forwarder, pid); + break; } resolver_imsg_compose_frontend(IMSG_CTL_END, pid, NULL, 0); } diff --git a/sbin/unwind/resolver.h b/sbin/unwind/resolver.h index 9d5cc61c16d..da9525ba3a0 100644 --- a/sbin/unwind/resolver.h +++ b/sbin/unwind/resolver.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolver.h,v 1.1 2019/01/23 13:11:00 florian Exp $ */ +/* $OpenBSD: resolver.h,v 1.2 2019/01/27 12:40:54 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -35,13 +35,15 @@ enum unwind_resolver_type { RECURSOR, FORWARDER, STATIC_FORWARDER, + STATIC_DOT_FORWARDER, RESOLVER_NONE = -1 }; static const char * const unwind_resolver_type_str[] = { "recursor", "dhcp forwarder", - "static forwarder" + "static forwarder", + "DoT forwarder" }; static const int64_t histogram_limits[] = { diff --git a/sbin/unwind/unwind.c b/sbin/unwind/unwind.c index 84e0c6c9b9c..11a6d776b41 100644 --- a/sbin/unwind/unwind.c +++ b/sbin/unwind/unwind.c @@ -1,4 +1,4 @@ -/* $OpenBSD: unwind.c,v 1.4 2019/01/27 07:46:49 florian Exp $ */ +/* $OpenBSD: unwind.c,v 1.5 2019/01/27 12:40:54 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -577,7 +577,7 @@ main_imsg_send_config(struct unwind_conf *xconf) if (main_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) return (-1); - /* send static forarders to children */ + /* send static forwarders to children */ SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_forwarder_list, entry) { if (main_sendboth(IMSG_RECONF_FORWARDER, unwind_forwarder, sizeof(*unwind_forwarder)) == -1) @@ -585,6 +585,15 @@ main_imsg_send_config(struct unwind_conf *xconf) } + /* send static DoT forwarders to children */ + SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_dot_forwarder_list, + entry) { + if (main_sendboth(IMSG_RECONF_DOT_FORWARDER, unwind_forwarder, + sizeof(*unwind_forwarder)) == -1) + return (-1); + + } + /* Tell children the revised config is now complete. */ if (main_sendboth(IMSG_RECONF_END, NULL, 0) == -1) return (-1); @@ -613,6 +622,11 @@ merge_config(struct unwind_conf *conf, struct unwind_conf *xconf) SIMPLEQ_REMOVE_HEAD(&conf->unwind_forwarder_list, entry); free(unwind_forwarder); } + while ((unwind_forwarder = + SIMPLEQ_FIRST(&conf->unwind_dot_forwarder_list)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&conf->unwind_dot_forwarder_list, entry); + free(unwind_forwarder); + } conf->unwind_options = xconf->unwind_options; @@ -623,6 +637,12 @@ merge_config(struct unwind_conf *conf, struct unwind_conf *xconf) SIMPLEQ_INSERT_TAIL(&conf->unwind_forwarder_list, unwind_forwarder, entry); } + while ((unwind_forwarder = + SIMPLEQ_FIRST(&xconf->unwind_dot_forwarder_list)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&xconf->unwind_dot_forwarder_list, entry); + SIMPLEQ_INSERT_TAIL(&conf->unwind_dot_forwarder_list, + unwind_forwarder, entry); + } free(xconf); } @@ -637,6 +657,7 @@ config_new_empty(void) fatal(NULL); SIMPLEQ_INIT(&xconf->unwind_forwarder_list); + SIMPLEQ_INIT(&xconf->unwind_dot_forwarder_list); return (xconf); } diff --git a/sbin/unwind/unwind.conf.5 b/sbin/unwind/unwind.conf.5 index 5efb0e1086c..e00c9929fdc 100644 --- a/sbin/unwind/unwind.conf.5 +++ b/sbin/unwind/unwind.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: unwind.conf.5,v 1.1 2019/01/23 13:11:00 florian Exp $ +.\" $OpenBSD: unwind.conf.5,v 1.2 2019/01/27 12:40:54 florian Exp $ .\" .\" Copyright (c) 2018 Florian Obser <florian@openbsd.org> .\" Copyright (c) 2005 Esben Norby <norby@openbsd.org> @@ -18,7 +18,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 23 2019 $ +.Dd $Mdocdate: January 27 2019 $ .Dt UNWIND.CONF 5 .Os .Sh NAME @@ -52,8 +52,13 @@ Macro names may not be reserved words. Macros are not expanded inside quotes. .Sh GLOBAL CONFIGURATION .Bl -tag -width Ds -.It Ic forwarder Brq forwarder list +.It Ic forwarder Brq Ar address Oo Ic port Ar number Oc Oo Ic DoT Oc ... list of addresses of DNS name servers to forward queries to. +If +.Ic DoT +is specified use DNS over TLS when sending queries to the server at +.Ar address . + .El .Sh FILES .Bl -tag -width "/etc/unwind.conf" -compact diff --git a/sbin/unwind/unwind.h b/sbin/unwind/unwind.h index 916b26f6659..6f8701aef60 100644 --- a/sbin/unwind/unwind.h +++ b/sbin/unwind/unwind.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unwind.h,v 1.2 2019/01/24 17:39:43 florian Exp $ */ +/* $OpenBSD: unwind.h,v 1.3 2019/01/27 12:40:54 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -56,6 +56,7 @@ enum imsg_type { IMSG_CTL_STATUS, IMSG_RECONF_CONF, IMSG_RECONF_FORWARDER, + IMSG_RECONF_DOT_FORWARDER, IMSG_RECONF_END, IMSG_UDP4SOCK, IMSG_UDP6SOCK, @@ -87,6 +88,7 @@ struct unwind_forwarder { struct unwind_conf { SIMPLEQ_HEAD(unwind_forwarder_head, unwind_forwarder) unwind_forwarder_list; + struct unwind_forwarder_head unwind_dot_forwarder_list; int unwind_options; }; diff --git a/sbin/unwind/uw_parse.y b/sbin/unwind/uw_parse.y index 000c6888481..24d7863af8e 100644 --- a/sbin/unwind/uw_parse.y +++ b/sbin/unwind/uw_parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: uw_parse.y,v 1.2 2019/01/24 15:59:32 florian Exp $ */ +/* $OpenBSD: uw_parse.y,v 1.3 2019/01/27 12:40:54 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -107,7 +107,7 @@ typedef struct { %} %token STRICT YES NO INCLUDE ERROR -%token FORWARDER +%token FORWARDER DOT PORT %token <v.string> STRING %token <v.number> NUMBER @@ -211,6 +211,66 @@ forwarderoptsl : STRING { &conf->unwind_forwarder_list, unwind_forwarder, entry); } + | STRING PORT NUMBER { + int ret; + + if ($3 <= 0 || $3 > (int)USHRT_MAX) { + yyerror("invalid port: %lld", $3); + YYERROR; + } + + if ((unwind_forwarder = calloc(1, + sizeof(*unwind_forwarder))) == NULL) + err(1, NULL); + + ret = snprintf(unwind_forwarder->name, + sizeof(unwind_forwarder->name), "%s@%d", $1, + (int)$3); + if (ret == -1 || (size_t)ret >= + sizeof(unwind_forwarder->name)) + err(1, "%s too long", $1); + + SIMPLEQ_INSERT_TAIL( + &conf->unwind_forwarder_list, + unwind_forwarder, entry); + } + | STRING DOT { + if ((unwind_forwarder = calloc(1, + sizeof(*unwind_forwarder))) == NULL) + err(1, NULL); + + if(strlcpy(unwind_forwarder->name, $1, + sizeof(unwind_forwarder->name)) >= + sizeof(unwind_forwarder->name)) + err(1, "%s too long", $1); + + SIMPLEQ_INSERT_TAIL( + &conf->unwind_dot_forwarder_list, + unwind_forwarder, entry); + } + | STRING PORT NUMBER DOT { + int ret; + + if ($3 <= 0 || $3 > (int)USHRT_MAX) { + yyerror("invalid port: %lld", $3); + YYERROR; + } + + if ((unwind_forwarder = calloc(1, + sizeof(*unwind_forwarder))) == NULL) + err(1, NULL); + + ret = snprintf(unwind_forwarder->name, + sizeof(unwind_forwarder->name), "%s@%d", $1, + (int)$3); + if (ret == -1 || (size_t)ret >= + sizeof(unwind_forwarder->name)) + err(1, "%s too long", $1); + + SIMPLEQ_INSERT_TAIL( + &conf->unwind_dot_forwarder_list, + unwind_forwarder, entry); + } ; %% @@ -246,10 +306,14 @@ lookup(char *s) { /* This has to be sorted always. */ static const struct keywords keywords[] = { + {"dot", DOT}, + {"DoT", DOT}, {"forwarder", FORWARDER}, {"include", INCLUDE}, {"no", NO}, + {"port", PORT}, {"strict", STRICT}, + {"tls", DOT}, {"yes", YES}, }; const struct keywords *p; @@ -713,11 +777,16 @@ symget(const char *nam) void clear_config(struct unwind_conf *xconf) { - while((unwind_forwarder = SIMPLEQ_FIRST(&xconf->unwind_forwarder_list)) != - NULL) { + while((unwind_forwarder = + SIMPLEQ_FIRST(&xconf->unwind_forwarder_list)) != NULL) { SIMPLEQ_REMOVE_HEAD(&xconf->unwind_forwarder_list, entry); free(unwind_forwarder); } + while((unwind_forwarder = + SIMPLEQ_FIRST(&xconf->unwind_dot_forwarder_list)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&xconf->unwind_dot_forwarder_list, entry); + free(unwind_forwarder); + } free(xconf); } |