通过修改 glibc 支持 DNS 加密
dnssec glibc DNS
域名解析系统（DNS）是互联网安全的许多薄弱环节之一；可以将应用程序所访问的主机对应的 IP 地址误导到其它地方。也就是说，会连接到错误的位置，从而引发<ruby> 中间人 <rp>  （ </rp> <rt>  man-in-the-middle </rt> <rp>  ） </rp></ruby>攻击等等。而 [DNSSEC](https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions) 扩展协议则通过为 DNS 信息建立一条加密的可信通道来解决这个漏洞。在正确地配置好 DNSSEC 后，应用程序将可以得到可靠的主机查询信息。通过关于[尝试将 DNSSEC 更好地集成到 GNU C 库里](http://lwn.net/Articles/664790/)的讨论，我们知道，确保 DNS 查询信息安全这件事并不是那么简单。


![](/data/attachment/album/201602/05/214955zjzfpkspm005pssz.jpg)


从某种意义上来说，这个问题多年以前就解决了，我们可以配置一个本地域名服务实现完整的 DNSSEC <ruby> 校验 <rp>  （ </rp> <rt>  verification </rt> <rp>  ） </rp></ruby>并允许应用程序通过 glibc 函数来使用该服务。DNSSEC 甚至还可以用于提高其他领域的安全性，比如，它可以携带 SSH 或 TLS 密钥指纹，让应用程序可以确认其在与正确的服务器对话。不过，当我们希望确认这条自称带有 DNSSEC 校验的 DNS 结果是不是真的已通过认证的时候 - 也就是说，当我们想依赖 DNSSEC 所承诺的安全的时候，事情变得有点复杂。


### /etc/resolv.conf 问题


从 glibc 的角度来看，这个问题一部分是因为 glibc 本身并没有做 DNSSEC 校验，而是引用 /etc/resolv.conf 文件，从该文件里读出的服务器来做解析以及校验，再将结果返回给应用程序。如果应用程序使用底层 res\_query() 接口，那结果中将会包含“<ruby> 已认证数据 <rp>  （ </rp> <rt>  authenticated data </rt> <rp>  ） </rp></ruby>”（AD）标识（如果域名服务器设定了的话）以表示 DNSSEC 校验已经成功。但是 glibc 却完全不知道提供这些结果的域名服务器的信用，所以它其实并不能告诉应用程序结果是否真的可靠。


由 glibc 的维护者 Carlos O'Donell 提出的建议是在 resolv.conf 文件里增加一个选项（dns-strip-dnssec-ad-bit）告诉 glibc 无条件移除 AD 标识。这个选项可以由各发行版设定，表示 DNSSEC 级别的 DNS 查询结果并不可靠。而一旦建立好合适的环境可以获得可靠的查询结果后，再移除这个选项。这样一来，虽然问题还没有完全解决，至少应用程序有依据来评价从 glibc 获取的 DNS 查询结果的可靠性。


一个可靠的环境配置应该是什么样？标准情况应该和这个差不太多：有一个本地域名服务器，通过<ruby> 环路 <rp>  （ </rp> <rt>  loopback </rt> <rp>  ） </rp></ruby>接口访问，作为访问 /etc/resolv.conf 文件的唯一条目。这个域名服务器应该配置来做校验，而在校验失败后就只是简单地不返回任何结果。绝大多数情况下，应用程序就不再需要关心 AD 标识，如果结果不可靠，应用程序就根本看不到。一些发行版已经倾向于这种模型，不过情况仍然不像一些人所设想的那么简单。


其中一个问题是，这种方式将 /etc/resolv.conf 文件放到整个系统可信任度的中心。但是，在一个典型的 Linux 系统里，有无数的 DHCP 客户端、网络脚本以及其他更多的程序可以修改这个文件。就像 Paul Wouters 所[指出](http://lwn.net/Articles/664794/)的，在短时间内锁定这个文件是不可能的。有时候这种修改是必须的：在一个无盘系统启动的时候，在自身的域名服务器启动之前也是需要域名服务的；一个系统的整个 DNS 环境也会根据所连接的网络不同而有所改变；运行在容器里的系统也最好是配置成使用宿主机的域名服务器；等等。


所以，现在一般认为，现有系统里的 /etc/resolv.conf 文件并不可信。于是有人提出增加另一个配置文件（/etc/secure-resolv.conf 或其他什么），但这并没有从根本上解决问题。除此之外，有些参与者觉得就算有一个运行在环路接口上的域名服务器也不是真正可靠，比如 Zack Weinberg 甚至[建议](http://lwn.net/Articles/664782/)系统管理员可以有意禁用 DNSSEC <ruby> 确认 <rp>  （ </rp> <rt>  validation </rt> <rp>  ） </rp></ruby>。


既然当前系统里的配置不足以信任，那可以这样推断，在情况有改善能够取得可信的结果后，glibc 需要有一种方式来通知应用程序。可以是上面讨论的屏蔽 AD 标识的方式（或者与之相反，增加一个显示的“此域名服务器可以信任”选项）；当然，这都需要一定程度上锁定系统以免 /etc/resolv.conf 受到任何不可预计的修改。按 Petr Spacek 的[建议](http://lwn.net/Articles/664784/)，还有一种引申方式，就是提供一种途径允许应用程序查询 glibc 当前通讯的是不是本地域名服务器。


### 在 glibc 里来处理？


另一种方式是不管域名服务器，而是让 glibc 本身来做 DNSSEC 确认。不过，把这么大一坨加密相关代码放进 glibc 也是有很大阻力。这样将增加库本身的大小，从而感觉会增加使用它的应用程序的受攻击可能性。这个方向再引申一下，由 Zack 提出的[建议](http://lwn.net/Articles/664796/)，可以把确认相关代码放到域名服务缓冲守护进程（nscd）里。因为 nscd 也是 glibc 的一部分，由 glibc 开发人员维护，因此在一定程度上可以相信能正确执行 DNSSEC 确认。而且 nscd 的通讯 socket 所在位置也是公开的，所以可以不考虑 /etc/resolv.conf 问题。不过，Carlos [担心](http://lwn.net/Articles/664786/)这种方式不能让那些不想使用 nscd 缓存功能的用户所接受；在他看来，基本可以排除 nscd 的方式。


所以，至少近期内，glibc 不太可能全部执行 DNSSEC 确认了的整个查询过程。这意味着，如果一个有安全考虑的应用要使用 glibc 库来查询域名，该库将需要提供一个标识来评价从独立域名服务器返回的结果有多大程度的可靠性。这几乎肯定需要发行版或系统管理员做出一些明确的改动。就像 Simo Sorce [说的](http://lwn.net/Articles/664787/)那样：



> 
> 如果 glibc 不使用明确的配置选项来通知应用程序它所用的域名解析是可信的，不会有什么用……不改一下还有很大弊端，因为应用程序开发者将马上认识到他们不能信任从 glibc 获取的任何信息，从而在处理 DNSSEC 相关信息时就简单地不用它。
> 
> 
> 


要配置一个系统能正常使用 DNSSEC 需要改动该系统的很多组件 - 这是一个发行版范围的问题，需要时间来完全解决。在这个转变过程中 glibc 所扮演的角色很可能会比较小，但是很重要的一部分：如果应用程序不实现一套自己的域名解析代码，glibc 很可能是保证 DNS 结果可信的唯一方式。在一个系统中运行多个 DNSSEC 实现方式看起来不像是一种安全的方式，所以最好还是把事情做对了。


glibc 项目目前并没有确定用哪种方式来做这个事情，虽然从 /etc/resolv.conf 文件里的某些标记看上去快好了。这种改动应该需要发布新版本；考虑到 glibc 开发的保守天性，很可能来不及加入预计二月份发布的 2.23 版本了。所以 glibc 中暂时还不会有更高安全性的 DNSSEC ，不过在这个方向上也有一些进展了。




---


via: <https://lwn.net/Articles/664776/>


作者：Jonathan Corbet 译者：[zpl1025](https://github.com/zpl1025) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
# Supporting secure DNS in glibc

One of the many weak links in Internet security is the domain name system (DNS); it is subject to attacks that, among other things, can mislead applications regarding the IP address of a system they wish to connect to. That, in turn, can cause connections to go to the wrong place, facilitating man-in-the-middle attacks and more. TheWe're bad at marketingWe can admit it, marketing is not our strong suit. Our strength is writing the kind of articles that developers, administrators, and free-software supporters depend on to know what is going on in the Linux world. Please

[subscribe today]to help us keep doing that, and so we don’t have to get good at marketing.

[DNSSEC](https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions)protocol extensions are meant to address this threat by setting up a cryptographically secure chain of trust for DNS information. When DNSSEC is set up properly, applications should be able to trust the results of domain lookups. As the discussion over

[an attempt to better integrate DNSSEC into the GNU C Library](/Articles/664790/)shows, though, ensuring that DNS lookups are safe is still not a straightforward problem.

In a sense, the problem was solved years ago; one can configure a local nameserver to perform full DNSSEC verification and use that server via glibc calls in applications. DNSSEC can even be used to increase security in other areas; it can, for example, carry SSH or TLS key fingerprints, allowing applications to verify that they are talking to the right server. Things get tricky, though, when one wants to be sure that DNS results claiming to have DNSSEC verification are actually what they claim to be — when one wants the security that DNSSEC is meant to provide, in other words.


#### The /etc/resolv.conf problem

Part of the problem, from the glibc perspective, is that glibc itself does
not do
DNSSEC verification. Instead, it consults `/etc/resolv.conf` and
asks the servers found therein to do the lookup and verification;
the results are then returned to
the application. If the application is using the low-level
`res_query()` interface, those results may include the
"authenticated data" (AD) flag (if the nameserver has set it) indicating
that DNSSEC verification has been
successfully performed. But glibc knows nothing about the trustworthiness
of the nameserver that has provided those results, so it cannot tell the
application anything about whether they should really be trusted.

One of the first steps suggested by glibc maintainer Carlos O'Donell is to
add an option (`dns-strip-dnssec-ad-bit`) to the
`resolv.conf` file telling glibc to unconditionally remove the AD
bit. This option could be set by distributions to indicate that the DNS
lookup results cannot be trusted at a DNSSEC level. Once things have been
set up so that the results *can* be trusted, that option can be
removed. In the meantime, though, applications would have a way to judge
the DNS lookup results they get from glibc, something that does not exist
now.

What would a trustworthy setup look like? The standard picture looks
something like this: there is a local nameserver, accessed via the loopback
interface, as the only entry in `/etc/resolv.conf`. That nameserver
would be configured to do verification and, in the case that verification
fails, simply return no results at all. There would, in almost all cases,
be no need to worry about whether applications see the AD bit or not; if
the results are not trustworthy, applications will simply not see them at
all. A number of distributions are moving toward this model, but the
situation is still not as simple as some might think.

One problem is that this scheme makes `/etc/resolv.conf` into a
central point of trust for the system. But, in a typical Linux system,
there are no end of DHCP clients, networking scripts, and more that will
make changes to that file. As Paul Wouters [pointed out](/Articles/664794/), locking down this file in the
short term is not really an option. Sometimes those changes are necessary:
when a
diskless system is booting, it may need name-resolution service before it
is at a point where it can start up its own nameserver. A system's entire
DNS environment may change depending on which network it is attached to.
Systems in containers may be best configured to talk to a nameserver on the
host. And so on.

So there seems to be a general belief that `/etc/resolv.conf` cannot
really be trusted on current systems. Ideas to add secondary configuration
files
(`/etc/secure-resolv.conf` or whatever) have been floated, but they
don't much change the basic nature of the situation. Beyond that, some
participants felt that even a local nameserver running on the loopback
interface is not really trustworthy; Zack Weinberg [suggested](/Articles/664782/) that administrators might
intentionally short out DNSSEC validation, for example.

Since the configuration cannot be trusted on current systems, the reasoning
goes, glibc needs to have a way to indicate to applications when the
situation has improved and things
*can* be trusted. That could include the AD-stripping option
described above (or, conversely, an explicit "this nameserver is trusted"
option); that, of course, would require that the system be locked down
to a level where surprising changes to `/etc/resolv.conf` no longer
happen. A variant, as [suggested](/Articles/664784/) by Petr
Spacek, is to have a way for an application to ask glibc whether it is
talking to a local nameserver or not.


#### Do it in glibc?

An alternative would be to dispense with the nameserver and have glibc do
DNSSEC validation itself. There is, however, resistance to putting a big
pile of cryptographic code into glibc itself. That would increase the size
of the library and, it is felt, increase the attack surface of any
application using it. A variant of this idea, [suggested](/Articles/664796/) by Zack, would be to put the
validation code into the name-service caching daemon (`nscd`)
instead. Since `nscd` is part of glibc, it is under the control of
the glibc developers and there could be a certain amount of confidence that
DNSSEC validation is being performed properly. The location of the
`nscd` socket is well known, so the `/etc/resolv.conf` issues
don't come into play. Carlos [worried](/Articles/664786/),
though, that this approach might deter adoption by users who do not want
the caching features of `nscd`; in his mind, that seems to rule out
the `nscd` option.

So, in the short term, at least, it seems unlikely that glibc will take on the
full task of performing validated DNSSEC lookups. That means that, if
security-conscious applications are going to use glibc for their name
lookups, the library will have to provide an indication of how trustworthy
the results received from a separate nameserver are. And that will almost
certainly require explicit action on
the part of the distributor and/or system administrator. As Simo Sorce [put it](/Articles/664787/):


Configuring a system to properly use DNSSEC involves change to many of the components of that system — it is a distribution-wide problem that will take time to solve fully. The role that glibc plays in this transition is likely to be relatively small, but it is an important one: glibc is probably the only place where applications can receive some assurance that their DNS results are trustworthy without implementing their own resolver code. Running multiple DNSSEC implementations on a system seems like an unlikely path to greater security, so it would be good to get this right.

The glibc project has not yet chosen a path by which it intends to get
things right, though some sort of annotation in `/etc/resolv.conf`
looks like a likely outcome. Any such change would then have to get into
a release; given the conservative nature of glibc development, it may
already be late for the 2.23 release, which is likely to happen in
February. So higher DNSSEC awareness in glibc may not happen right away,
but there is at least some movement in that direction.

Index entries for this article | |
---|---|

|


[DNSSEC](/Security/Index/#DNSSEC) Posted Nov 18, 2015 23:05 UTC (Wed)
by
Posted Nov 19, 2015 1:41 UTC (Thu)
by
The issue here is playing nice with non-glibc resolvers, like c-ares, adns, and the untold number of similar resolvers floating around. Not to mention non-systemd DHCP clients and other code that manipulates /etc/resolv.conf directly.
The resolved approach also effectively moves the real query code outside the library and into the local [systemd] resolver. But per the article glibc wasn't prepared to always assume the local resolver to be trusted, presumably reasoning that trusting unrelated processes is not something they're prepared to do. Obviously this not reasoning that systemd folk would agree with. But the underlying judgments relate to stances on portability, standards conformance (POSIX, historical, etc), forwards and backwards compatibility, and ultimately where the real interface boundaries should be. Which is basically the whole systemd debate in a nut shell. And perhaps why systemd has felt compelled (rightly or wrongly, for better or worse) to buildup an entire parallel ecosystem of infrastructure software--DNS, NTP, DHCP, etc.
Posted Nov 20, 2015 8:27 UTC (Fri)
by Oh, PLEASE don't take away my resolv.conf—I (ab)use it by adding some 0.0.0.0 entries to get ad.doubleclick.net (and some others) to STFU when web-browsing.
Posted Nov 20, 2015 8:43 UTC (Fri)
by
Note that there is also nsswitch.conf, which governs sources and their order. /etc/hosts is "files" source, while resolv.conf is used by for example "dns" source.
Posted Nov 21, 2015 5:06 UTC (Sat)
by I stand corrected. Not sure what I was thinking when I typed that... :-\
Posted Nov 20, 2015 20:51 UTC (Fri)
by
Posted Nov 20, 2015 21:36 UTC (Fri)
by
In practice I've found that things filtering on source/destination host pairs (NoScript, RequestPolicy, Policeman, uMatrix) are good enough 90% of the time, and closer to 99% if you add content type to the filter. In Chromium-based browsers there's even a special fast path for this specific use case.
Having said that, I also took the malware/spam hosts lists in uMatrix and converted them to empty BIND zones for my LAN. A bit of defence in depth can't hurt.
Posted Nov 23, 2015 2:55 UTC (Mon)
by
I have an SSID on my home network especially for Android devices on which the DNS server handed out by DHCP is a local Unbound server configured with a hosts file style blacklist. It does a great job killing both in-browser and in-app ads.
Posted Dec 3, 2015 1:16 UTC (Thu)
by
I've yet to see a convincing reason why hooking at the NSS level (like libnss-resolve does) is any better than speaking the DNS protocol directly (like unbound would do). There's a straightforward respect in which it's worse, thouggh: the unbound approach works with all the non-glibc third-party asynchronous resolvers.
(Of course, both approaches will want some way to signal to apps that the local resolver is validating, but I think they're on equal footing there in that neither one actually succeeds without library and API changes.)
Posted Dec 3, 2015 6:46 UTC (Thu)
by
Posted Dec 3, 2015 17:56 UTC (Thu)
by
It's a pretty dire situation when an average Linux desktop has more ways of looking up a hostname than graphical toolkits installed.
I wish someone would come along and do for gethostbyname() what sqlite did for fopen() - a library that doesn't suck and offers *no* excuses for not using it.
Posted Nov 19, 2015 10:50 UTC (Thu)
by
If you want secure DNS, the administrator needs to set up the system with a trustworthy resolv.conf. If you can't trust the admin to do that, how can you fix that at the application level?
Posted Nov 19, 2015 15:05 UTC (Thu)
by
Posted Nov 19, 2015 15:26 UTC (Thu)
by
This is why you want a validating resolver on your own machine.
Posted Nov 20, 2015 2:51 UTC (Fri)
by
... or a VPN back to base which has trusted DNS servers. This has the bonus of working for all your users without having to maintain multiple funky resolvers. Either method will work - I do both for myself but my staff (who generally wouldn't know what a resolver is) get a (Open)VPN which forces all traffic via base.
Posted Nov 19, 2015 14:58 UTC (Thu)
by
Posted Nov 20, 2015 7:44 UTC (Fri)
by
Posted Nov 24, 2015 20:03 UTC (Tue)
by
Nevertheless, Snowden did give the IETF a wake-up call and work is proceeding. There is the excellent RFC 7626 by Stephane Bortzmeyer which covers the problem space:
As far as actual standards work, there is DPRIVE, the DNS Privacy working group, which was chartered recently to tackle some of these issues. Current work focuses on moving DNS over TLS or the UDP variant thereof (DTLS). It's not enough, but we are adding more tools to protect against pervasive monitoring via DNS. Sadly a 30 year old protocol is hard to update....
Posted Nov 19, 2015 18:44 UTC (Thu)
by
Posted Nov 19, 2015 19:52 UTC (Thu)
by
Posted Nov 19, 2015 19:58 UTC (Thu)
by
Posted Nov 19, 2015 23:47 UTC (Thu)
by
Posted Nov 20, 2015 3:46 UTC (Fri)
by
I think that HTTP[S] tunneling should only solve the problem of filtering middleboxes and DNSSEC should be used for everything else.
Posted Nov 20, 2015 3:51 UTC (Fri)
by Ah, sounds like you also might be interested in
Posted Nov 19, 2015 21:42 UTC (Thu)
by
I think Cyberax suggested using HTTPS to get authentication, but that draft seems to only talk about using SSL to get privacy.
I don't think HTTPS is the best choice for authentication though made it is so widely used that it is OK.
Would it make sense to put a public key in resolv.conf and configure your trusted DNS server (whether on localhost or in the machine room or whatever) to sign all verified responses with the matching public key?
Then a relatively small amount of crypto code in glibc could verify local responses.
Posted Nov 19, 2015 23:44 UTC (Thu)
by draft-ietf-dprive-dns-over-tls-01 specifies two different usage profiles in section 4, "Opportunistic Privacy Profile" and "Pre-Deployed Profile". The pre-deployed profile requires that the server be authenticated. The short answer is: There have been a few attempts at adding non-TLS crypto privacy to stub lookups, e.g. There are a few IETF-standardized DNS extensions that allow crypto authentication for lookups, TSIG and SIG(0). But these are rarely used (the big problem is key distribution) and don't provide privacy. (TSIG is probably more familiar to people as a mechanism used to protect DNS zone transfers.)
Posted Nov 20, 2015 3:44 UTC (Fri)
by
And then trusted DNS information can be used by other layers.
Posted Nov 20, 2015 22:16 UTC (Fri)
by
Posted Nov 21, 2015 5:40 UTC (Sat)
by
Posted Nov 19, 2015 23:09 UTC (Thu)
by
Hi,
I have a few brief comments.
It looks like these two proposals come down to implementing what the DNSSEC RFCs
call a "Non-Validating Security-Aware Stub Resolver" (the first proposal
described in the article) and a "Validating Security-Aware Stub Resolver" (the
second proposal). Here are the definitions from RFC 4033:
[
][
]## Supporting secure DNS in glibc

**josh** (subscriber, #17465)
[[Link](/Articles/664908/)] (10 responses)

[
]## Supporting secure DNS in glibc

**wahern** (subscriber, #37304)
[[Link](/Articles/664921/)] (6 responses)



[
]## Supporting secure DNS in glibc

**pr1268** (subscriber, #24648)
[[Link](/Articles/665136/)] (5 responses)
it just defines it away by obsoleting /etc/resolv.conf, or at least making it read-only and always pointing to 127.0.0.1.

[
]## Supporting secure DNS in glibc

**zdzichu** (subscriber, #17118)
[[Link](/Articles/665138/)] (1 responses)


[
]## Supporting secure DNS in glibc

**pr1268** (subscriber, #24648)
[[Link](/Articles/665361/)]
You put this in resolv.conf, not in /etc/hosts? Are you sure?

[
]## Supporting secure DNS in glibc

**josh** (subscriber, #17465)
[[Link](/Articles/665286/)] (2 responses)

[
]## Supporting secure DNS in glibc

**flussence** (guest, #85566)
[[Link](/Articles/665287/)]



[
]## Supporting secure DNS in glibc

**edmonds42** (guest, #42670)
[[Link](/Articles/665498/)]


[
]## Supporting secure DNS in glibc

**luto** (subscriber, #39314)
[[Link](/Articles/666632/)] (2 responses)



[
]## Supporting secure DNS in glibc

**Cyberax** (**✭ supporter ✭**, #52523)
[[Link](/Articles/666665/)]

[
]## Supporting secure DNS in glibc

**flussence** (guest, #85566)
[[Link](/Articles/666770/)]



[
]## Supporting secure DNS in glibc

**runekock** (subscriber, #50229)
[[Link](/Articles/664955/)] (3 responses)


[
]## Supporting secure DNS in glibc

**smoogen** (subscriber, #97)
[[Link](/Articles/664983/)] (2 responses)

[
]## Supporting secure DNS in glibc

**anselm** (subscriber, #2796)
[[Link](/Articles/664985/)] (1 responses)
[
]## Supporting secure DNS in glibc

**gerdesj** (subscriber, #5446)
[[Link](/Articles/665111/)]


[
]## "Secure" DNS?

**civodul** (guest, #58311)
[[Link](/Articles/664982/)] (2 responses)
[https://gnunet.org/mcb](https://gnunet.org/mcb) . The "secure" label may give people a wrong sense of security.

[
]## "Secure" DNS?

**kleptog** (subscriber, #1183)
[[Link](/Articles/665132/)]

[
]## "Secure" DNS?

**shane** (subscriber, #3335)
[[Link](/Articles/665723/)]


[https://www.rfc-editor.org/info/rfc7626](https://www.rfc-editor.org/info/rfc7626)


[
]## Supporting secure DNS in glibc

**Cyberax** (**✭ supporter ✭**, #52523)
[[Link](/Articles/665064/)] (10 responses)

[
]## Supporting secure DNS in glibc

**cstrotm** (subscriber, #55963)
[[Link](/Articles/665070/)] (7 responses)
[
]## Supporting secure DNS in glibc

**Cyberax** (**✭ supporter ✭**, #52523)
[[Link](/Articles/665071/)] (3 responses)

[
]## Supporting secure DNS in glibc

**edmonds42** (guest, #42670)
[[Link](/Articles/665101/)] (2 responses)
[draft-hoffman-dprive-dns-tls-https](https://tools.ietf.org/html/draft-hoffman-dprive-dns-tls-https-00) is probably the draft you're looking for, then.
[
]## Supporting secure DNS in glibc

**Cyberax** (**✭ supporter ✭**, #52523)
[[Link](/Articles/665115/)] (1 responses)


[
]## Supporting secure DNS in glibc

**edmonds42** (guest, #42670)
[[Link](/Articles/665116/)]
[draft-ietf-dnsop-dnssec-roadblock-avoidance](https://datatracker.ietf.org/doc/draft-ietf-dnsop-dnssec-roadblock-avoidance/?include_text=1), then.
[
]## Supporting secure DNS in glibc

**neilbrown** (subscriber, #359)
[[Link](/Articles/665083/)] (2 responses)





[
]## Supporting secure DNS in glibc

**edmonds42** (guest, #42670)
[[Link](/Articles/665096/)]
*I think Cyberax suggested using HTTPS to get authentication, but that draft seems to only talk about using SSL to get privacy.**Would it make sense to put a public key in resolv.conf and configure your trusted DNS server (whether on localhost or in the machine room or whatever) to sign all verified responses with the matching public key?**Then a relatively small amount of crypto code in glibc could verify local responses.*[don't design your own cryptosystem, it will look bad when cryptographers review it](https://mailarchive.ietf.org/arch/msg/dns-privacy/P9kHBNpPFmPbMHzfOI-JpVfEDuc).[DNSCrypt](https://dnscrypt.org/), [draft-wijngaards-dnsop-confidentialdns](https://tools.ietf.org/html/draft-wijngaards-dnsop-confidentialdns-03), and [draft-krecicki-dprive-dnsenc](https://tools.ietf.org/html/draft-krecicki-dprive-dnsenc-01). Probably the most successful of those so far is DNSCrypt (e.g., see OpenDNS's deployment), but even that one relies on a local proxy daemon.[
]## Supporting secure DNS in glibc

**Cyberax** (**✭ supporter ✭**, #52523)
[[Link](/Articles/665114/)]


[
]## Supporting secure DNS in glibc

**imMute** (guest, #96323)
[[Link](/Articles/665304/)] (1 responses)

[
]## Supporting secure DNS in glibc

**Cyberax** (**✭ supporter ✭**, #52523)
[[Link](/Articles/665366/)]

[
]## Supporting secure DNS in glibc

**edmonds42** (guest, #42670)
[[Link](/Articles/665055/)]
Non-Validating Security-Aware Stub Resolver: A security-aware stub
resolver that trusts one or more security-aware recursive name
servers to perform most of the tasks discussed in this document
set on its behalf. In particular, a non-validating security-aware
stub resolver is an entity that sends DNS queries, receives DNS
responses, and is capable of establishing an appropriately secured
channel to a security-aware recursive name server that will
provide these services on behalf of the security-aware stub
resolver. See also security-aware stub resolver, validating
security-aware stub resolver.
Non-Validating Stub Resolver: A less tedious term for a
non-validating security-aware stub resolver.
[...]
Validating Security-Aware Stub Resolver: A security-aware resolver
that sends queries in recursive mode but that performs signature
validation on its own rather than just blindly trusting an
upstream security-aware recursive name server. See also
security-aware stub resolver, non-validating security-aware stub
resolver.
Validating Stub Resolver: A less tedious term for a validating
security-aware stub resolver.


The first definition refers to "an appropriately secured channel", which is further mentioned in RFC 4035:

4.9.3. Handling of the AD Bit A non-validating security-aware stub resolver MAY chose to examine the setting of the AD bit in response messages that it receives in order to determine whether the security-aware recursive name server that sent the response claims to have cryptographically verified the data in the Answer and Authority sections of the response message. Note, however, that the responses received by a security-aware stub resolver are heavily dependent on the local policy of the security-aware recursive name server. Therefore, there may be little practical value in checking the status of the AD bit, except perhaps as a debugging aid. In any case, a security-aware stub resolver MUST NOT place any reliance on signature validation allegedly performed on its behalf, except when the security-aware stub resolver obtained the data in question from a trusted security-aware recursive name server via a secure channel. A validating security-aware stub resolver SHOULD NOT examine the setting of the AD bit in response messages, as, by definition, the stub resolver performs its own signature validation regardless of the setting of the AD bit.

The RFCs generally treat the "stub resolver" and applications that rely on the
stub resolver as separate components that communicate via an interface, and this
is true enough if you are using high-level interfaces like
`getaddrinfo()`, but in practice on GNU/Linux and *BSD systems this
abstraction becomes very leaky when you want to do anything other than an
address lookup (A/AAAA). On Linux systems, the DNS "stub resolver" consists of
the `res_*()` functions and related `ns_*()` and `dn_*()`
helper functions, which are provided by a separate library `libresolv`,
which is shipped by glibc.

glibc's `libresolv` is very old. As near as I've been able to track down,
it's a cut down version of the "`libbind`" stub resolver that was
included with CSRG BSD, BIND 4, BIND 8, and BIND 9 (up until BIND 9.6.0, when it
was removed). glibc first(?) imported this code from BIND 4.9.1 in May 1993,
and periodically synchronized with the upstream codebase until the last update
from BIND 8.2.3-T5B in July 2000, at which point it continued to evolve
independently in glibc. This is why if you execute `libc.so.6` glibc will
print out `BIND-8.2.3-T5B` as an "available extension". (The upstream
codebase is still kicking around; ISC split it out into a standalone "libbind"
distribution when it was removed from BIND 9.6.0, and it was later adopted from
ISC by the NetBSD project a few years ago where it was renamed to "netresolv".)

(A digression: parts of the `nss_dns` code in glibc, which interfaces
`libresolv` to the glibc Name Service Switch, is similarly old and
descended from CSRG on stone tablets. This code in its modern glibc form is not
easy to read; to take a cherry-picked example,
[
this 2007 commit
](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=2f1687b96b25af512b095c9ebfa283f63c13bb78;hp=a15ccd8f07d7afbbd7635f350e318ede84709ac6)
[
[corresponding bug report BZ#4381]
](https://sourceware.org/bugzilla/show_bug.cgi?id=4381)
introduced a vulnerability which was later fixed in
[
this 2015 commit,
](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=2959eda9272a03386;hp=7bf8fb104226407b75103b95525364c4667c869f)
[
[corresponding bug report BZ#18287]
](https://sourceware.org/bugzilla/show_bug.cgi?id=18287)
resulting in CVE-2015-1781, which could have been exploited remotely by
malformed DNS response packets under certain conditions. If you're a moderately
skilled C programmer who only rarely ventures into the glibc codebase, your
reaction to reading these diffs will probably be similar to
[this fellow](http://i.imgur.com/E3ui9OC.gif), or perhaps [this one](http://i.imgur.com/B9NGjSn.gif). This code is seriously hard
to read.
Fortunately, it appears this bug wasn't likely to be exploitable in practice, at
least in instances of calling code which were audited. According to Florian
Weimer, then of Red Hat Product Security: "This can only happen if these
functions are called with a misaligned buffer. I looked at quite a bit of source
code, and tested applications with a patched glibc that logs misaligned buffers.
I did not observe any such misaligned buffers.")

The `res_*` interface is not very fun to use. The result returned by the
`res_query()`, `res_search()`, and `res_send()` functions
is a bare DNS protocol wire-format message which must be parsed by the
application. `libresolv` offers a number of `ns_*()` functions
(`ns_initparse()`, `ns_parserr()`, etc.) that don't quite amount
to a parser, but are rather a collection of helper functions that can be used to
construct a parser. The `ns_*()` functions aren't fully documented on
GNU or even BSD systems, though; the best API reference available is probably
contained in chapter 15 of the O'Reilly "DNS and BIND" book.
[Here](https://github.com/farsightsec/wrapsrv/blob/tags/v1.0.0/wrapsrv.c#L235-L262)
is a trivial example I wrote of using this interface to parse a DNS `SRV`
response. Note how the caller is responsible for checking that the resource
record is well-formed and for knowing the precise layout of the data fields
within the `SRV` resource record. In practice, the `ns_*()`
functions tend to be avoided by applications that use the `res_*()`
interface to perform lookups. A good example is the Postfix
MTA, which uses the `res_*()` functions to send a query, but implements
its own wire-format message parser. [Debian Code Search](https://codesearch.debian.net/) finds only [34
packages with ns_parserr references](https://codesearch.debian.net/perpackage-results/ns_parserr/2/page_0), though not all of these
instances are actual users of the interface.

Taking the Postfix example, Postfix together with `libresolv`
participate jointly in the parsing of the DNS message, and in particular Postfix
examines the AD bit, which arguably puts that application code within the
boundary of what the DNSSEC RFCs call the "non-validating security-aware stub
resolver". RFC 4035 specifically says, "In any case, a security-aware stub
resolver MUST NOT place any reliance on signature validation allegedly performed
on its behalf [i.e., the AD bit], except when the security-aware stub resolver
obtained the data in question from a trusted security-aware recursive name
server via a secure channel." Postfix tries to conform with that "MUST NOT" by
[warning](https://www.ietf.org/mail-archive/web/dane/current/msg06294.html)
that it's the sysadmin's responsibility to configure the system's resolver
correctly.
(BTW, there is a
[comment](https://github.com/vdukhovni/postfix/blob/e3c9d425eee3cb2088add18025cdd0d141018f8b/postfix/src/dns/dns_lookup.c#L304-L306)
in the Postfix codebase that they might make `libunbound`, a
validating stub resolver library, a mandatory dependency, which would allow
Postfix to do its own validation.)

Another example is the OpenSSH client on Debian and Fedora systems, which is
compiled without `ldns` support. In order to look up `SSHFP`
records it uses the `res_*()` interface with
`RES_USE_EDNS0|RES_USE_DNSSEC` and examines the AD-bit, and it also uses
its
[
own DNS message parsing implementation](http://sources.debian.net/src/openssh/1:6.9p1-2/openbsd-compat/getrrsetbyname.c/)
rather than relying on `libresolv`'s `ns_*()` interface.

If I understand correctly, since e.g. Postfix and OpenSSH currently assume the
AD-bit is trustworthy, the AD-bit stripping proposal described in this article
amounts to declaring that the glibc stub resolver does not always obtain its
data from "a trusted security-aware recursive name server via a secure channel",
and if there were some way to determine that the system's upstream resolver is
both trustworthy and that the system communicates with it over a secure channel,
the AD-bit could be unmasked. Both of those determinations are pretty hard to
evaluate, and to communicate to relying processes with the existing APIs/ABIs.
Especially when those relying processes might use their own stub resolver (e.g.,
`adns`, `c-ares`) and the only ABI you have is the contents of the
`/etc/resolv.conf` file.

The second proposal described in the article appears to be to add a "Validating
Security-Aware Stub Resolver" to glibc, which is the "trust, but verify" (i.e.,
don't trust) mode, where the stub resolver on the end host is responsible for
performing the cryptographic validation itself. However, since DNSSEC validation
requires obtaining additional DNS records
[this
results in short-lived processes spamming the upstream resolver with more
DNS queries](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=679828;msg=10).
Reducing this query spam requires either a local cache, and/or the deployment
of a proposal like
[draft-ietf-dnsop-edns-chain-query](https://datatracker.ietf.org/doc/draft-ietf-dnsop-edns-chain-query/?include_text=1).
Moreover, in-process validation would result in pulling in a heavyweight library
like `libunbound`, which may spawn threads, perform long-lived heap
allocations for its cache, load hairy crypto libraries like OpenSSL into the
process, etc. As a proof-of-concept, a few years ago I attempted an
[ nss-ubdns](https://github.com/edmonds/nss-ubdns)
module for the Name Service Switch that could replace

`nss_dns`and use

`libunbound`rather than

`libresolv`for DNS resolution. This turned out to be very crashy in practice with nontrivial applications like Firefox, and I lost interest in the approach.

There are also developments on the horizon that lean towards having a local
daemon on the system: the IETF's
[DNS PRIVate Exchange
(DPRIVE)](https://datatracker.ietf.org/wg/dprive/charter/)
working group is coalescing around proposals to protect the privacy of the "last
mile" of DNS with TLS and/or D(TLS) sessions between stub resolvers and
recursive DNS servers. (IANA has provisionally allocated TCP/UDP port 853 for
this.) To scale, this is going to require maintaining a long-lived session with
the recursive DNS server, to minimize the overhead and latency of TCP and TLS
session initiation. That means the end host's stub resolver needs to have a
nearby long-lived daemon somewhere between it and the recursive DNS server.
Probably that means something like a local unbound instance on the system
operating in forwarding mode and speaking the port 853 protocol to its upstream
resolver.

Finally, folks writing new applications that want to rely on
DNSSEC-authenticated resource records from the DNS are unlikely to want to rely
on the old resolver interface, even if eventually bleeding edge versions of the
glibc resolver grow the capability to tell the caller that the results are
trustworthy. (What do you do if you're running on an older glibc version, or the
distro you're running on hasn't set things up properly, or you're on a BSD,
etc.) Easier to add an external dependency on something like [ getdnsapi](https://getdnsapi.net/), which currently only has a

`libunbound`backend but will hopefully have an alternate implementation provided by a library form of CZ.NIC's

[Knot Resolver](https://github.com/CZ-NIC/knot-resolver/issues/5).

Posted Dec 8, 2015 21:49 UTC (Tue)
by
Given this, why do we care about DNS security?
Posted Dec 9, 2015 1:23 UTC (Wed)
by
Posted Dec 9, 2015 9:01 UTC (Wed)
by
[
]## Why Do We Need Secure DNS, Again?

**ldo** (guest, #40946)
[[Link](/Articles/667209/)] (2 responses)


[
]## Why Do We Need Secure DNS, Again?

**flussence** (guest, #85566)
[[Link](/Articles/667234/)]

[
]## Why Do We Need Secure DNS, Again?

**paulj** (subscriber, #341)
[[Link](/Articles/667251/)]