一、dnspod-sr 介绍
dnspod-sr: A faster recursive dns server from DNSPod。 dnspod-sr 是一个运行在 Linux 平台上的高性能的递归 DNS 服务器软件,强烈公司内网或者服务器内网使用dnspod-sr,具备高性能、高负载、易扩展的优势,非 BIND、powerdns 等软件可以比拟。
dnspod-sr 是递归 DNS 程序,功能类似于 BIND ,但是性能较 BIND 高出数倍。可以通过架设 dnspod-sr 集群,替换各大运营商目前基于 BIND 的陈旧方案,减少运营成本;也可以用于公司、学校、政府等组织内部 DNS,解析外部不可见的私有域名,提高上网速度。其中的基础模块也可以在其他项目上使用。
此次开源的是递归 DNS 代码,而非授权 DNS 代码。这意味着 dnspod-sr 只能作为本地递归DNS服务器,也就是说 dnspod-sr 不具备授权功能。
1.1 dnspod-sr 特性
- 高性能,比所有流行的开源 DNS 软件性能高出2倍以上
- 安全,能抵御一般攻击
- 稳定,有效降低解析失败率
- 主动刷新缓存,响应速度更快
- 易于扩展,非常容易部署
- 防污染,能够正确解析被污染域名
1.2 dnspod-sr 性能
dnspod-sr 依托于 DNSPod 多年运营和优化 DNS 服务的经验,针对国内复杂的网络情况,对递归 DNS 进行了一系列的优化,比较其他开源软件,性能得到大幅提升。
这时dnspod-sr官方站点给出的测试数据:
测试环境
千兆网卡,4核 CPU,4G 内存,Linux 64位系统。
性能测试
- dnspod-sr: 15万 qps
- BIND 9.9: 7万 qps
- unbound 4.7: 8万 qps
测试结果如图:
1.3 功能特点
- CNAME解析加速:在解析过程中,dnspod-sr会首先循环查找本地缓存的CNAME记录,如果解析到CNAME记录,再去解析最后一级CNAME记录值的指定记录类型,在解析请求存在CNAME时可以省却递归解析过程,大大加快解析速度。详见 author.c 的 find_record_from_mem() 接口。
- A记录组包缓存:根据我们的解析日志统计,DNS解析请求超过90%都是请求的A记录(即IPv4地址),所以dnspod-sr针对此进行了一项优化,如果授权返回了A记录,则会将该A记录提前组好应答包存储到本地缓存中,在客户端下次请求该记录时省去了组包的过程,加速解析过程。但该功能在前一版本中有时候会出现解析错误的问题,在新版本中暂时移除了该功能,待修正解析错误的问题后会再下一版本重新增加该功能。
- 请求转发功能:通过配置 sr.conf 文件的 xfer: 模块,可以设置在解析指定的域名时直接将该解析请求发送到指定的解析服务器(可以是递归服务器也可以是授权服务器)进行解析。详见 dns.c 的pre_find() 接口。
- 缓存刷新功能:该功能主要用于手动强制刷新dnspod-sr本地缓存中的记录值,主要用于刷新一些被污染的记录或者TTL时间很长但又更新了记录需要快速更新生效时。需要配合 tool 目录下的客户端工具使用。
- HASH表缓存:dnspod-sr的本地缓存方式使用了比较流行的HASH表方式,所有数据缓存在内存中,不进行数据库的相关操作,另外quizzer列表也使用HASH表方式。详见 storage.c 中的相关接口。
- 内存池:内存池是新版新加的功能,主要是减少在缓存查找和递归解析整个过程中频繁的内存分配和释放操作,提高性能。详见 memory.c 中的相关接口。
- 系统函数重写:因为系统函数的性能问题,所以对部分系统函数进行了自行实现,如大小写转换和域名有效性检查改为使用查表法进行;字符串比较和ip地址转换也进行了重新实现等。
1.4 解析过程
上图是一次典型的域名解析过程,如果dnspod-sr已经在本地缓存了解析结果,则会直接返回解析结果,如果没有缓存结果,则会从根开始逐级递归进行解析,递归解析过程可以参考 dig +trace <domain> 的解析结果,当然如果中间某一级的结果已经在本地缓存中存在,则会直接从该级进行递归解析。
在典型的解析过程之外,尚存在一些其他一些非典型操作,如在第一个quizzer线程中,每次循环都会检查用于自动刷新的记录的TTL时间,如果TTL剩余时间小于3秒,就该将记录添加到quizzer列表中,在下次解析时进行刷新。但是目前自动刷新功能尚存在问题,暂时关闭了所有解析记录的自动刷新功能,只对root.z文件中的记录进行刷新。
1.5 尚存在的问题
目前dnspod-sr尚在修改维护中,还存在一些如下问题,将会在之后的版本更新中进行解决,如:
- 不支持PTR反解析;
- 增加配置参数文件,解决现在需要通过修改代码修改配置的问题,如fetcher和quizzer线程数等,并可以通过动态加载部分参数实现不停机修改部分配置;
- 在最近更新中因存在问题而去掉的A记录提前组包功能;
- 红黑树如果自动刷新所有记录尚存在问题;
- 代码整理、包括风格、函数调用和无用代码清理等;
- 增加在程序崩溃时将缓存记录转储到磁盘的功能;
- 较老版本内核和32位系统的兼容性测试等。
二、dnspod-sr 快速开始
2.1 dnspod-sr 安装
下载源码(推荐):
# git clone https://github.com/DNSPod/dnspod-sr.git # cd dnspod-sr
或者下载压缩包:
# wget https://github.com/DNSPod/dnspod-sr/zipball/master
编译源码:
# cd dnspod-sr/src # make # 不需要 make install 步骤, 安装过程很快速
运行
# pwd : dnspod-sr/src ./dnspod-sr
备注:切记一定要在相对路径下执行
程序报了一个异常: set affinity fetcher failed, may be the cpu cores num less than (FETCHER_NUM + QUIZZER_NUM + 1)
set affinity quizzer failed, may be the cpu cores num less than (FETCHER_NUM + QUIZZER_NUM + 1) [DBG:] dnspod-sr is successful running now!! [DBG:] max_ele_size is 1000000 - 1808 [DBG:] server may contain 332730 useful records [DBG:] hash_table_size is 65536 [DBG:] we have 10 hash tables [DBG:] we have 2 fetchers,2 quizzers
在虚拟机测试的时候出现这个问题,难道CPU必须是双核才可以么?
大致看了一下dnspod-sr托管在github上的源码,上面的输出是 dnspod-sr/src/init.c文件的 create_author 函数产生:
for(i = 0;i < QUIZZER_NUM ;i ++) { CPU_ZERO(&cpuinfo); CPU_SET_S(i + FETCHER_NUM + 1, sizeof(cpuinfo), &cpuinfo); if(0 != pthread_setaffinity_np(apt[i], sizeof(cpu_set_t), &cpuinfo)) { printf("set affinity quizzer failed, may be the cpu cores num less than (FETCHER_NUM + QUIZZER_NUM + 1)\n"); // exit(0); } }
可以试试修改一下 src/author.h 头文件:
enum { FETCHER_NUM = 2, SERVER_PORT = 53, };
实际上就是强制 fetcher 跑在0和1两个CPU上,没有双核实际上还是可以跑,只是强制把第二个线程强制在CPU1这个失败了,还是会跑在CPU0上面。
本文很多内容参考: 网站:运维生存时间 网址:http://www.ttlsa.com/linux/dnspod-sr-little-dns/
2.2 dnspod-sr 配置
一、如果你仅仅需要一个dns转发器(DNS缓存服务器),那么什么都不需要配置,直接可以使用。
[[email protected] ~]# dig www.baidu.com @127.0.0.1 ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.30.rc1.el6_6.2 <<>> www.baidu.com @127.0.0.1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34337 ;; flags: qr ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;www.baidu.com. IN A ;; ANSWER SECTION: www.baidu.com. 689 IN CNAME www.a.shifen.com. www.a.shifen.com. 320 IN A 61.135.169.121 www.a.shifen.com. 320 IN A 61.135.169.125 ;; Query time: 781 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sun Apr 19 00:33:35 2015 ;; MSG SIZE rcvd: 90
二、但是如果你想解析自己的域名,修改dnspod-sr上层目录的 root.z, 修改前,请注意备份。
增加 NS / A 记录:
添加完成后, 需要重新启动 ./dnspod-sr, 才能生效。
备注:经过测试发现它不支持CNAME、官方文档几乎是空白。无奈 root.z的最后一行一定要一个空行,否则最后一条记录解析不到。
指定NS服务器
也就是配置DNS转发(forward),将非本区域负责解析的请求转发到其指定的DNS服务器。需要修改配置文件:sr.conf。dnspod-sr 默认配置文件为当前目录下的 sr.conf,也可以在命令行参数中指定
集群式部署
DNSPOD-SR说明文档里面提到支持集群,也没看出怎么支持集群,如果你想实现集群,同步 root.z 文件,前端可以用 lvs、haproxy、keepalived 等等来实现集群,方法很多,不在多说了。
最后
在内网使用dnspod-sr值得推荐,配置简单,集群搭建也简单。相比bind等等要简单很多,但是功能也简单。但是内网下足够用了。dnspod-sr的wiki基本上空白,官方文档没本文详细。官方文档只包含了安装,并未提到如何配置。
参考文章:
DNSPOD-SR Wiki: https://github.com/DNSPod/dnspod-sr/wiki
TTLSA:http://www.ttlsa.com/html/4071.html
网站:运维生存时间 网址:http://www.ttlsa.com/linux/dnspod-sr-little-dns/