DNS is a hierarchical distributed database containing information about hosts and services. DNSSEC is a mechanism to detect and prevent man-in-the-middle attacks resulting in fake DNS data accepted by the clients. One of the main goals is to avoid user interaction and especially the need to configure exceptions every now and then.
When using DNSSEC, DNS data are retrieved along with respective DNSSEC records usually from a DNSSEC-compliant recursive DNS server. The validator then uses a local copy of root DNSSEC public key together with the retrieved DNSSEC data to build and verify the chain of trust. At the end of the process we have a cryptograhpical proof of validity or invalidity of the obtained data. The trust for the DNS data verification derives from trust for the DNS root keys and applied cryptography.
When DNSSEC is enabled and DNSSEC data cannot be retrieved, security is maintained and DNS failure is reported. For proper DNS operation, at least one compliant recursive DNS server is needed.
As long as DNSSEC is enabled, applications are protected from receiving fake DNS data for DNS secured domains. This technique covers all sorts of applications including those that don't contain any explicit security features.
Keeping DNSSEC enabled all the time may be a challenge especially for road warrior setups and other mobile devices. The word opportunistic stands for the fact that the end user application doesn't check whether the received data are secure or not.
When DNSSEC is disabled, the security features are gone but functionality is otherwise intact.
Applications and libraries with DNSSEC support
In addition, applications and libraries may choose to treat validated DNS data specially and use them for security purposes. This allows for storing security data (e.g. certificate fingerprint, IPSec keys, etc.) in DNS and authenticating them using DNSSEC.
The chain of trust is thus extended from the authenticated data to other security mechanisms. That way DNSSEC indirectly covers other protocols than just DNS and helps to mitigate attacks relying on the name resolution as one of the attack vectors.
Security data stored in DNS and secured by DNSSEC are typically fingerprints of various keys and certificates and DNSSEC provides a way to validate the data integrity and authenticity and even detect when an attacker is trying to hide the data from us.
When DNSSEC is disabled, the application will treat all DNS data as insecure and act accordingly.
- Automatically or manually configured DNS servers should be tested for the ability to provide DNSSEC data. They should be used for retrieving DNSSEC data when possible. Fallback methods should be used when configured servers turn out to be broken. User should be notified when there's no way to contact a working name server and they should be presented with a possibility to turn off DNSSEC temporarily. In Fedora Workstation no dialog will be displayed ATM and the DNSSEC validation is turned off automatically in such situation.
- Overhead caused by DNSSEC testing and validation is kept reasonable thanks to the local DNS cache.
Application API (not part of the Default DNS resolver change)
- Applications and libraries can trust DNS data from glibc resolver is are marked as DNSSEC secure.
- When DNSSEC is enabled, DNS data from domains secured by DNSSEC are properly validated and marked.
- Name resolution works even when DNSSEC is disabled but all data is marked as DNSSEC insecure.
Applications and cryptographic libraries
- TLS libraries should be able to make use of DNS data secured by DNSSEC when available.
- SSH host keys should be verified using DNSSEC when available.
- And more...
To achieve the stated goals we need to perform DNSSEC validation on every client machine (except a couple of Cloud and containers use-cases) and allow application to use DNS as a trusted source of security data (certificate fingerprints, SSH fingerprints, ...).
Fedora is using a combination of NetworkManager, dnssec-trigger and Unbound to perform all the configuration tasks, DNS data retrieval and DNSSEC validation.
Contemporary networks are full of broken DNS proxies so we need to jump through various hoops to get DNSSEC data. Therefore the configuration task consists not only of transporting the configuration from NetworkManager to unbound but also of testing the recursive DNS servers for the ability to deliver global DNSSEC data that is then used for validation.
When dnssec-trigger is running, it is expected to be the only tool
/etc/resolv.conf. Unbound also accepts manual
configuration from configuration files and using the command line
The main network configuration tool is NetworkManager. When using DNSSEC it is combined with dnssec-trigger via a script shipped in the dnssec-trigger package. The script is run on every network configuration change and the current configuration is fetched from NetworkManager through the libnm API.
With or without DNSSEC, NetworkManager gathers the list of recursive name servers from DHCP, VPN connections and/or static configuration. The purpose of those name servers is to answer DNS queries including those for DNSSEC records. Those name servers are not meant to be trusted for anything else than attempting to answer the queries and especially not for performing DNSSEC validation.
When DNSSEC is not in use, the easiest way to handle the list of name servers is to put them into
/etc/resolv.conf so that the stub resolver can do its job.
/etc/resolv.conf doesn't support advanced configuration (e.g. split-DNS commonly used with VPN connections), it is often useful to instead configure a local recursive DNS server (e.g dnsmasq or unbound) with the name server list and point the stub resolver to the local host using
When DNSSEC is in use, after gathering the recursive resolvers, NetworkManager notifies dnssec-trigger that the network configuration changed. Dnssec-trigger then fetches the current configuration from NetworkManager performs probing of the recursive resolvers. Finally dnssec-trigger reconfigures The local Unbound instance with the proper set of recursive resolvers for the global name resolution and potentially with some additional resolvers to handle specific domains (this is the split-DNS handling). In this case the stub resolver should use the local Unbound instance. Ideally the stub resolver should be instructed that the local Unbound instance is not just an ordinary recursive name server but also a trusted DNSSEC validator.
Problem: There is currently no way to distinguish ordinary recursive name servers and trusted DNSSEC validators in the stub resolver configuration, see later. However this is NOT part of the Default DNS resolver change.
Captive portals (aka hotspots)
Captive portal detection needs to allow the user to log into the captive portal without being restricted by DNSSEC validation. The user might also want to access the hotspot resources even after logging also without being restricted by DNSSEC validation if the hotspot uses a hijacked domain name that is not designated as insecure in the global DNS tree.
All of the above has to be done in a way that doesn't allow an attacker to compromise security.
Previously the Captive portal detection and login has been handled by the dnssec-trigger panel. However after discussions with NetworkManager and GNOME developers we decided that NetworkManager will be the only tool doing the detection and others will only consume the information from it. This requires implementation of notifications on connectivity state changes in NetworkManager ([]).
Originally the Hotspot sign on was handled by dnssec-trigger panel. After discussion with GNOME developers, this part will be handled only by GNOME Shell in Fedora Workstation. When doing the Hotspot sign on, GNOME will not rely on correct information being present in the
/etc/resolv.conf and rather fetch the DNS resolvers to be used directly from NetworkManager and use them in a sandboxed browser window for sign on.
Some networks are so broken that even without captive portal they are not able to deliver DNSSEC data to the clients. In that case dnssec-trigger will setup Unbound to tunnel the Queries over SSL to other DNS servers on the Internet (Fedora Infra or public DNS root). Naturally, local/internal domains need to be available.
The connection provided resolvers will be used at least for the unsigned part of the DNS tree. Note that this relies on the "mixed-mode" Unbound module to be used. The module is not yet contributed to the Upstream, but the default DNS resolver change owners are working on getting everything done for Fedora 24.
- libreswan ?
- systemd-resolved/networkd ?
- connman ?
Stub resolver requirements
Applications and cryptographic libraries need an interface to get DNS data that is either verified using a trusted DNSSEC validator (e.g. a local unbound instance) or declared as not trusted (not verified using DNSSEC). False positive answers are unacceptable because treating ordinary DNS data as DNSSEC secure data would allow attacks on applications that use DNSSEC secure data for security purposes.
Example: SSH server fingerprint verification
Imagine that OpenSSH client is verifying server's fingerprint against the value obtained from DNS instead of asking the user. If the client accepted a fake response with faked server's fingerprint then everything is doomed.
The assumption here is that (something like) dnssec-trigger properly configures local resolver to do DNSSEC validation locally so that a fake DNS answer is detected and never gets it to the application and a DNSSEC secure DNS data is distinguished from DNS insecure data. The open question is how to pass the information about security status to all the parties. The mechanism needs to be simple so other resolver libraries like e.g. python-dns can follow the same rules and use the same logic as libc.
Those distribution policies have been correct for ages. Before DNSSEC was created, no one would question them.
We were looking for a solution where:
1) Application or security library can trust the data from libc resolver including security information.
2) Resolver can provide unauthenticated DNS data when in non-DNSSEC mode and the list of recursive name servers is configured by a system administrator or an automated tool.
3) Resolver can provide authenticated DNS data when in DNSSEC mode and the list of trusted resolvers is provided by the system administrator (rarely) or by an automated tool (in most cases giving just 127.0.0.1).
The most important thing is that the application never receives authenticated data that were only verified by an ordinary recursive server. That would mean an implicit trust in an unauthorized and unexpected DNSSEC validator.
Note that a recursive name server is typically a host on the local network announced by DHCP while a trusted validator is typically running on the local machine which itself is talking to a recursive name server.
Case: Captive portal, broken DNSSEC or DNSSEC turned off
We are in hot-spot sign-on mode or validating resolver is unavailable for some reason (early boot, resource constraints, Docker container [finally!], and so on):
In this case *nothing* can be trusted. Resolver might return faked answers and we have no means to check if declared trustworthiness is correct or not. Again, we need to be 100 % sure from the cryptographical point of view. Application must not receive any DNS answer marked as DNSSEC secure in this mode.
Case: DNSSEC fully configured
Validating resolver is up, running, properly configured, and the path to the resolver is trusted - it might be running on localhost or we are in Docker container and we trust the host and so on.
In this case we trust to the result of validation indicated by AD bit. Application will receive the answer marked as trusted if the resolver tells us to do so by AD bit in the DNS reply.
The current implementation in glibc doesn't achieve the goals stated above and doesn't prevent the security problem of implicitly using foreign recursive name servers as trusted DNSSEC validators.
We have an experimental implementation using '/etc/resolv-secure.conf' that solves the problem. I'm looking forward to see any alternatives. The issue has been holding back DNSSEC deployment for long and might cause a lot of damage.
Solution: Separate file where all DNS servers are DNSSEC validators
We have an experimental solution that relies on a separate
resolv-secure.conf file. As opposed to
/etc/resolv.conf typically containing the list of recursive name servers,
resolv-secure.conf contains a list of trusted DNSSEC validators in form of validating DNSSEC servers. The list typically includes a single DNSSEC validator which is running on the local host.
- The file can be separately protected using mandatory access control. The whole stub resolver configuration is protected.
- The syntax is identical to
/etc/resolv.conf. On a DNSSEC enabled system,
/etc/resolv.confcan be just a symlink to
Use a special
- The configuration file could not be protected by mandatory access control while at the same time allowing tools to write a
/etc/resolv.confconfiguration when not using DNSSEC.
(or for example
/etc/resolv.conf configuration as secure when providing the list of secure DNSSEC validators.
- An existing tool might rewrite the list of name servers and keep the unknown options including
/etc/resolv.conf configuration explicitly as insecure unless providing the list of secure DNSSEC validators.
/etc/resolv.conffiles would be wrongly considered secure for DNSSEC validation.
- Existing tools would generate such files.
Why is it wrong to implicitly trust the AD flag from recursive name servers
AD flag is how a validating name server informs the requester that the returned DNS data have been successfully validated using the DNSSEC mechanism.
There is a huge difference between using an untrusted recursive name server to retrieve DNS data and using an untrusted DNSSEC validator. DNSSEC works well with untrusted recursive name servers but its security is jeopardized by using them as DNSSEC validators. Applications may attribute additional trust to the validated data especially when they contain security keys for TLS, SSH and other authenticated protocols.
Trusting a random DNSSEC validator on the local network or Internet is like trusting a random security certificate.
Does DNSSEC work on untrusted or public networks?
Yes. There is no such concept as trusted or untrusted network in DNSSEC. The confusion comes from the distinction between a recursive name server (used by the system to retrieve DNS data) and a DNSSEC validator (which is typically a validating name server running on the local host).
For DNSSEC, all we need is to never implicitly use recursive name servers as trusted DNSSEC validators. In our opinion, the preferred way to implement that is to avoid passing security information from ordinary recursive name servers (not configured as trusted DNSSEC validators).
Does NetworkManager need to keep track of trusted DNSSEC validators
No. When working with dnssec-trigger, NetworkManager only needs to keep track of learnt and configured recursive name servers. The list of trusted DNSSEC validators always contains a single unbound instance running on the local host.
- Some terms might need to be improved, especially recursive name server doesn't really say what we want to say which is a name server that is used by the system to gather necessary DNS data. I'm also still not sure about using opportunistic for security of DNSSEC-unaware applications. User:pavlix
- Provide information about isolated network operation. This is especially important because our design often relies on learning about security of the local domains using the global DNS.