一、什么是 DNS
DNS(Domain Name System)是一个全球化的分布式数据库,用于存储域名与互联网 IP 地址的映射关系。DNS 分为两大类:权威 DNS,递归 DNS。
- 权威 DNS: 权威 DNS 服务器只对自己所拥有的域名进行域名解析,对于不是自己的域名则拒绝访问。比如,向 “example.com” 的权威 DNS 服务器查询 “test.com” 的域名肯定会查询失败。
- 递归 DNS: 递归 DNS(也称本地 DNS 或者缓存 DNS)用于域名查询。递归 DNS 会迭代权威服务器返回的应答,直至最终查询到的 IP 地址,将其返回给客户端,并将请求结果缓存到本地。
二、自建 DNS 的作用
- 提供 DNS 缓存。将 DNS 查询结果缓存下来,避免重复向上查询 DNS 结果,提高查询速率。
- 防止 DNS 污染。部分 DNS 提供商会针对部分 DNS 查询返回错误的结果,以达到无法访问或跳转到错误目标地址的目的,自建 DNS 服务则可以避免这样的情况。
三、递归 DNS 的选型
选型主要有两个:
3.1 Knot Resolver
Knot Resolver 是 Knot DNS (高性能的权威 DNS 服务器)的子项目
- 项目开源,源代码在 GPL 许可下可用。
- 高性能,服务器采用与其余 DNS 递归器不同的缩放策略 —— 无线程、无共享架构(除了可能共享的缓存)。可以在不停机的情况下启动、停止或重新配置实例。
3.2 CoreDNS
CoreDNS 是 k8s 中的一个插件,可作为 k8s 的服务发现,也可单独作为 DNS 服务器使用。
- 使用 Go 语言编写,项目开源,在 Apache License Version 2 许可下可用。
- 配置文件简单,语法类似于 Caddyfile。
- 插件丰富,通过插件可提供外部缓存等功能。
四、搭建 Knot-Resolver
本文就先使用 Knot-Resolver 来搭建 DNS 服务
4.1 安装
|
|
4.2 启动服务
|
|
五、配置
配置文件路径:
|
|
5.1 监听接口
以下配置指示 Knot Resolver 在 IP 地址 127.0.0.1
接收标准的未加密 DNS 查询和 DNS-over-TLS 查询
net.listen('127.0.0.1', 53, { kind = 'dns' })
net.listen('127.0.0.1', 853, { kind = 'tls' })
5.2 限制访问
在使用 IP 防火墙不限制 DNS 解析器访问的情况下,可以使用结合查询源信息和策略规则的视图模块来实现访问限制。以下配置仅允许来自子网 192.0.2.0/24 中的客户端的查询,并拒绝所有其余的。
modules.load('view')
-- whitelist queries identified by subnet
view:addr('192.0.2.0/24', policy.all(policy.PASS))
-- drop everything that hasn't matched
view:addr('0.0.0.0/0', policy.all(policy.DROP))
5.3 转发
将 DNS 查询转发到其他公共 DNS 服务商,将自动选择响应最快的 IP 地址进行返回。
policy.FORWARD()
函数一次最多接受四个 IP 地址
-- Forward all queries to public resolvers https://www.nic.cz/odvr
policy.add(policy.all(
policy.FORWARD({
'8.8.8.8',
'1.1.1.1'
})
))
转发到 DNS-over-TLS 则是
policy.add(policy.all(
policy.TLS_FORWARD({
{'1.1.1.1', hostname='one.one.one.one'},
{'1.0.0.1', hostname='one.one.one.one'}
})
))
一些公共 DNS-over-TLS 提供商可能会应用速率限制,这使得他们的服务与 Knot Resolver 的 TLS 转发不兼容。值得注意的是,从 2019 年 7 月 10 日起, Google 公共 DNS将无法使用。
更多配置说明可以查看官方文档:Knot Resolver Docs
参考资料