summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorflorian <florian@openbsd.org>2019-01-24 17:39:43 +0000
committerflorian <florian@openbsd.org>2019-01-24 17:39:43 +0000
commitd265a5d353d317bc97eb3111703cf93f33b12fdd (patch)
treecd3ed70642fe35642b902616ab0f2dd4932526d0
parentAccept the host key fingerprint as a synonym for "yes" when accepting (diff)
downloadwireguard-openbsd-d265a5d353d317bc97eb3111703cf93f33b12fdd.tar.xz
wireguard-openbsd-d265a5d353d317bc97eb3111703cf93f33b12fdd.zip
Open and close listening sockets on localhost:53 depending on if we can
resolve at all. We come up without listening and open IPv4 and IPv6 sockets once the resolver process has determinded that we can speak DNS to the outside world. Furthermore close the listening sockets when the resolver process notices that we can no longer speak DNS to the outside. This is a last-ditch effort to get out of libc resolver's way and let it speak directly to e.g. dhcp provided resolvers. With the recomended configuration of having 127.0.0.1 first in /etc/resolv.conf and then add dhcp provided resolvers after that our libc resolver will receive a port unreachable error and immediately switch to the next one if unwind is not listening on port 53. (Networks have been observed in the wild that intercept DNS packets and answer NXDOMAIN if an edns0 option is send with the query.)
-rw-r--r--sbin/unwind/frontend.c31
-rw-r--r--sbin/unwind/resolver.c17
-rw-r--r--sbin/unwind/unwind.c94
-rw-r--r--sbin/unwind/unwind.h5
4 files changed, 92 insertions, 55 deletions
diff --git a/sbin/unwind/frontend.c b/sbin/unwind/frontend.c
index a1542257b62..607f42f336d 100644
--- a/sbin/unwind/frontend.c
+++ b/sbin/unwind/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.2 2019/01/24 15:33:44 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.3 2019/01/24 17:39:43 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -328,6 +328,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
__func__);
event_set(&udp6ev.ev, udp6sock, EV_READ | EV_PERSIST,
udp_receive, &udp6ev);
+ event_add(&udp6ev.ev, NULL);
break;
case IMSG_UDP4SOCK:
if ((udp4sock = imsg.fd) == -1)
@@ -336,6 +337,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
__func__);
event_set(&udp4ev.ev, udp4sock, EV_READ | EV_PERSIST,
udp_receive, &udp4ev);
+ event_add(&udp4ev.ev, NULL);
break;
case IMSG_ROUTESOCK:
if ((fd = imsg.fd) == -1)
@@ -440,6 +442,23 @@ frontend_dispatch_resolver(int fd, short event, void *bula)
send_answer(pq, imsg.data, imsg.hdr.len -
IMSG_HEADER_SIZE);
break;
+ case IMSG_RESOLVER_DOWN:
+ log_debug("%s: IMSG_RESOLVER_DOWN", __func__);
+ if (udp4sock != -1) {
+ event_del(&udp4ev.ev);
+ close(udp4sock);
+ udp4sock = -1;
+ }
+ if (udp6sock != -1) {
+ event_del(&udp6ev.ev);
+ close(udp6sock);
+ udp6sock = -1;
+ }
+ break;
+ case IMSG_RESOLVER_UP:
+ log_debug("%s: IMSG_RESOLVER_UP", __func__);
+ frontend_imsg_compose_main(IMSG_OPEN_PORTS, 0, NULL, 0);
+ break;
case IMSG_CTL_RESOLVER_INFO:
case IMSG_CTL_RESOLVER_WHY_BOGUS:
case IMSG_CTL_RESOLVER_HISTOGRAM:
@@ -465,16 +484,6 @@ frontend_dispatch_resolver(int fd, short event, void *bula)
void
frontend_startup(void)
{
- if (!event_initialized(&udp4ev.ev) || !event_initialized(&udp6ev.ev))
- fatalx("%s: did not receive a UDP4 or UDP6 socket fd from the "
- "main process", __func__);
-
- if (event_initialized(&udp4ev.ev))
- event_add(&udp4ev.ev, NULL);
-
- if (event_initialized(&udp6ev.ev))
- event_add(&udp6ev.ev, NULL);
-
if (!event_initialized(&ev_route))
fatalx("%s: did not receive a route socket from the main "
"process", __func__);
diff --git a/sbin/unwind/resolver.c b/sbin/unwind/resolver.c
index 708d5485f4a..54104380120 100644
--- a/sbin/unwind/resolver.c
+++ b/sbin/unwind/resolver.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolver.c,v 1.3 2019/01/24 15:33:44 florian Exp $ */
+/* $OpenBSD: resolver.c,v 1.4 2019/01/24 17:39:43 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -136,6 +136,8 @@ struct event_base *ev_base;
/* for openssl */
pthread_mutex_t *locks;
+enum unwind_resolver_state global_state = DEAD;
+
void
resolver_sig_handler(int sig, short event, void *arg)
{
@@ -770,6 +772,7 @@ check_resolver_done(void *arg, int rcode, void *answer_packet, int answer_len,
int sec, char *why_bogus, int was_ratelimited)
{
struct check_resolver_data *data;
+ struct unwind_resolver *best;
char *str;
data = (struct check_resolver_data *)arg;
@@ -817,6 +820,18 @@ out:
resolver_unref(data->check_res);
free(data);
+
+ best = best_resolver();
+
+ if (best->state != global_state) {
+ if (best->state < RESOLVING && global_state > UNKNOWN)
+ resolver_imsg_compose_frontend(IMSG_RESOLVER_DOWN, 0,
+ NULL, 0);
+ else if (best->state > UNKNOWN && global_state < RESOLVING)
+ resolver_imsg_compose_frontend(IMSG_RESOLVER_UP, 0,
+ NULL, 0);
+ global_state = best->state;
+ }
}
/* for openssl */
diff --git a/sbin/unwind/unwind.c b/sbin/unwind/unwind.c
index 791a2cbfdbc..07f0086a315 100644
--- a/sbin/unwind/unwind.c
+++ b/sbin/unwind/unwind.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: unwind.c,v 1.1 2019/01/23 13:11:00 florian Exp $ */
+/* $OpenBSD: unwind.c,v 1.2 2019/01/24 17:39:43 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -68,7 +68,7 @@ static int main_imsg_send_config(struct unwind_conf *);
int main_reload(void);
int main_sendboth(enum imsg_type, void *, uint16_t);
void open_dhcp_lease(int);
-void open_ta(void);
+void open_ports(void);
struct unwind_conf *main_conf;
struct imsgev *iev_frontend;
@@ -122,13 +122,11 @@ int
main(int argc, char *argv[])
{
struct event ev_sigint, ev_sigterm, ev_sighup;
- struct addrinfo hints, *res0;
int ch;
int debug = 0, resolver_flag = 0, frontend_flag = 0;
char *saved_argv0;
int pipe_main2frontend[2];
int pipe_main2resolver[2];
- int udp4sock = -1, udp6sock = -1, error;
int frontend_routesock, rtfilter;
int control_fd;
char *csock;
@@ -269,41 +267,6 @@ main(int argc, char *argv[])
if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, &iev_resolver->ibuf))
fatal("could not establish imsg links");
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_PASSIVE;
-
- error = getaddrinfo("127.0.0.1", "domain", &hints, &res0);
- if (!error && res0) {
- if ((udp4sock = socket(res0->ai_family, res0->ai_socktype,
- res0->ai_protocol)) != -1) {
- if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen)
- == -1) {
- close(udp4sock);
- udp4sock = -1;
- }
- }
- }
- freeaddrinfo(res0);
-
- hints.ai_family = AF_INET6;
- error = getaddrinfo("::1", "domain", &hints, &res0);
- if (!error && res0) {
- if ((udp6sock = socket(res0->ai_family, res0->ai_socktype,
- res0->ai_protocol)) != -1) {
- if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen)
- == -1) {
- close(udp6sock);
- udp6sock = -1;
- }
- }
- }
- freeaddrinfo(res0);
-
- if (udp4sock == -1 && udp6sock == -1)
- fatal("could not bind to 127.0.0.1 or ::1 on port 53");
-
if ((control_fd = control_init(csock)) == -1)
fatalx("control socket setup failed");
@@ -317,13 +280,11 @@ main(int argc, char *argv[])
&rtfilter, sizeof(rtfilter)) < 0)
fatal("setsockopt(ROUTE_MSGFILTER)");
- main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock);
- main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock);
main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd);
main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock);
main_imsg_send_config(main_conf);
- if (pledge("stdio rpath sendfd", NULL) == -1)
+ if (pledge("stdio inet rpath sendfd", NULL) == -1)
fatal("pledge");
main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0);
@@ -462,6 +423,9 @@ main_dispatch_frontend(int fd, short event, void *bula)
memcpy(&rtm_index, imsg.data, sizeof(rtm_index));
open_dhcp_lease(rtm_index);
break;
+ case IMSG_OPEN_PORTS:
+ open_ports();
+ break;
default:
log_debug("%s: error handling imsg %d", __func__,
imsg.hdr.type);
@@ -725,3 +689,49 @@ open_dhcp_lease(int if_idx)
main_imsg_compose_frontend_fd(IMSG_LEASEFD, 0, fd);
}
+
+void
+open_ports(void)
+{
+ struct addrinfo hints, *res0;
+ int udp4sock = -1, udp6sock = -1, error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE;
+
+
+ error = getaddrinfo("127.0.0.1", "domain", &hints, &res0);
+ if (!error && res0) {
+ if ((udp4sock = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) != -1) {
+ if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen)
+ == -1) {
+ close(udp4sock);
+ udp4sock = -1;
+ }
+ }
+ }
+ freeaddrinfo(res0);
+
+ hints.ai_family = AF_INET6;
+ error = getaddrinfo("::1", "domain", &hints, &res0);
+ if (!error && res0) {
+ if ((udp6sock = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) != -1) {
+ if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen)
+ == -1) {
+ close(udp6sock);
+ udp6sock = -1;
+ }
+ }
+ }
+ freeaddrinfo(res0);
+
+ if (udp4sock == -1 && udp6sock == -1)
+ fatal("could not bind to 127.0.0.1 or ::1 on port 53");
+
+ main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock);
+ main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock);
+}
diff --git a/sbin/unwind/unwind.h b/sbin/unwind/unwind.h
index d64c6f347f1..916b26f6659 100644
--- a/sbin/unwind/unwind.h
+++ b/sbin/unwind/unwind.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: unwind.h,v 1.1 2019/01/23 13:11:00 florian Exp $ */
+/* $OpenBSD: unwind.h,v 1.2 2019/01/24 17:39:43 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -71,6 +71,9 @@ enum imsg_type {
IMSG_OPEN_DHCP_LEASE,
IMSG_LEASEFD,
IMSG_FORWARDER,
+ IMSG_RESOLVER_DOWN,
+ IMSG_RESOLVER_UP,
+ IMSG_OPEN_PORTS,
IMSG_CTL_RESOLVER_INFO,
IMSG_CTL_RESOLVER_WHY_BOGUS,
IMSG_CTL_RESOLVER_HISTOGRAM,