DNS 解析器模块

概述

DNS 解析器模块为内核服务提供了一种通过请求 dns_resolver 类型的密钥来进行 DNS 查询的方法。这些查询通过 /sbin/request-key 上调用到用户空间。

这些例程必须由用户空间工具 dns.upcall、cifs.upcall 和 request-key 支持。它正在开发中,尚未提供完整的功能集。它支持的功能包括

(*) 实现 dns_resolver key_type 以联系用户空间。

它尚未支持以下 AFS 功能

(*) 对 AFSDB 资源记录的 DNS 查询支持。

此代码是从 CIFS 文件系统提取的。

编译

应通过启用内核配置选项来启用该模块

CONFIG_DNS_RESOLVER     - tristate "DNS Resolver support"

设置

要设置此工具,必须修改 /etc/request-key.conf 文件,以便 /sbin/request-key 可以适当地定向上调用。例如,要处理基本的 dname 到 IPv4/IPv6 地址解析,应添加以下行

#OP     TYPE            DESC    CO-INFO PROGRAM ARG1 ARG2 ARG3 ...
#====== ============    ======= ======= ==========================
create  dns_resolver    *       *       /usr/sbin/cifs.upcall %k

要定向查询类型为“foo”的查询,应在上面给出的更通用的行之前添加如下行,因为第一个匹配项是被采用的

create  dns_resolver    foo:*   *       /usr/sbin/dns.foo %k

用法

要使用此工具,可以在执行以下操作后调用模块中实现的以下函数之一

   #include <linux/dns_resolver.h>

::

   int dns_query(const char *type, const char *name, size_t namelen,
                const char *options, char **_result, time_t *_expiry);

This is the basic access function.  It looks for a cached DNS query and if
it doesn't find it, it upcalls to userspace to make a new DNS query, which
may then be cached.  The key description is constructed as a string of the
form::

           [<type>:]<name>

where <type> optionally specifies the particular upcall program to invoke,
and thus the type of query to do, and <name> specifies the string to be
looked up.  The default query type is a straight hostname to IP address
set lookup.

The name parameter is not required to be a NUL-terminated string, and its
length should be given by the namelen argument.

The options parameter may be NULL or it may be a set of options
appropriate to the query type.

The return value is a string appropriate to the query type.  For instance,
for the default query type it is just a list of comma-separated IPv4 and
IPv6 addresses.  The caller must free the result.

The length of the result string is returned on success, and a negative
error code is returned otherwise.  -EKEYREJECTED will be returned if the
DNS lookup failed.

If _expiry is non-NULL, the expiry time (TTL) of the result will be
returned also.

内核维护一个内部密钥环,它在其中缓存查找的密钥。任何具有 CAP_SYS_ADMIN 功能的进程都可以通过对密钥环 ID 使用 KEYCTL_KEYRING_CLEAR 来清除它。

从用户空间读取 DNS 密钥

可以使用 keyctl_read() 或 “keyctl read/print/pipe” 从用户空间读取 dns_resolver 类型的密钥。

机制

dns_resolver 模块注册了一个名为“dns_resolver”的密钥类型。此类型的密钥用于传输和缓存来自用户空间的 DNS 查找结果。

当调用 dns_query() 时,它会调用 request_key() 在本地密钥环中搜索缓存的 DNS 结果。如果找不到,它会上调用用户空间以获取新结果。

对用户空间的上调用通过 request_key() 上调用向量进行,并通过 /etc/request-key.conf 中的配置行来定向,这些配置行告诉 /sbin/request-key 要运行什么程序来实例化密钥。

上调用处理程序程序负责查询 DNS,将结果处理成适合传递给 keyctl_instantiate_key() 例程的形式。然后,它将数据传递给 dns_resolver_instantiate(),后者剥离并处理数据中包含的任何选项,然后将字符串的其余部分作为其有效负载附加到密钥。

上调用处理程序程序应将密钥的过期时间设置为其从中提取结果的所有记录的最低 TTL。这意味着当它保存的数据过期时,该密钥将被丢弃并重新创建。

dns_query() 返回附加到密钥的值的副本,或者如果指示了错误则返回错误。

有关 request-key 函数的更多信息,请参见 <file:Documentation/security/keys/request-key.rst>。

调试

可以通过将 1 写入以下文件来动态打开调试消息

/sys/module/dns_resolver/parameters/debug