一、什么是 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 安装
wget https://secure.nic.cz/files/knot-resolver/knot-resolver-release.debdpkg -i knot-resolver-release.debapt updateapt install -y knot-resolver
4.2 启动服务
# 启动服务# 开机自启服务
五、配置
配置文件路径:
/etc/knot-resolver/kresd.conf
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 subnetview:addr('192.0.2.0/24', policy.all(policy.PASS))
-- drop everything that hasn't matchedview: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/odvrpolicy.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'} })))
5.4 DNS 分流
可以配置不同域名走不同 DNS,从而实现 DNS 分流的情况。
分流的域名来自于 ACL4SSR
-- Netflixpolicy.add(policy.suffix( policy.FORWARD({ '1.1.1.1' }), policy.todnames({ 'netflix.com', 'netflix.net', 'nflxext.com', 'nflximg.com', 'nflximg.net', 'nflxso.net', 'nflxvideo.net' })))
-- Disney+policy.add(policy.suffix( policy.FORWARD({ '1.1.1.1' }), policy.todnames({ 'adobedtm.com', 'bam.nr-data.net', 'bamgrid.com', 'braze.com', 'cdn.optimizely.com', 'cdn.registerdisney.go.com', 'cws.conviva.com', 'd9.flashtalking.com', 'disney-plus.net', 'disney-portal.my.onetrust.com', 'disney.demdex.net', 'disney.my.sentry.io', 'disneyplus.bn5x.net', 'disneyplus.com', 'disneyplus.com.ssl.sc.omtrdc.net', 'disneystreaming.com', 'dssott.com', 'execute-api.us-east-1.amazonaws.com', 'js-agent.newrelic.com' })))
-- Geminipolicy.add(policy.suffix( policy.FORWARD({ '1.1.1.1' }), policy.todnames({ 'ai.google.dev', 'alkalimakersuite-pa.clients6.google.com', 'makersuite.google.com', 'bard.google.com', 'deepmind.com', 'deepmind.google', 'gemini.google.com', 'generativeai.google', 'proactivebackend-pa.googleapis.com', 'apis.google.com' })))
-- OpenAIpolicy.add(policy.suffix( policy.FORWARD({ '1.1.1.1' }), policy.todnames({ 'auth0.com', 'challenges.cloudflare.com', 'chatgpt.com', 'client-api.arkoselabs.com', 'events.statsigapi.net', 'featuregates.org', 'identrust.com', 'intercom.io', 'intercomcdn.com', 'oaistatic.com', 'oaiusercontent.com', 'openai.com', 'openaiapi-site.azureedge.net', 'sentry.io', 'stripe.com' })))
更多配置说明可以查看官方文档:Knot Resolver Docs
参考资料