Re: Opportunistic DoT for unwind(8)
On Sat, Nov 02, 2019 at 08:20:08AM +0100, Otto Moerbeek wrote: > On Fri, Nov 01, 2019 at 10:43:27PM +0100, Remi Locherer wrote: > > > On Fri, Nov 01, 2019 at 09:53:28PM +0100, Florian Obser wrote: > > > On Fri, Nov 01, 2019 at 09:45:37PM +0100, Florian Obser wrote: > > > > On Fri, Nov 01, 2019 at 09:35:07PM +0100, Remi Locherer wrote: > > > > > On Thu, Oct 31, 2019 at 08:14:04PM +0100, Otto Moerbeek wrote: > > > > > > Hi, > > > > > > > > > > > > So here's a new diff that incorporates the bug fix mentioned plus > > > > > > debug printf line changes suggested by Stuart. > > > > > > > > > > > > Please note that this is a diff on top of very recent current, i.e. > > > > > > florian's work he committed today. That means that you need to be > > > > > > up-to-date (including a recent libc update that was committed a few > > > > > > days ago) to be able to test this version. > > > > > > > > > > I upgraded to a snapshot from today, updated the source and applied > > > > > your diff. Then I did the same test as last time using pf to block > > > > > port 53 > > > > > (block return out log inet proto {tcp udp} to !9.9.9.9 port 53). > > > > > > > > > > Result: the non functional type asr is selected instead of the > > > > > forwarder. > > > > > > > > > > $ doas unwindctl status > > > > > captive portal is unknown > > > > > > > > > > selected type status > > > > > recursor dead > > > > > forwarder validating (OppDoT) > > > > > dhcp unknown (OppDoT) > > > > >* asr dead > > > > > $ > > > > > $ getent hosts undeadly.org > > > > > $ echo $? > > > > > 2 > > > > > $ dig +short undeadly.org @9.9.9.9 > > > > > 94.142.241.173 > > > > > $ > > > > > > > > > > Without your patch unwind behaves similar regarding the type > > > > > selection: > > > > > > > > > > $ doas unwindctl status > > > > > captive portal is unknown > > > > > > > > ^ you are creating a not supported configuration. > > > > > > > > When we are behind a captive portal or don't know yet if we are behind > > > > a captive portal resolving is forced to asr. > > > > > > > > That might not be very wise if asr is dead but I currently don't see > > > > how this can happen in practice except with a well aimed foot-gun. > > > > > > Actually, I have an idea how this can happen in practice, please try this: > > > > > > diff --git resolver.c resolver.c > > > index f59860a5e98..5bbc63f60fa 100644 > > > --- resolver.c > > > +++ resolver.c > > > @@ -1282,7 +1282,8 @@ best_resolver(void) > > > > > > if (captive_portal_state == PORTAL_UNKNOWN || captive_portal_state == > > > BEHIND) { > > > - if (resolvers[UW_RES_ASR] != NULL) { > > > + if (resolvers[UW_RES_ASR] != NULL && resolvers[UW_RES_ASR]-> > > > +state != DEAD) { > > > res = resolvers[UW_RES_ASR]; > > > goto out; > > > } > > > > > > > > > > Yes, this makes unwind cope with this situation: > > > > $ unwindctl status > > not behind captive portal > > > > selected type status > > recursor dead > >*forwarder validating > > dhcp dead > > asr dead > > $ > > > > OK remi@ > > > > And with my diff on top of that? Yes, now it works as expected. OK remi@
Re: Opportunistic DoT for unwind(8)
On Fri, Nov 01, 2019 at 10:43:27PM +0100, Remi Locherer wrote: > On Fri, Nov 01, 2019 at 09:53:28PM +0100, Florian Obser wrote: > > On Fri, Nov 01, 2019 at 09:45:37PM +0100, Florian Obser wrote: > > > On Fri, Nov 01, 2019 at 09:35:07PM +0100, Remi Locherer wrote: > > > > On Thu, Oct 31, 2019 at 08:14:04PM +0100, Otto Moerbeek wrote: > > > > > Hi, > > > > > > > > > > So here's a new diff that incorporates the bug fix mentioned plus > > > > > debug printf line changes suggested by Stuart. > > > > > > > > > > Please note that this is a diff on top of very recent current, i.e. > > > > > florian's work he committed today. That means that you need to be > > > > > up-to-date (including a recent libc update that was committed a few > > > > > days ago) to be able to test this version. > > > > > > > > I upgraded to a snapshot from today, updated the source and applied > > > > your diff. Then I did the same test as last time using pf to block port > > > > 53 > > > > (block return out log inet proto {tcp udp} to !9.9.9.9 port 53). > > > > > > > > Result: the non functional type asr is selected instead of the > > > > forwarder. > > > > > > > > $ doas unwindctl status > > > > captive portal is unknown > > > > > > > > selected type status > > > > recursor dead > > > > forwarder validating (OppDoT) > > > > dhcp unknown (OppDoT) > > > >* asr dead > > > > $ > > > > $ getent hosts undeadly.org > > > > $ echo $? > > > > 2 > > > > $ dig +short undeadly.org @9.9.9.9 > > > > 94.142.241.173 > > > > $ > > > > > > > > Without your patch unwind behaves similar regarding the type selection: > > > > > > > > $ doas unwindctl status > > > > captive portal is unknown > > > > > > ^ you are creating a not supported configuration. > > > > > > When we are behind a captive portal or don't know yet if we are behind > > > a captive portal resolving is forced to asr. > > > > > > That might not be very wise if asr is dead but I currently don't see > > > how this can happen in practice except with a well aimed foot-gun. > > > > Actually, I have an idea how this can happen in practice, please try this: > > > > diff --git resolver.c resolver.c > > index f59860a5e98..5bbc63f60fa 100644 > > --- resolver.c > > +++ resolver.c > > @@ -1282,7 +1282,8 @@ best_resolver(void) > > > > if (captive_portal_state == PORTAL_UNKNOWN || captive_portal_state == > > BEHIND) { > > - if (resolvers[UW_RES_ASR] != NULL) { > > + if (resolvers[UW_RES_ASR] != NULL && resolvers[UW_RES_ASR]-> > > +state != DEAD) { > > res = resolvers[UW_RES_ASR]; > > goto out; > > } > > > > > > Yes, this makes unwind cope with this situation: > > $ unwindctl status > not behind captive portal > > selected type status > recursor dead >*forwarder validating > dhcp dead > asr dead > $ > > OK remi@ > And with my diff on top of that? -Otto
Re: Opportunistic DoT for unwind(8)
On Fri, Nov 01, 2019 at 09:53:28PM +0100, Florian Obser wrote: > On Fri, Nov 01, 2019 at 09:45:37PM +0100, Florian Obser wrote: > > On Fri, Nov 01, 2019 at 09:35:07PM +0100, Remi Locherer wrote: > > > On Thu, Oct 31, 2019 at 08:14:04PM +0100, Otto Moerbeek wrote: > > > > Hi, > > > > > > > > So here's a new diff that incorporates the bug fix mentioned plus > > > > debug printf line changes suggested by Stuart. > > > > > > > > Please note that this is a diff on top of very recent current, i.e. > > > > florian's work he committed today. That means that you need to be > > > > up-to-date (including a recent libc update that was committed a few > > > > days ago) to be able to test this version. > > > > > > I upgraded to a snapshot from today, updated the source and applied > > > your diff. Then I did the same test as last time using pf to block port 53 > > > (block return out log inet proto {tcp udp} to !9.9.9.9 port 53). > > > > > > Result: the non functional type asr is selected instead of the forwarder. > > > > > > $ doas unwindctl status > > > captive portal is unknown > > > > > > selected type status > > > recursor dead > > > forwarder validating (OppDoT) > > > dhcp unknown (OppDoT) > > >* asr dead > > > $ > > > $ getent hosts undeadly.org > > > $ echo $? > > > 2 > > > $ dig +short undeadly.org @9.9.9.9 > > > 94.142.241.173 > > > $ > > > > > > Without your patch unwind behaves similar regarding the type selection: > > > > > > $ doas unwindctl status > > > captive portal is unknown > > > > ^ you are creating a not supported configuration. > > > > When we are behind a captive portal or don't know yet if we are behind > > a captive portal resolving is forced to asr. > > > > That might not be very wise if asr is dead but I currently don't see > > how this can happen in practice except with a well aimed foot-gun. > > Actually, I have an idea how this can happen in practice, please try this: > > diff --git resolver.c resolver.c > index f59860a5e98..5bbc63f60fa 100644 > --- resolver.c > +++ resolver.c > @@ -1282,7 +1282,8 @@ best_resolver(void) > > if (captive_portal_state == PORTAL_UNKNOWN || captive_portal_state == > BEHIND) { > - if (resolvers[UW_RES_ASR] != NULL) { > + if (resolvers[UW_RES_ASR] != NULL && resolvers[UW_RES_ASR]-> > +state != DEAD) { > res = resolvers[UW_RES_ASR]; > goto out; > } > > Yes, this makes unwind cope with this situation: $ unwindctl status not behind captive portal selected type status recursor dead *forwarder validating dhcp dead asr dead $ OK remi@
Re: Opportunistic DoT for unwind(8)
On Fri, Nov 01, 2019 at 09:45:37PM +0100, Florian Obser wrote: > On Fri, Nov 01, 2019 at 09:35:07PM +0100, Remi Locherer wrote: > > On Thu, Oct 31, 2019 at 08:14:04PM +0100, Otto Moerbeek wrote: > > > Hi, > > > > > > So here's a new diff that incorporates the bug fix mentioned plus > > > debug printf line changes suggested by Stuart. > > > > > > Please note that this is a diff on top of very recent current, i.e. > > > florian's work he committed today. That means that you need to be > > > up-to-date (including a recent libc update that was committed a few > > > days ago) to be able to test this version. > > > > I upgraded to a snapshot from today, updated the source and applied > > your diff. Then I did the same test as last time using pf to block port 53 > > (block return out log inet proto {tcp udp} to !9.9.9.9 port 53). > > > > Result: the non functional type asr is selected instead of the forwarder. > > > > $ doas unwindctl status > > captive portal is unknown > > > > selected type status > > recursor dead > > forwarder validating (OppDoT) > > dhcp unknown (OppDoT) > >* asr dead > > $ > > $ getent hosts undeadly.org > > $ echo $? > > 2 > > $ dig +short undeadly.org @9.9.9.9 > > 94.142.241.173 > > $ > > > > Without your patch unwind behaves similar regarding the type selection: > > > > $ doas unwindctl status > > captive portal is unknown > > ^ you are creating a not supported configuration. > > When we are behind a captive portal or don't know yet if we are behind > a captive portal resolving is forced to asr. > > That might not be very wise if asr is dead but I currently don't see > how this can happen in practice except with a well aimed foot-gun. Actually, I have an idea how this can happen in practice, please try this: diff --git resolver.c resolver.c index f59860a5e98..5bbc63f60fa 100644 --- resolver.c +++ resolver.c @@ -1282,7 +1282,8 @@ best_resolver(void) if (captive_portal_state == PORTAL_UNKNOWN || captive_portal_state == BEHIND) { - if (resolvers[UW_RES_ASR] != NULL) { + if (resolvers[UW_RES_ASR] != NULL && resolvers[UW_RES_ASR]-> +state != DEAD) { res = resolvers[UW_RES_ASR]; goto out; } > > > > > selected type status > > recursor dead > > forwarder validating > > dhcp dead > >* asr dead > > $ > > > > -- > I'm not entirely sure you are real. > -- I'm not entirely sure you are real.
Re: Opportunistic DoT for unwind(8)
On Fri, Nov 01, 2019 at 09:35:07PM +0100, Remi Locherer wrote: > On Thu, Oct 31, 2019 at 08:14:04PM +0100, Otto Moerbeek wrote: > > Hi, > > > > So here's a new diff that incorporates the bug fix mentioned plus > > debug printf line changes suggested by Stuart. > > > > Please note that this is a diff on top of very recent current, i.e. > > florian's work he committed today. That means that you need to be > > up-to-date (including a recent libc update that was committed a few > > days ago) to be able to test this version. > > I upgraded to a snapshot from today, updated the source and applied > your diff. Then I did the same test as last time using pf to block port 53 > (block return out log inet proto {tcp udp} to !9.9.9.9 port 53). > > Result: the non functional type asr is selected instead of the forwarder. > > $ doas unwindctl status > captive portal is unknown > > selected type status > recursor dead > forwarder validating (OppDoT) > dhcp unknown (OppDoT) >* asr dead > $ > $ getent hosts undeadly.org > $ echo $? > 2 > $ dig +short undeadly.org @9.9.9.9 > 94.142.241.173 > $ > > Without your patch unwind behaves similar regarding the type selection: > > $ doas unwindctl status > captive portal is unknown ^ you are creating a not supported configuration. When we are behind a captive portal or don't know yet if we are behind a captive portal resolving is forced to asr. That might not be very wise if asr is dead but I currently don't see how this can happen in practice except with a well aimed foot-gun. > > selected type status > recursor dead > forwarder validating > dhcp dead >* asr dead > $ > -- I'm not entirely sure you are real.
Re: Opportunistic DoT for unwind(8)
On Thu, Oct 31, 2019 at 08:14:04PM +0100, Otto Moerbeek wrote: > Hi, > > So here's a new diff that incorporates the bug fix mentioned plus > debug printf line changes suggested by Stuart. > > Please note that this is a diff on top of very recent current, i.e. > florian's work he committed today. That means that you need to be > up-to-date (including a recent libc update that was committed a few > days ago) to be able to test this version. I upgraded to a snapshot from today, updated the source and applied your diff. Then I did the same test as last time using pf to block port 53 (block return out log inet proto {tcp udp} to !9.9.9.9 port 53). Result: the non functional type asr is selected instead of the forwarder. $ doas unwindctl status captive portal is unknown selected type status recursor dead forwarder validating (OppDoT) dhcp unknown (OppDoT) * asr dead $ $ getent hosts undeadly.org $ echo $? 2 $ dig +short undeadly.org @9.9.9.9 94.142.241.173 $ Without your patch unwind behaves similar regarding the type selection: $ doas unwindctl status captive portal is unknown selected type status recursor dead forwarder validating dhcp dead * asr dead $
Re: Opportunistic DoT for unwind(8)
Hi, So here's a new diff that incorporates the bug fix mentioned plus debug printf line changes suggested by Stuart. Please note that this is a diff on top of very recent current, i.e. florian's work he committed today. That means that you need to be up-to-date (including a recent libc update that was committed a few days ago) to be able to test this version. -Otto Index: sbin/unwind/parse.y === RCS file: /cvs/src/sbin/unwind/parse.y,v retrieving revision 1.12 diff -u -p -r1.12 parse.y --- sbin/unwind/parse.y 31 Oct 2019 12:51:43 - 1.12 +++ sbin/unwind/parse.y 31 Oct 2019 16:32:27 - @@ -84,7 +84,6 @@ intcheck_pref_uniq(enum uw_resolver_ty static struct uw_conf *conf; static int errors; -static struct uw_forwarder *uw_forwarder; voidclear_config(struct uw_conf *xconf); struct sockaddr_storage*host_ip(const char *); @@ -287,7 +286,9 @@ forwarderopts_l : forwarderopts_l forwa forwarderoptsl : STRING port authname dot { int ret, port; + struct uw_forwarder *uw_fwd; struct sockaddr_storage *ss; + if ((ss = host_ip($1)) == NULL) { yyerror("%s is not an ip-address", $1); free($1); @@ -305,37 +306,53 @@ forwarderoptsl: STRING port authname d else port = $2; - if ((uw_forwarder = calloc(1, - sizeof(*uw_forwarder))) == NULL) + if ($3 != NULL && $4 == 0) { + yyerror("authentication name can only " + "be used with DoT"); + free($1); + YYERROR; + } + + + if ((uw_fwd = calloc(1, + sizeof(*uw_fwd))) == NULL) err(1, NULL); - if ($3 == NULL) - ret = snprintf(uw_forwarder->name, - sizeof(uw_forwarder->name), - "%s@%d", $1, port); - else - ret = snprintf(uw_forwarder->name, - sizeof(uw_forwarder->name), - "%s@%d#%s", $1, port, $3); + if ($4 == DOT) { + if ($3 == NULL) + ret = snprintf(uw_fwd->name, + sizeof(uw_fwd->name), + "%s@%d", $1, port); + else + ret = snprintf(uw_fwd->name, + sizeof(uw_fwd->name), + "%s@%d#%s", $1, port, $3); + } else { + uw_fwd->port = $2; + /* complete string wil be done later */ + ret = snprintf(uw_fwd->name, + sizeof(uw_fwd->name), "%s", $1); + } if (ret < 0 || (size_t)ret >= - sizeof(uw_forwarder->name)) { - free(uw_forwarder); + sizeof(uw_fwd->name)) { + free(uw_fwd); yyerror("forwarder %s too long", $1); free($1); YYERROR; } - free($1); if ($4 == DOT) SIMPLEQ_INSERT_TAIL( &conf->uw_dot_forwarder_list, - uw_forwarder, entry); - else + uw_fwd, entry); + else { SIMPLEQ_INSERT_TAIL( &conf->uw_forwarder_list, - uw_forwarder, entry); + uw_fwd, entry); +
Re: Opportunistic DoT for unwind(8)
On Thu, Oct 31, 2019 at 10:04:07AM +, Stuart Henderson wrote: > Writing as a note to myself to check later when I have more time as > much as anything, is there a hold-off on re-checking if there is a > cert failure (or indeed if DoT port isn't answered), or does it > re-check for every query sent upstream. Also are there excessive > delays if port 853 packets are dropped rather than rejected. > Checking a resolving strategy is decoupled from using a strategy. The global variable struct uw_resolver *resolvers[UW_RES_NONE]; stores the available resolving strategy contexts. best_resolvers() picks the best one according to res_state (VALIDATING > RESOLVING > DEAD) while also consindering the preference (default or from unwind.conf). check_resolver / check_resolver_done are running non blocking via libevent and set res_state in the the resolvers list. So the checking never blocks resolving. When a strategy is found to be DEAD we do an exponatial back-off stopping saturating at ~ 17 minutes (1024 seconds). (re-)checks are triggered when - we got a SERVFAIL for a query - we created a new resolver (config reload, new dhcp forwarders) - we got past a captive portal - we got a RTM_IFINFO on the routing socket (interface going up /down) This is of course the most important part of unwind, resolving stuff is trivial from unwind's point of view, just hand it of to libunbound. Finding out to which libunbound is the tough part. There is still room for improvement. -- I'm not entirely sure you are real.
Re: Opportunistic DoT for unwind(8)
On 2019/10/31 10:18, Otto Moerbeek wrote: > On Wed, Oct 30, 2019 at 08:51:00PM +, Stuart Henderson wrote: > > > - unwind doesn't have keepalives, so it's a new TCP session and TLS > > handshake for every query, which can be bad in some cases (and could get > > expensive with metered mobile data connections). for this reason it > > would be helpful to have a way to disable it (though I suppose "block > > out proto tcp to port 853" works at a pinch). > > unwind should cache thogh, can you observe that? Yes, it does cache. (for "every query" I meant "every query sent to the forwarder") > > - several of the public DNS providers do include their IP in the certificate > > so they could be validated even when picking them up opportunistically. > > though I suppose with unwind this doesn't make a lot of difference as > > it's just going to fallback to cleartext if TLS fails. > > For any Dot mode the validity of the cert is checked, for OppDot the > trust check is only: is the cert signed by a trusted CA. We do not > know which DoT providers include a cert with an IP address, so we > cannot force a check for that. Besides that, I could not get > libunbound to accept a authentication IP like 9.9.9.9, only a name > like "quad9.net". Writing as a note to myself to check later when I have more time as much as anything, is there a hold-off on re-checking if there is a cert failure (or indeed if DoT port isn't answered), or does it re-check for every query sent upstream. Also are there excessive delays if port 853 packets are dropped rather than rejected.
Re: Opportunistic DoT for unwind(8)
On Wed, Oct 30, 2019 at 08:51:00PM +, Stuart Henderson wrote: > On 2019/10/30 15:57, Otto Moerbeek wrote: > > Hi, > > > > I got *very* little feedback on this request for testing. > > > > If not enough enough testing is done, I'll either abandon the diff or > > commit it as-is, introducing bugs that could have been prevented. Both > > are not good. So get going! > > > > -Otto > > > > I'm pointing it at a local dnsdist box via "forwarders { $ip_address }" > and querying unwind while watching tcpdump, I see it correctly using > TCP/853, and status correctly says > > $ unwindctl status > captive portal is unchecked > > selected type status >*forwarder validating (OppDoT) > recursor validating > > > Thanks for testing. > Comments: > > - unwind doesn't have keepalives, so it's a new TCP session and TLS > handshake for every query, which can be bad in some cases (and could get > expensive with metered mobile data connections). for this reason it > would be helpful to have a way to disable it (though I suppose "block > out proto tcp to port 853" works at a pinch). unwind should cache thogh, can you observe that? > > - several of the public DNS providers do include their IP in the certificate > so they could be validated even when picking them up opportunistically. > though I suppose with unwind this doesn't make a lot of difference as > it's just going to fallback to cleartext if TLS fails. For any Dot mode the validity of the cert is checked, for OppDot the trust check is only: is the cert signed by a trusted CA. We do not know which DoT providers include a cert with an IP address, so we cannot force a check for that. Besides that, I could not get libunbound to accept a authentication IP like 9.9.9.9, only a name like "quad9.net". > > - might be useful to show OppDoT in the "best_resolver" line in debug logs? > > > > Sample config from the dnsdist server below for anyone interested, this > is for 1.40rc5 but I think it'll work with the current ports version > (1.3.3) if you remove the addDOHLocal line. > > --snip- > addACL('0.0.0.0/0') > addACL('::/0') > newServer({address="44.33.22.11", name="upstream"}) > addLocal('11.22.33.44:53',{doTCP=true, reusePort=true}) > addTLSLocal("11.22.33.44", "/etc/ssl/xx.fullchain.pem", > "/etc/ssl/private/xx.key",{ doTCP=true, reusePort=true }) > addDOHLocal("11.22.33.44:5343", "/etc/ssl/xx.fullchain.pem", > "/etc/ssl/private/xx.key", "/", {doTCP=true, reusePort=true}) > pc = newPacketCache(1, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, > staleTTL=60, dontAge=false}) > getPool(""):setCache(pc) > --snip-- > Yes , that should work indeed. -Otto
Re: Opportunistic DoT for unwind(8)
On Wed, Oct 30, 2019 at 11:46:36PM +0100, Remi Locherer wrote: > Hi Otto, > > On Wed, Oct 30, 2019 at 03:57:15PM +0100, Otto Moerbeek wrote: > > Hi, > > > > I got *very* little feedback on this request for testing. > > > > If not enough enough testing is done, I'll either abandon the diff or > > commit it as-is, introducing bugs that could have been prevented. Both > > are not good. So get going! > > > > -Otto > > > > I applied your diff and tried with the following config: > > $ unwind -nv > preference { recursor DoT forwarder dhcp } > forwarder { > 9.9.9.9 > } > captive portal { > url "http://captive.apple.com/"; > expected status 200 > expected response > "SuccessSuccess" > auto yes > } > block list "/etc/unwind_blocklist.txt" > $ > > To force unwind to use 9.9.9.9 I tested with this pf rules: > > $ doas pfctl -sr > doas (r...@typhoon.relo.ch) password: > block return log all > pass log all flags S/SA > pass out log on egress inet from (vether0:network) to any flags S/SA nat-to > (egress:0) round-robin > block return in on ! lo0 proto tcp from any to any port 6000:6010 > block return out log inet proto tcp from any to ! 9.9.9.9 port = 53 > block return out log inet proto udp from any to ! 9.9.9.9 port = 53 > block return out log inet6 proto tcp from any to any port = 53 > block return out log inet6 proto udp from any to any port = 53 > block return out log proto tcp all user = 55 > block return out log proto udp all user = 55 > $ > > As expected I can now query 9.9.9.9 but 8.8.8.8 fails: > > $ dig +short undeadly.org @9.9.9.9 > 94.142.241.173 > typhoon ..c/examples$ dig +short undeadly.org @8.8.8.8 > ;; connection timed out; no servers could be reached > $ > > I expected that unwind would choose 9.9.9.9 with OppDoT. But unwind > selects dhcp which is correctly displayed as dead: > > $ unwindctl status > captive portal is unknown > > selected type status > recursor dead > forwarder validating >* dhcp dead > $ > > Port 853 on 9.9.9.9 is not blocked: > > $ nc -zv 9.9.9.9 853 > Connection to 9.9.9.9 853 port [tcp/domain-s] succeeded! > $ nc -zv -u 9.9.9.9 853 > Connection to 9.9.9.9 853 port [udp/domain-s] succeeded! > $ > > Did I do something wrong in unwind.conf? > > Remi No, you found a bug that happens if the recursor is found dead. In that case it would switch off OppDot for forwarders as well. Next version of the diff will have a fix. As for the unwindctl thing, I could not reproduce that one. Dould it be that you did not build and install usr.sbin/unwindctl? It looks like the messaging between unwind and unwindctl is off. -Otto
Re: Opportunistic DoT for unwind(8)
Hi Otto, On Wed, Oct 30, 2019 at 03:57:15PM +0100, Otto Moerbeek wrote: > Hi, > > I got *very* little feedback on this request for testing. > > If not enough enough testing is done, I'll either abandon the diff or > commit it as-is, introducing bugs that could have been prevented. Both > are not good. So get going! > > -Otto > I applied your diff and tried with the following config: $ unwind -nv preference { recursor DoT forwarder dhcp } forwarder { 9.9.9.9 } captive portal { url "http://captive.apple.com/"; expected status 200 expected response "SuccessSuccess" auto yes } block list "/etc/unwind_blocklist.txt" $ To force unwind to use 9.9.9.9 I tested with this pf rules: $ doas pfctl -sr doas (r...@typhoon.relo.ch) password: block return log all pass log all flags S/SA pass out log on egress inet from (vether0:network) to any flags S/SA nat-to (egress:0) round-robin block return in on ! lo0 proto tcp from any to any port 6000:6010 block return out log inet proto tcp from any to ! 9.9.9.9 port = 53 block return out log inet proto udp from any to ! 9.9.9.9 port = 53 block return out log inet6 proto tcp from any to any port = 53 block return out log inet6 proto udp from any to any port = 53 block return out log proto tcp all user = 55 block return out log proto udp all user = 55 $ As expected I can now query 9.9.9.9 but 8.8.8.8 fails: $ dig +short undeadly.org @9.9.9.9 94.142.241.173 typhoon ..c/examples$ dig +short undeadly.org @8.8.8.8 ;; connection timed out; no servers could be reached $ I expected that unwind would choose 9.9.9.9 with OppDoT. But unwind selects dhcp which is correctly displayed as dead: $ unwindctl status captive portal is unknown selected type status recursor dead forwarder validating * dhcp dead $ Port 853 on 9.9.9.9 is not blocked: $ nc -zv 9.9.9.9 853 Connection to 9.9.9.9 853 port [tcp/domain-s] succeeded! $ nc -zv -u 9.9.9.9 853 Connection to 9.9.9.9 853 port [udp/domain-s] succeeded! $ Did I do something wrong in unwind.conf? Remi
Re: Opportunistic DoT for unwind(8)
On 2019/10/30 15:57, Otto Moerbeek wrote: > Hi, > > I got *very* little feedback on this request for testing. > > If not enough enough testing is done, I'll either abandon the diff or > commit it as-is, introducing bugs that could have been prevented. Both > are not good. So get going! > > -Otto > I'm pointing it at a local dnsdist box via "forwarders { $ip_address }" and querying unwind while watching tcpdump, I see it correctly using TCP/853, and status correctly says $ unwindctl status captive portal is unchecked selected type status *forwarder validating (OppDoT) recursor validating Comments: - unwind doesn't have keepalives, so it's a new TCP session and TLS handshake for every query, which can be bad in some cases (and could get expensive with metered mobile data connections). for this reason it would be helpful to have a way to disable it (though I suppose "block out proto tcp to port 853" works at a pinch). - several of the public DNS providers do include their IP in the certificate so they could be validated even when picking them up opportunistically. though I suppose with unwind this doesn't make a lot of difference as it's just going to fallback to cleartext if TLS fails. - might be useful to show OppDoT in the "best_resolver" line in debug logs? Sample config from the dnsdist server below for anyone interested, this is for 1.40rc5 but I think it'll work with the current ports version (1.3.3) if you remove the addDOHLocal line. --snip- addACL('0.0.0.0/0') addACL('::/0') newServer({address="44.33.22.11", name="upstream"}) addLocal('11.22.33.44:53',{doTCP=true, reusePort=true}) addTLSLocal("11.22.33.44", "/etc/ssl/xx.fullchain.pem", "/etc/ssl/private/xx.key",{ doTCP=true, reusePort=true }) addDOHLocal("11.22.33.44:5343", "/etc/ssl/xx.fullchain.pem", "/etc/ssl/private/xx.key", "/", {doTCP=true, reusePort=true}) pc = newPacketCache(1, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false}) getPool(""):setCache(pc) --snip--
Re: Opportunistic DoT for unwind(8)
Hi Otto, * Otto Moerbeek wrote: > Hi, > > I got *very* little feedback on this request for testing. > > If not enough enough testing is done, I'll either abandon the diff or > commit it as-is, introducing bugs that could have been prevented. Both > are not good. So get going! I have your diff running for a couple of days and I can at least confirm that it doesn't break an existing setup. I have several upstream DoT servers configured but no opportunistic DoT setup. HTH and cheers Matthias
Re: Opportunistic DoT for unwind(8)
Hi, I got *very* little feedback on this request for testing. If not enough enough testing is done, I'll either abandon the diff or commit it as-is, introducing bugs that could have been prevented. Both are not good. So get going! -Otto
Re: Opportunistic DoT for unwind(8)
On 2019/10/24 11:48, Paul de Weerd wrote: > The downside of using your own resolver (e.g. by running unbound on > your laptop), its traffic is more easily tied to a specific user. > There's an anonymizing power in using a bigger (shared) resolver (with > the downside that you then give your queries to a resolver that's > probably outside of your control - different risks and all that) And the downside of using a shared non-ISP resolver is that CDNs or services using geolocation on the DNS requests won't have information about your network location, so you may end up served by a suboptimal server or CDN node (in the worst case you may end up with a very unsuitable one, for example perhaps from a country halfway around the world). The notable exception here of course is where the CDN also runs their own public DNS resolver (hi Cloudflare!).
Re: Opportunistic DoT for unwind(8)
On Thu, Oct 24, 2019 at 12:24:22PM +0200, Otto Moerbeek wrote: > On Thu, Oct 24, 2019 at 11:27:24AM +0100, Kevin Chadwick wrote: > > > > > > The purpose of unwind is to provide secure DNS services even when > > > the available nameservers are broken or filtered like in many hotels. > > > To do that, it prefers DNSSEC whenever possible and changes to do > > > resolving by itself if needed. > > > > > > DNSSEC only offers integrity and authenticity. To protect > > > eavesdropping on the requests in transit, encryption is needed, as > > > offered by e.g. DNS over TLS (DoT) and DNS over HTTP (DoT). unwind > > > > Before I jump aboard with DNSSECs failings in mind on my own networks rather > > than the mentioned hotel scenario. I believe but I am still not certain that > > services like PowerDNS have secure channels to the main primary DNS servers > > that > > apparently do not scale for the rest of us? Otherwise I worry that the > > network > > security target is a more singular centralised target compared to e.g. > > unbound. > > > > Guess what the default config of unwind does: it runs a local resolver > and learns from DHCP. It will select either one, with DNSSEC working > preferred. DNSSEC operations if sometimes blocked by crappy > middleware. Unwind's resolver is basically a buit-in simple unbound, > the code uses libunbound. > > So the default config of unwind addresss both your concerns. > > -Otto > To elaborate: unwind checks if DNSSEC works on any source and switches back to non-validation if needed. The whole point of unwind is that it will try to provide the best DNS service possibe in any circumstance. -Otto
Re: Opportunistic DoT for unwind(8)
On Thu, Oct 24, 2019 at 11:27:24AM +0100, Kevin Chadwick wrote: > > > The purpose of unwind is to provide secure DNS services even when > > the available nameservers are broken or filtered like in many hotels. > > To do that, it prefers DNSSEC whenever possible and changes to do > > resolving by itself if needed. > > > > DNSSEC only offers integrity and authenticity. To protect > > eavesdropping on the requests in transit, encryption is needed, as > > offered by e.g. DNS over TLS (DoT) and DNS over HTTP (DoT). unwind > > Before I jump aboard with DNSSECs failings in mind on my own networks rather > than the mentioned hotel scenario. I believe but I am still not certain that > services like PowerDNS have secure channels to the main primary DNS servers > that > apparently do not scale for the rest of us? Otherwise I worry that the network > security target is a more singular centralised target compared to e.g. > unbound. > Guess what the default config of unwind does: it runs a local resolver and learns from DHCP. It will select either one, with DNSSEC working preferred. DNSSEC operations if sometimes blocked by crappy middleware. Unwind's resolver is basically a buit-in simple unbound, the code uses libunbound. So the default config of unwind addresss both your concerns. -Otto
Re: Opportunistic DoT for unwind(8)
On Thu, Oct 24, 2019 at 11:27:24AM +0100, Kevin Chadwick wrote: | | > The purpose of unwind is to provide secure DNS services even when | > the available nameservers are broken or filtered like in many hotels. | > To do that, it prefers DNSSEC whenever possible and changes to do | > resolving by itself if needed. | > | > DNSSEC only offers integrity and authenticity. To protect | > eavesdropping on the requests in transit, encryption is needed, as | > offered by e.g. DNS over TLS (DoT) and DNS over HTTP (DoT). unwind | | Before I jump aboard with DNSSECs failings in mind on my own networks rather | than the mentioned hotel scenario. I believe but I am still not certain that | services like PowerDNS have secure channels to the main primary DNS servers that | apparently do not scale for the rest of us? Otherwise I worry that the network | security target is a more singular centralised target compared to e.g. unbound. These solutions (DoT / DoH, or the older DNSCrypt) encrypt DNS queries from client to resolver, authorities are not available through these protocols (yet). This topic of DNS has lots of different attack vectors and risks associated with it. Slowly but surely, things are improving .. but there's no big-bang solution that gets rid of all the issues in one go. If you want to use encrypted DNS from your client to your own resolver then you can also do that. Unbound is in base, look at the tls-service-* and tls-port: options in unbound.conf(5). The downside of using your own resolver (e.g. by running unbound on your laptop), its traffic is more easily tied to a specific user. There's an anonymizing power in using a bigger (shared) resolver (with the downside that you then give your queries to a resolver that's probably outside of your control - different risks and all that) If you don't want to trust the freely available PowerDNS recursor then that's your prerogative; it's just an easy option that's available should you wish to test Otto's diff. Cheers, Paul 'WEiRD' de Weerd -- >[<++>-]<+++.>+++[<-->-]<.>+++[<+ +++>-]<.>++[<>-]<+.--.[-] http://www.weirdnet.nl/
Re: Opportunistic DoT for unwind(8)
> The purpose of unwind is to provide secure DNS services even when > the available nameservers are broken or filtered like in many hotels. > To do that, it prefers DNSSEC whenever possible and changes to do > resolving by itself if needed. > > DNSSEC only offers integrity and authenticity. To protect > eavesdropping on the requests in transit, encryption is needed, as > offered by e.g. DNS over TLS (DoT) and DNS over HTTP (DoT). unwind Before I jump aboard with DNSSECs failings in mind on my own networks rather than the mentioned hotel scenario. I believe but I am still not certain that services like PowerDNS have secure channels to the main primary DNS servers that apparently do not scale for the rest of us? Otherwise I worry that the network security target is a more singular centralised target compared to e.g. unbound.
Re: Opportunistic DoT for unwind(8)
On Wed, Oct 23, 2019 at 02:40:53PM +0200, Otto Moerbeek wrote: > Hi, > > The patch below add opportunistic DoT to unwind. Some background > info: > > The purpose of unwind is to provide secure DNS services even when > the available nameservers are broken or filtered like in many hotels. > To do that, it prefers DNSSEC whenever possible and changes to do > resolving by itself if needed. > > DNSSEC only offers integrity and authenticity. To protect > eavesdropping on the requests in transit, encryption is needed, as > offered by e.g. DNS over TLS (DoT) and DNS over HTTP (DoT). unwind That second DoT should be DoH. > already supports DoT for forwarders but only when explicitly > configured to do so. > > This diff makes unwind try DoT for forwarders and nameservers learned > via DHCP and fall back to plaintext if it does not work. > > Which DoT servers to use for testing? Most quad-whatever open DNS > resolvers like 9.9.9.9 support DoT so you can specify them as a > forwarder. But please note the privacy policies and realize they see > all your DNS queries. You might consider reading [1] which offers DoT > on 136.144.215.158 as well and has a good privacy policy and is in Not that the mentioned privacy page talsk about DoH and does not mention DoT, but the IP does offer DoT. [1] https://powerdns.org/doh/privacy.html -Otto
Re: Opportunistic DoT for unwind(8)
On Wed, Oct 23, 2019 at 02:40:53PM +0200, Otto Moerbeek wrote: > [1] https://doh.powerdns.org/doh/privacy.html Should be https://powerdns.org/doh/privacy.html
Opportunistic DoT for unwind(8)
Hi, The patch below add opportunistic DoT to unwind. Some background info: The purpose of unwind is to provide secure DNS services even when the available nameservers are broken or filtered like in many hotels. To do that, it prefers DNSSEC whenever possible and changes to do resolving by itself if needed. DNSSEC only offers integrity and authenticity. To protect eavesdropping on the requests in transit, encryption is needed, as offered by e.g. DNS over TLS (DoT) and DNS over HTTP (DoT). unwind already supports DoT for forwarders but only when explicitly configured to do so. This diff makes unwind try DoT for forwarders and nameservers learned via DHCP and fall back to plaintext if it does not work. Which DoT servers to use for testing? Most quad-whatever open DNS resolvers like 9.9.9.9 support DoT so you can specify them as a forwarder. But please note the privacy policies and realize they see all your DNS queries. You might consider reading [1] which offers DoT on 136.144.215.158 as well and has a good privacy policy and is in Dutch jurisdiction. If you do want to run DoT yourself there's dnsdist in ports. Some ISPs offer DoT as well. How to test? Apply the diff in /usr/src and rebuild sbin/unwind and usr.sbin/unwindctl. - read the unwind(8) man page about changing dhclient.conf if you use DHCP (this is not related to this diff but important anyway). - make sure that if you have an existing working setup it does not break with this diff. - check if DoT is used when appriopiate by using the unwindctl command. Even if you do not want to run DoT at least make sure existing stuff does not break. I might need to add a config option to tune the always on behaviour of opportunistic DoT, but only want to do that if I have evidence it is needed. Happy testing! -Otto [1] https://doh.powerdns.org/doh/privacy.html Index: sbin/unwind/parse.y === RCS file: /cvs/src/sbin/unwind/parse.y,v retrieving revision 1.11 diff -u -p -r1.11 parse.y --- sbin/unwind/parse.y 21 Oct 2019 07:16:09 - 1.11 +++ sbin/unwind/parse.y 23 Oct 2019 12:28:42 - @@ -84,7 +84,6 @@ intcheck_pref_uniq(enum uw_resolver_ty static struct uw_conf *conf; static int errors; -static struct uw_forwarder *uw_forwarder; voidclear_config(struct uw_conf *xconf); struct sockaddr_storage*host_ip(const char *); @@ -286,7 +285,9 @@ forwarderopts_l : forwarderopts_l forwa forwarderoptsl : STRING port authname dot { int ret, port; + struct uw_forwarder *uw_fwd; struct sockaddr_storage *ss; + if ((ss = host_ip($1)) == NULL) { yyerror("%s is not an ip-address", $1); free($1); @@ -304,37 +305,53 @@ forwarderoptsl: STRING port authname d else port = $2; - if ((uw_forwarder = calloc(1, - sizeof(*uw_forwarder))) == NULL) + if ($3 != NULL && $4 == 0) { + yyerror("authentication name can only " + "be used with DoT"); + free($1); + YYERROR; + } + + + if ((uw_fwd = calloc(1, + sizeof(*uw_fwd))) == NULL) err(1, NULL); - if ($3 == NULL) - ret = snprintf(uw_forwarder->name, - sizeof(uw_forwarder->name), - "%s@%d", $1, port); - else - ret = snprintf(uw_forwarder->name, - sizeof(uw_forwarder->name), - "%s@%d#%s", $1, port, $3); + if ($4 == DOT) { + if ($3 == NULL) + ret = snprintf(uw_fwd->name, + sizeof(uw_fwd->name), + "%s@%d", $1, port); + else + ret = snprintf(uw_fwd->name, + sizeof(uw_fwd->name), + "%s@%d#%s", $1, port, $3); + } else { + uw_f