dnsmasq
dnsmasq 提供了一个 DNS 服务器,一个支持 DHCPv6 和 PXE 的 DHCP 服务器,以及一个 TFTP 服务器。它旨在轻量化且占用资源少,适用于资源受限的路由器和防火墙。dnsmasq 还可以配置为缓存 DNS 查询,以提高之前访问过的网站的 DNS 解析速度。
安装
安装 dnsmasq 软件包。然后 启动/启用 dnsmasq.service。
网络也需要重启,以便 DHCP 客户端可以创建新的 /etc/resolv.conf。
配置
要配置 dnsmasq,请编辑 /etc/dnsmasq.conf。该文件包含解释各选项的注释。所有可用选项请参阅 dnsmasq(8)。
port=0 来显式禁用它。如果 dnsmasq 不被用作本地 DNS 解析器,您可能还希望 编辑 dnsmasq.service,使其不再加载 nss-lookup.target
/etc/systemd/system/dnsmasq.service.d/no-nss-lookup-target.conf
[Unit] Wants=
$ dnsmasq --test
DNS 服务器
要将 dnsmasq 设置为单台计算机上的 DNS 缓存守护进程,请指定 listen-address 指令,并添加 localhost IP 地址
listen-address=::1,127.0.0.1
若要让这台计算机监听其局域网 (LAN) IP 地址以服务网络上的其他计算机,建议在这种情况下使用静态局域网 IP。例如:
listen-address=::1,127.0.0.1,192.168.1.1
或者,您可以指定一个网络接口
interface=enp5s0
使用 cache-size=size 设置缓存的域名数量(默认值为 150)
cache-size=10000
要验证 DNSSEC,请加载由 dnsmasq 软件包提供的 DNSSEC 信任锚点并设置 dnssec 选项
conf-file=/usr/share/dnsmasq/trust-anchors.conf dnssec
更多您可能想使用的选项请参阅 dnsmasq(8)。
DNS 地址文件与转发
配置 dnsmasq 后,您需要将 localhost 地址作为 /etc/resolv.conf 中唯一的名称服务器。这将导致所有查询都发送到 dnsmasq。
由于 dnsmasq 是一个存根解析器 (stub resolver) 而不是递归解析器,因此您必须设置转发到外部 DNS 服务器。这可以通过使用 openresolv 自动完成,或者在 dnsmasq 配置中手动指定 DNS 服务器地址。
openresolv
如果您的网络管理器支持 resolvconf,您可以使用 openresolv 为 dnsmasq 生成配置文件,而不是直接修改 /etc/resolv.conf。
编辑 /etc/resolvconf.conf,将环回地址添加为名称服务器,并配置 openresolv 写入 dnsmasq 配置
/etc/resolvconf.conf
# Use the local name server name_servers="::1 127.0.0.1" resolv_conf_options="trust-ad" # Write out dnsmasq extended configuration and resolv files dnsmasq_conf=/etc/dnsmasq-conf.conf dnsmasq_resolv=/etc/dnsmasq-resolv.conf
运行 resolvconf -u 以创建配置文件。如果文件不存在,dnsmasq.service 将无法启动。
编辑 dnsmasq 配置文件以使用 openresolv 生成的配置[1]
# Read configuration generated by openresolv conf-file=/etc/dnsmasq-conf.conf resolv-file=/etc/dnsmasq-resolv.conf
手动转发
首先,您必须将 localhost 地址设置为 /etc/resolv.conf 中唯一的名称服务器
/etc/resolv.conf
nameserver ::1 nameserver 127.0.0.1 options trust-ad
请确保按照 域名解析#覆盖 /etc/resolv.conf 中所述,保护 /etc/resolv.conf 不被修改。
或者,可以使用以下命令配置 NetworkManager 为特定连接自动生成 /etc/resolv.conf 文件
$ nmcli connection modify 'connection-name' ipv4.dns 127.0.0.1 $ nmcli connection modify 'connection-name' ipv4.dns-options trust-ad $ nmcli connection modify 'connection-name' ipv4.ignore-auto-dns yes $ nmcli connection modify 'connection-name' ipv6.dns ::1 $ nmcli connection modify 'connection-name' ipv6.dns-options trust-ad $ nmcli connection modify 'connection-name' ipv6.ignore-auto-dns yes
然后 重启 NetworkManager.service。
随后必须在 dnsmasq 配置文件中以 server=server_address 指定上游 DNS 服务器地址。同时添加 no-resolv,这样 dnsmasq 就不会毫无必要地读取仅包含其自身 localhost 地址的 /etc/resolv.conf。
/etc/dnsmasq.conf
[...] no-resolv # Google's nameservers, for example server=8.8.8.8 server=8.8.4.4
- 本例使用了 Google 公共 DNS。请将其替换为您信任的 DNS 解析器。参阅 域名解析#第三方 DNS 服务。
- dnsmasq 不支持在连接第三方 DNS 服务时所需的 加密协议。一种解决方法是运行一个支持加密 DNS 的独立 DNS 解析器,并将 dnsmasq 的查询转发给它。示例请参阅 Stubby#本地 DNS 缓存配置。
现在 DNS 查询将由 dnsmasq 解析,仅在缓存中无法回答查询时才检查外部服务器。
添加自定义域名
您只需通过添加以下内容即可分配域名:
address=/router/192.168.1.1
或者,如果您想继续在(本地)网络中的主机中使用自定义域名:
local=/home.arpa/ domain=home.arpa
在本例中,可以通过 hostname.home.arpa 来 ping 一个主机/设备(例如在您的 /etc/hosts 文件中定义的)。
取消注释 expand-hosts 以将自定义域名添加到主机条目中
expand-hosts
如果没有此设置,您必须手动将域名添加到 /etc/hosts 的条目中。
测试
要进行查找速度测试,请选择一个在 dnsmasq 启动后尚未访问过的网站(drill 是 ldns 软件包的一部分)
$ drill archlinux.org | grep "Query time"
如果 dnsmasq 设置正确,再次运行该命令将使用缓存的 DNS IP,从而获得更快的查找时间
$ drill archlinux.org | grep "Query time"
;; Query time: 18 msec
$ drill archlinux.org | grep "Query time"
;; Query time: 2 msec
要测试 DNSSEC 验证是否工作,请参阅 DNSSEC#测试本地验证解析器。
DHCP 服务器
默认情况下,dnsmasq 的 DHCP 功能是关闭的,如果您想使用,必须将其开启。以下是重要设置:
# Only listen to routers' LAN NIC. Doing so opens up tcp/udp port 53 to localhost and udp port 67 to world: interface=enp0s0 # dnsmasq will open tcp/udp port 53 and udp port 67 to world to help with dynamic interfaces (assigning dynamic IPs). # dnsmasq will discard world requests to them, but the paranoid might like to close them and let the kernel handle them. # You may also need this option if you have other instances of dnsmasq running (eg. because of libvirtd) bind-interfaces # Optionally set a domain name domain=example.org # Set default gateway dhcp-option=3,0.0.0.0 # Set DNS servers to announce dhcp-option=6,0.0.0.0 # If your dnsmasq server is also doing the routing for your network, you can use option 121 to push a static route out. # x.x.x.x is the destination LAN, yy is the CIDR notation (usually /24), and z.z.z.z is the host which will do the routing. dhcp-option=121,x.x.x.x/yy,z.z.z.z,0.0.0.0/0,0.0.0.0 # Dynamic range of IPs to make available to LAN PC and the lease time. # Ideally set the lease time to 5m only at first to test everything works okay before you set long-lasting records. # The range of addresses here must lie within the address range assigned to the virtual interface. dhcp-range=192.168.111.50,192.168.111.100,12h # Provide IPv6 DHCP leases, the range is constructed using the network interface as prefix dhcp-range=::f,::ff,constructor:enp0s0 # If you’d like to have dnsmasq assign static IPs to some clients, bind the LAN computers NIC MAC addresses: dhcp-host=aa:bb:cc:dd:ee:ff,192.168.111.50 dhcp-host=aa:bb:cc:ff:dd:ee,192.168.111.51
更多选项请参阅 dnsmasq(8)。
代理 DHCP
如果网络上已经运行了一个 DHCP 服务器且您希望与其协作,可以将 dnsmasq 设置为表现得像一个“代理 DHCP”,因此仅向客户端提供 #PXE 服务器 的特定信息。此模式仅适用于 IPv4。使用以下语法,并提供现有的 DHCP 服务器地址:
dhcp-range=192.168.0.1,proxy
测试
在连接到安装有 dnsmasq 的计算机的客户端上,将其配置为使用 DHCP 自动分配 IP 地址,然后尝试正常登录网络。
如果您检查服务器上的 /var/lib/misc/dnsmasq.leases 文件,应该能看到租约信息。
TFTP 服务器
dnsmasq 内置了 TFTP 服务器。
要使用它,请为 TFTP 创建一个根目录(例如 /srv/tftp)以存放可传输的文件。
enable-tftp tftp-root=/srv/tftp
为了提高安全性,建议使用 dnsmasq 的 TFTP 安全模式。在安全模式下,只有属于 dnsmasq 用户的文件才可通过 TFTP 提供服务。您需要将 TFTP 根目录及其所有文件 chown 给 dnsmasq 用户才能使用此功能。
tftp-secure
更多选项请参阅 dnsmasq(8)。
PXE 服务器
PXE 需要 DHCP 和 TFTP 服务器;两者都可以由 dnsmasq 提供。要设置 PXE 服务器,请执行以下步骤:
- 在 dnsmasq 配置文件中设置 #TFTP 服务器 和 #DHCP 服务器(全功能 DHCP 或代理模式),
- 在 TFTP 根目录下复制并配置一个兼容 PXE 的启动加载程序(例如 PXELINUX),
- 在 dnsmasq 配置文件中启用 PXE
若仅发送一个文件:
dhcp-boot=lpxelinux.0
若根据客户端架构发送文件:
pxe-service=x86PC,"PXELINUX (BIOS)",bios/lpxelinux pxe-service=X86-64_EFI,"PXELINUX (EFI)",efi64/syslinux.efi
- 文件路径相对于 TFTP 根路径
- 如果文件具有 .0 后缀,您必须在
pxe-service选项中排除该后缀
如果 pxe-service 无法识别架构(尤其是对于基于 UEFI 的客户端),可以使用 dhcp-match 和 dhcp-boot 的组合。更多用于 DHCP 启动协议的 client-arch 编号请参阅 RFC 4578 2.1。
dhcp-match=set:efi-x86_64,option:client-arch,7 dhcp-match=set:efi-x86_64,option:client-arch,9 dhcp-match=set:efi-x86,option:client-arch,6 dhcp-match=set:bios,option:client-arch,0 dhcp-boot=tag:efi-x86_64,efi64/syslinux.efi dhcp-boot=tag:efi-x86,efi32/syslinux.efi dhcp-boot=tag:bios,bios/lpxelinux.0
更多选项请参阅 dnsmasq(8)。
其余部分由 启动加载程序 处理。
技巧与提示
防止 OpenDNS 重定向 Google 查询
要防止 OpenDNS 将所有 Google 查询重定向到其自己的搜索服务器,请在 /etc/dnsmasq.conf 中添加:
server=/www.google.com/isp-dns-ip
覆盖地址
在某些情况下,例如运行强制网络门户 (captive portal) 时,将特定的域名解析为一组硬编码的地址会很有用。这通过 address 配置实现:
address=/example.com/1.2.3.4
此外,可以使用特殊的通配符,为所有未在 /etc/hosts 或 DHCP 中回答的域名返回一个特定地址:
address=/#/1.2.3.4
运行多个实例
如果我们希望两个或更多 dnsmasq 服务器在每个接口上工作。
静态
若要静态实现——每个接口一个服务器,请使用 interface 和 bind-interfaces 选项。这将启动第二个 dnsmasq 实例,并且仅在运行并发名称服务器时才需要。
例如,若要简单地与 libvirtd 共存,请在 dnsmasq 服务启动选项中添加 --bind-dynamic。
动态式
在这种情况下,我们可以按接口排除并绑定其他任何接口
except-interface=lo bind-dynamic
域名黑名单
要将域名列入黑名单(即对它们的查询回答 NXDOMAIN),请使用 address 选项且不指定 IP 地址
address=/blocked.example/ address=/anotherblocked.example/
/etc/hosts 文件不同,dnsmasq 将拦截这些域名以及所有子域名,例如 subdomain.blocked.example。同时也支持通配符。在模式开头添加 *
# blocks both blocked.example and anotherblocked.example and all their subdomains address=/*blocked.example/ # blocks subdomains like mail.google.com but not google.com address=/*.google.com/
可以使用 # 作为服务器地址来取消屏蔽某些特定的子域名
# blocks google.com and all subdomains except mail.google.com. address=/google.com/ server=/mail.google.com/#
- 选项
address=/example.com/和server=/example.com/是等价的。两者都会对这些查询回答 NXDOMAIN。 - 选项
address=/example.com/#和server=/example.com/#并不等价。address=/example.com/#将对该域名的查询回答空地址 (0.0.0.0 或 IPv6 的 ::)。server=/example.com/#将把该域名的查询发送到标准配置的服务器。
- 模式
/example.com/和/.example.com/是等价的。两者都会匹配 example.com 及其所有子域名。
为了方便使用,请将黑名单放在单独的文件中,例如 /etc/dnsmasq.d/blocklist.conf,并在 /etc/dnsmasq.conf 中通过 conf-file=/etc/dnsmasq.d/blocklist.conf 或 conf-dir=/etc/dnsmasq.d/,*.conf 加载它。
- 可以在 OpenWrt adblock 软件包的 README 中找到潜在的黑名单来源列表。
- hosts 文件黑名单可以使用
addn-hosts=hosts.txt选项,或者可以使用此 awk 命令将其转换为 dnsmasq 黑名单:awk '/^[^#]/ { print "address=/"$2"/"$1"" }' hosts.txt。
查看缓存统计信息
可以使用 chaos 请求查询缓存统计信息,使用来自 ldns 软件包中的 drill 工具
$ drill misses.bind TXT CH $ drill hits.bind TXT CH
输出将分别包含缓存未命中(misses)和命中(hits)的数量
;; ANSWER SECTION: misses.bind. 0 CH TXT "411"
其他选项包括 cachesize.bind, insertions.bind, evictions.bind, auth.bind 以及 servers.bind。