On Fri, 2015-06-12 at 14:32 -0400, Paul Wouters wrote: > On Fri, 12 Jun 2015, Dan Williams wrote: > > >> That is why HTTP redirection and DNS failure have to be detected by > >> whatever is the "hot spot detector". Both items weigh in on triggering > >> a hotspot logon window. > > > > Agreed. But how does the DNS failure actually get relayed to the thing > > doing the HTTP request, when unbound + DNSSEC is involved? That's one > > point I'm very unclear on. > > In hotspot mode (dnssec-trigger's version of hotspot mode) > /etc/resolv.conf contains the DHCP supplied DNS servers. Those are used > to determine both the "DNS cleanliness" state, and is also used to fetch > the fedoraproject hot spot detection page. The unbound DNS server, while > running, is not used at all for anything, as resolv.conf does not point > to it. Unfortunately, because this is not isolated to dnssec-triggerd, > all applications doing DNS during this time get crap/dangerous DNS > resolves, leading to add the bad certificate warning popups. And why I > was hoping to isolate that with either a network namespace, or other > solution that prevents us from requiring to affect the whole system > by changing resolv.conf. > > If selecting "cache only", then resolv.conf points to 127.0.0.1 and > unbound is configured with a "DNS forwarder" for everything set to > 127.0.0.127 so no DNS lookups ever leave the host. > > >>> 1. NM connects to a new network > >>> 2. NM updates DNS information > >> > >> I don't know what 2) means. If it means rewriting /etc/resolv.conf or > >> the unbound forwarder configuration, we have already lost if the DNS > >> was malicious (and/or a hotspot DNS) > > > > It means whatever "dns" action was set in NM, either writing > > resolv.conf, not touching anything (dns=none), sending split DNS to > > unbound (dns=unbound), or to dnsmasq (dns=dnsmasq), etc. In this case > > I'll presume dns=unbound. > > Ahh thanks. > > >> dnssec-trigger currently detects the difference by also checking for an > >> http hotspot redirect using http://fedoraproject.org/static/hotspot.txt > >> If no http redirect, then DNS is broken and it tries to work around it > >> by becoming a full iterative resolver or doing DNS over TCP or DNS over > >> TLS. and if it all fails, presents the "insecure or cache only" dialog. > > > > NM also checks for redirection. > > > > Though, what do you mean by "if no HTTP redirect, then DNS is broken"? > > Sorry I meant "If no http redirect, and DNS is broken, then it tries to > work around by ...". That is, when there is an http redirect, there is > no point doing anything about DNS because after authenticating to the > hotspot, DNS might turn out to be either fine or broken for other > reasons. > > >> 1) NM detects a new nework, but doesn't tell the applications that there > >> is network connectivity yet. So firefox won't throw HTTPS warnings > >> and pidgin/IM won't throw https warnings. Because as far as they know > >> the network is still down. > > > > Agreed. Right now we have "connectivity" states, but they are all > > determined after the interface is signaled as "connected". We can do > > some work here to indicate connectivity status on this interface before > > indicating to applications that the interface is fully connected. > > That would be awesome! > > >> 2) NM/dnssec-trigger does the HTTP and DNS probing and prompting using > >> a dedicated container and any DNS requests in that container are > >> thrown away with the container once hotspot has been authenticated. > >> This would allow us to never have resolv.conf on the host be > >> different from 127.0.0.1. (currently, it needs to put in the hotspot > >> DNS servers for the hotspot logon, exposing other applications to > >> fake DNS) > > > > I'm not sure a container really needs to be involved as long as the DNS > > resolution can be done without hitting resolv.conf. That's not hugely > > hard to do I think > > True. In fact with unbound it is pretty trivial to do. The equivalent > unbound python code for that would be: > > import unbound > > ctx = unbound.ub_ctx() > ctx.resolvconf("/this/networks/respresentation/of/resolv.conf") Hmm, that doesn't really allow for split DNS though since it uses the resolv.conf format? Ideally we could just send unbound a list of server +domain, and then a fallback of server+"*" for anything not matching that list. > any resolve calls made will use the non-system resolv.conf's nameserver > addresses. > > So the hotspot check could be: > > ctx = unbound.ub_ctx() > ctx.add_ta_file(rootanchor) # DNSSEC root key > ctx.resolvconf("/this/networks/respresentation/of/resolv.conf") > status, result = ctx.resolve("fedoraproject.org", unbound.RR_TYPE_A) > if not result.havedata or not result.secure: > # we're captive because fedoraproject.org is DNSSEC signed and > # we got an error (forged) response > # Redo query with a non-DNSSEC cache to get forged A record to > # authenticate to the hotspot > insecurectx = unbound.ub_ctx() > insecurectx.resolvconf("/this/networks/respresentation/of/resolv.conf") > status, result = insecurectx.resolve("fedoraproject.org", unbound.RR_TYPE_A) > if result.havedata: > addr = result.data.address_list[0] > # give addr to the captive portal logon HTTP engine > insecurectx.ub_close() > else: > if result.havedata: > # check for HTTP interception - we might still be captive > addr = result.data.address_list[0] > # give addr to the captive portal logon HTTP engine > ctx.ub_close() Ok, so as I asked about earlier, the connectivity checking is a two-step process then: 1) look up the IP address of your connectivity server using DNS, and if the result is insecure then you know your DNS is hijacked (eg, hotspot/portal) or your local DNS server is utterly broken 2) if #1 succeeded then continue to the HTTP connectivity check > Things are a little tricker because the hotspot likely stupidly uses > even more DNS calls to build up the logon page, so whatever the http > rendering agent is (eg xdg-open or firefox or whatever) needs to keep > using this unbound cache and not fall back to the system default one. Yeah, whatever thing handles the logon (GNOME Shell, etc) would have to have a method to inject nameservers that the web sub-process would use exclusively instead of the system namesevers. Then the process would go something like this: 0) resolve.conf/unbound/whatever DNS is unpopulated 1) NetworkManager looks up connectivity server IP address 2) NetworkManager does the connectivity check using that IP address 3) assuming either #1 or #2 fails, NM signals HOTSPOT connectivity state and provides the DNS information via the API, including any DHCP/WISPR information received from the network 4) Hotspot agent (GNOME Shell, KDE, whatever) sees the HOTSPOT state, reads the DNS servers, and spawns a sandboxed web browser using the preliminary DNS servers 5) User completes hotspot logon or rejection, user agent signals that hotspot operations complete 6) NetworkManager re-does connectivity checks, and assuming the result is "success", indicates CONNECTED connectivity state or something like that. But these steps could be split out into a small, single-purpose connectivityd that used information from NM/other sources and was triggered by NM/other sources, and then NM wouldn't have to do it. NM could still proxy the state since NM would know when to trigger connectivity checks anyway. But I digress. > > Then once the hotspot login is completed, we must re-do the connectivity > > check to ensure that we do indeed have access to the full internet. If > > we do, then we can finally signal "connected". If it fails again, then > > we either show the hotspot login window again, or somehow indicate that > > hotspot login failed. > > > Note that none of this mentions DNS to the user at all yet... so what > > happens if the hotspot login succeeds, we get connectivity to the > > internet, but the hotspot DNS doesn't support DNSSEC correctly? > > If HTTP is no longer redirected (dnssec-trigger keeps probing while you > pull your credit card out), it assumes you have successfully authenticated > to the hotspot. It re-tests the supplied DNS servers. If these are still > determined to be too broken for using DNSSEC (eg too old bind, > dnsmasq) it tries to (silently) become a full itterative nameservers, > eg it will not use any forwards and do all the DNS work itself. If this > also fails, for example because the network blocks port 53 to all but > its own DNS servers, dnssec-trigger tries the other modes of DNS over > TCP/SSL. If any of this works the user isn't even consulted. Only when > all of this fails do we need to contact the user and ask them to go > "insecure" or "cache only" This is the part that I feel like unbound should do, or if not unbound then whatever local caching nameserver we do have. Perhaps that's already built into unbound and only controlled by dnssec-trigger, but it seems like something more integral to the resolver than outside of it? Dan -- devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/devel Fedora Code of Conduct: http://fedoraproject.org/code-of-conduct