加速OpenWRT路由器的DNS解析 – pdnsd代替dnsmasq

注:新版dnsmasq已经可以手动设置min-ttl和cache-size,使用pdnsd替代dnsmasq已经无太大意义;dnsmasq设置方法,在 /etc/dnsmasq.conf 中加入:


此篇文章说明使用缓存功能更加强大的pdnsd来代替openwrt自带的dnsmasq完成dns解析功能,从而改善解析速度的方法。本篇内容和科学上网没有关系!

OpenWRT默认使用dnsmasq提供DHCP/DNS服务,通常情况下够用。但在某些特殊情况下,DNS查询延迟较大,dnsmasq对于DNS记录的缓存时间、还有缓存文件大小都比较受限,一条记录可能没多久就被清除出缓冲区,失效了。这时我们就希望有一个缓存功能更强的DNS软件,可以手动改大TTL、增大缓存文件大小。这时就可以用pdnsd。你可以配置它,让TTL超期的记录也不被自动清除、可以提高TTL的最小值等等。同时也有完整的可用性检查,你可以配置对DNS服务器的可用性检查,如果一组DNS服务器不可用,可以做故障切换,切至你添加的另一组DNS(比如说你用你的VPS做解析,VPS挂掉了,这时自动切到114DNS或者Google DNS等)。


一、安装

可以直接在Luci界面中,切至软件包配置页面,刷新列表后,键入pdnsd点击安装即可。

也可以使用SSH安装。CC15.05开始,官方源中不再包含pdnsd,请自行到官网的BB14.07版本下对应packages\oldpackages目录下下载对应的pdnsd包手动安装。

二、配置

配置/etc/pdnsd.conf,文件配置分为数个区域,主要修改global区域和server区域,其他区域保留默认值即可。具体的配置文件详情请查阅官方文档:pdnsd Documents

如果不用到其他的server,请确保文件其他的server{}被删除掉或者注释掉

最后,把dnsmasq的dns服务端口改成别的,把53留给pdnsd,反正不是53而且不和其他程序冲突就行了,可以在Luci里面修改(你也可以改/etc/dnsmasq.conf):

dnsmasq_change_dns_port

为了避免改了dnsmasq的dns服务端口后,连接路由器设备无法正常从dhcp服务获取dns服务器地址,还要一步额外的配置,在luci中点击“接口”,然后点击LAN口右边的修改,下方的DHCP服务器中,切至高级设置,在

dhcp

三、启动

给pdnsd设置开机启动:

也可以在Luci的启动项配置页面找到pdnsd,将开机自动从禁用改成启用

最后,重启一下路由,应该就好了。

PS:如果出现问题,排查DNS问题推荐使用DIG工具:为Windows添加DIG等DNS工具

 

81 条评论

  1. Nemo 回复

    是的,shadowsocks代理选择的是忽略列表,shadowsocks和chinadns的chnroute文件都指向ignore.list文件,你说的“使用各类国内IP测试站点检测IP地址”,我不大理解,网络理论知识欠缺,能详细说明一下吗?

    1. cokebar 文章作者 回复

      http://www.ip138.com/ 这类可以显示你IP地址的站点 可以用来判断访问该站点是否走了代理 走了代理会显示代理IP,没走就显示实际IP
      造成国内站点走代理的情况有两种:
      1、站点存在国外服务器,ChinaDNS误判,导致使用国外DNS解析到了国外IP从而走了代理
      2、shadowsocks的chnroute不是最新,或者不完整(比如你用wget下载更新的时候意外中断而你不知情,此时列表不完整),导致shadowosocks将国内IP当国外,从而走了代理
      国内网站访问慢除过走代理的情况,还可能是采用了不恰当的国内DNS服务器 导致解析延迟高 或者解析倒了连接速度不佳的IP上

      1. Nemo 回复

        忘了说chnroute的更新,我都是在VPS上wget好后,才下载到本地路由器的,肯定不会不完整:)

  2. Nemo 回复

    非常感谢,晚上回家继续折腾,话说折腾一次这东西得短寿好几年;好在这次学乖了,路由器配置备份加/overlay方式备份,不至于搞错恢复备份也上不了网或者进不了luci不得不tftp重刷;现在的状态是shadowsocks,chinadns,pdnsd,unbound,全部安装并配置好,只是处于disable状态:)

    另外,给博主提一点小意见,技术博文能开篇说一下思路,整个大致的理论指导,然后细说具体的操作,比较好;因为网络知识很繁杂,水很深;不是科班出生的人可能很难清楚博主的操作,如果再多出几个工具的配置就晕掉了,很可能就把这些工具直接的关联配置搞混淆了,比如https://www.techllage.com/179-openwrt-zhe-teng-xiao-ji-di-er-pianpdnsd-chinadns-dnsmasq-jie-j/0 这个博主其中写的下面这段:

    /*******************************************************************************************/
    工作方式:
    dnsmasq 转发 dns 流量,到 127.0.0.1:5354 (Chinadns的端口),chinadns 处理国内结果时使用114dns,处理国外结果时转发 dns 请求到 127.0.0.1:1053,(工作在1053端口的 pdnsd,使用TCP方式查询),而 pdnsd 将请求交给更上一级的dns 处理,例如 Google Public DNS:8.8.8.8。
    /*******************************************************************************************/
    就很清晰了:)

    1. cokebar 文章作者 回复

      你的建议我也知道 但是不写的人不知道写的人的累。。面面俱到是很难的 一些文章里我也尽量做出说明了 但是像是这一篇 我是以读者有一定基础为前提写的 如果面向OpenWRT的初心者 不知道要多解释多少东西
      这几篇文章自己看来 有些缺乏条理性 有一篇回复特别多 我也尽量都一一回答 但是确实有很多回复抓不到重点 只是提故障表象(比如说只说打不开) 让人完全无法判断到底是什么引起的 可能也是我没有将排错思路说明的原因 但这也牵扯到精力的问题 我只能慢慢改善 可能过一段我会写一篇如何如何排查问题的文章
      感谢提的建议 希望你能最终搞定

      1. Nemo 回复

        你的困难也在理,毕竟是免费的公益行为,那就只能希望翻墙党自己努力提高业务水平,你有更多的精力了,呵呵.。

  3. Nemo 回复

    真是莫名其妙的问题,/etc/init.d/chinadns enable,start ,restart都试过了,luci界面里面一直是未运行,而且ps里面也没有chinadns的进程,用的是最新的1.3.1-1版本,luci也是1.3.1-1的,第一次安装的时候可以,现在又不行了,本地端口也试了没被占用的端口,opkg remove chinadns和它的luci,然后重新安装,还是不行,如何调试从而发现原因?

    1. Nemo 回复

      这个问题博主不用费神回复了,应该是2个DNS ip之间的逗号被我错误的写成了句号

  4. Nemo 回复

    测试发现chinadns启动后3,4秒即死掉了,
    3586 root 844 S /usr/bin/chinadns -p 5555 -s 114.114.114.114,***.***.***:****-c /etc/shadowsocks/ignore.list -m
    无论用114,还是本地ISP的DNS都是这样,***是个人私有DNS服务器,dig无问题。

    似乎是内存不够用挂掉,但是内存还有很多,WNDR3800

    内存
    可用数
    104024 kB / 126324 kB (82%)
    空闲数
    91644 kB / 126324 kB (72%)
    已缓存
    10196 kB / 126324 kB (8%)
    已缓冲
    2184 kB / 126324 kB (1%)

    1. cokebar 文章作者 回复

      加上-v 启动 然后发起几次DNS查询检查输出

      1. Nemo 回复

        隔了几天,刚才-v启动/etc/init.d/chinadns start -v没有,没有任何调试信息,如何处理?

        1. cokebar 文章作者

          init.d哪有这种用法。。。 init.d是启动脚本,就好比Windows中注册表自启动的键值
          你要调试就不能用init.d 你要手动执行chinadns,加-h可以查看用法

      2. Nemo 回复

        # chinadns -v
        Wed Jul 22 23:22:42 2015 CHNROUTE_FILE not specified, CHNRoute is disabled
        Wed Jul 22 23:22:42 2015 chinadns.c:545 bind: Address already in use
        Wed Jul 22 23:22:42 2015 Can’t bind address 0.0.0.0:53

        奇怪luci里面没有问题,怎么说文件没有指定,绑定地址问题?

        1. cokebar 文章作者

          你只有一个-v参数怎么可能启动啊。。。我都让你加 -h看用法了

      3. Nemo 回复

        好吧,里面有个地方错了,4个点分十进制的数被我写成了3个。现在好了;谢谢了

      4. Nemo 回复

        不好意思,水平太菜,见笑了,是下面这样吧,然后dnsmasq DNS转发到5388,最后发起DNS查询检查?
        root@NemoOpenWrt:/usr/bin# /etc/init.d/chinadns stop
        root@NemoOpenWrt:/usr/bin# chinadns -l /etc/chinadns_iplist.txt -c /etc/shadowsocks/ignore.list -p 5388 -m -v

        1. cokebar 文章作者

          加了-m 就没有 -l

      5. Nemo 回复

        看到调试信息了,最后请教一个问题chinadns1.3.1_1,luci也是这个版本版本:luci界面里面没有 -l /etc/chinadns_iplist.txt的接口,
        只有国内路由表:/etc/shadowsocks/ignore.list的接口,init.d/chinadns脚本文件里面也没有默认引入该参数的影子,是我下错文件了吗?

        1. cokebar 文章作者

          启用压缩指针就无需污染列表

  5. Nemo 回复

    谢谢,另外一个疑惑一直没好意思问你,下面是我咨询另一个大虾的邮件,他的回复如下:

    /*********************************************************************************************************/
    你好,大概看了一下,不清楚你既然用了 ChinaDNS,那为什么还要用 Unbound 呢?
    1. 解决 dns 污染用 ChinaDNS 就行了,我的博文也写了,其实 ChinaDNS 是最不折腾的方式了吧
    2. 然后针对自动代理的,我的博文中是通过设置 iptable 进行自动代理切换的,你这边我们看到有任何设置自动代理的地方,你之事解决了 代理+dns 污染的问题,自动代理切换应该根本就没有配置

    下面是我的回复和我的疑惑:
    /*********************************************************************************************************/
    你好,

    我是按照https://cokebar.info/archives/664的方案做的,unbound主要是DNS走TCP查询,防止UDP方式被干扰https://cokebar.info/archives/1053,你说的自动代理配置确实也是我疑惑的地方,不知道原博文作者怎么处理的,博文中好像也没有说明。

    1. Nemo 回复

      哦,我可能想到了,自动代理是通过ignore.list关联起来的,对吧?

      1. cokebar 文章作者 回复

        是的。这篇为了适合新手我就没有详细说明。spec版本是aa65535写的special版本,所有的iptables相关的脚本都写在ss-rules中了,而且还添加了不少选项和功能,省心省力

      2. cokebar 文章作者 回复

        另外说一下 pdnsd比unbound效果好些 unbound我这里用着反应很慢不知道为啥 不知道你有类似情况没

        1. Nemo

          好吧,这里我又糊涂了,我先理清一下头绪:

          1, openwrt自带的dnsmasq具有dhcp和dns转发和解析功能。

          2, unbound主要是dns以tcp模式转发dns查询。它不具有dhcp功能。

          3, pdnsd也是具有dns转发和解析功能,它可以取代dnsmasq的dns功能,具有tcp模式查询,也不具有dhcp功能。

          方案1的dns数据流动为:
          lan的设备dns查询->dnsmasq(udp dns)->chinadns->unbound(tcp dns)

          方案2的dns数据流动为:
          lan的设备dns查询->pdnsd(tcp dns?1)->chinadns->unbound(tcp dns?2)

          方案2的后面还是需要的吧,unbound 必不可少,对吧?

          你说“pdnsd比unbound效果好些”,完全把他们的功能等同了,好像不是这样的。

      3. cokebar 文章作者 回复

        你问的那人估计就没看开头,我文中提到了:方案根据IP判断是否代理,国内IP不代理,国外IP走代理。代理通过shadowsocks所带ss-redir做TCP转发实现,分国内外IP通过国内IP段列表文件chnroute来区别,并通过iptables规则分别处理(这些功能已经全部集成到shadowsocks-spec里了无需额外配置)。

      4. cokebar 文章作者 回复

        不是 我的意思是用pdnsd代替unbound 前端的dnsmasq不变 因为实际使用其实dnsmasq完全够用了
        client>dnsmasq>chinadns>pdnsd>server
        不行可以试试这个改版的dnsmasq 具体作用见本篇第一页第一个回复 那个是aa65535作者本人:https://github.com/aa65535/openwrt-dnsmasq

        1. Nemo

          好吧,总算理清了:

          方案1, client>dnsmasq>chinadns>unbound>server
          方案2, client>dnsmasq>chinadns>pdnsd>server

          对吧,但是你的某个帖子里面,把dnsmasq的通用DNS查询53端口,修改成非53端口,分明就是要用pdnsd替代dnsmasq的DNS功能。可能是我太笨了,模糊了你的意思,看来有必要明天带路由器来单位了。

        2. Nemo

          就是这篇博文,里面是这样写的:

          /*********************************************************************************************************/
          最后,把dnsmasq的dns服务端口改成别的,把53留给pdnsd,反正不是53而且不和其他程序冲突就行了,可以在Luci里面修改(你也可以改/etc/dnsmasq.conf):
          /*********************************************************************************************************/

        3. Nemo

          各种奇奇怪怪的问题,这些问题还具有随机性,退回到前一个状态,有时候还不行;

          要不我直接把路由器快递给你,你帮我弄好了再寄送给我吧,哈哈

  6. Nemo 回复

    为了搞清楚原理,我设想的一次完整的墙内,墙外访问流程,错误之处,请博主给予指点:

    方案1, client>dnsmasq>chinadns>unbound>server
    A)墙内(腾讯视频安卓客户端,简称Tenc.apk)
    1, Tenc.apk发起***v.qq.com***的域名请求,默认#53端口
    2, dnsmasq监听#53端口,收到Tenc.apk的DNS解析请求。
    3_1,如果dnsmasq(openwrt官方原版)或者aa65535的dnsmasq特别版有配置墙内域名匹配表accelerated-domains.china.conf和墙外域名匹配表foreign_list.conf。
    3_1_1,在墙内域名匹配表里面匹配到,那么用114DNS或者本地ISP的DNS去查询***v.qq.com***得到该视频的IP地址,这个时候shadowsocks通过ss-redir和iptables参与进来,至于为什么这个时候参与进来,猜测是DNS的事件查询引发一次事件驱动,使得shadowsocks参与进来;shadowsocks发现该IP属于墙内,于是不走代理。
    3_1_2,如果在墙内域名匹配表里面没有匹配到(墙外域名匹配表肯定匹配不到),那么交给chinadns,chinadns根据chinadns_iplist.txt(shadowsocks/ignore.list)判断,找到了走114DNS,没找到走谷歌DNS(或者自己的DNS);查询成功,触发shadowsocks,走或者不走代理

    B)墙外(youtube.apk)
    1, youtube.apk发起***youtube.com***的域名请求,默认#53端口
    2, dnsmasq监听#53端口,收到youtube.apk的DNS解析请求。
    3_1,如果dnsmasq(openwrt官方原版)或者aa65535的dnsmasq特别版有配置墙内域名匹配表accelerated-domains.china.conf和墙外域名匹配表foreign_list.conf。
    3_1_1,在墙外域名匹配表里面匹配到,那么用谷歌DNS(最好用自己的DNS),这个时候shadowsocks通过ss-redir和iptables参与进来,shadowsocks发现该IP属于墙外,于是走代理。
    3_1_2,如果在墙外域名匹配表里面没有匹配到(墙内域名匹配表肯定匹配不到),那么交给chinadns,chinadns根据chinadns_iplist.txt(shadowsocks/ignore.list)判断,走谷歌DNS(或者自己的DNS),发给监听本地某个端口的unbound,unbound以tcp方式查询DNS(或者自己的DNS);查询成功,触发shadowsocks,走代理

    /*********************************************************************************************************/

    方案2, client>dnsmasq>chinadns>pdnsd>server
    同方案1,只是pdnsd的min_ttl,缓存大小,清空时间更大

    1. cokebar 文章作者 回复

      1、如果你的unbound运行良好,那就没问题;我推荐pdnsd除过pdnsd功能强一些外,unbound在我这里运行有问题,经常DNS查询缓慢,有时候要1秒多才有结果。
      2、ChinaDNS同时向你填入的所有DNS发起查询,根据返回的A记录判断:
      ①国内DNS查询A记录为国内IP,国外DNS查询A记录为国内IP:采用国内DNS结果
      ②国内DNS查询A记录为国外IP,国外DNS查询A记录为国外IP:采用国外DNS结果
      ③国内DNS查询A记录为国内IP,国外DNS查询A记录为国外IP:这个我不确定有没有进一步的判断,但是我估计是简单地采用了国外DNS的结果
      3、一次HTTP访问首先就是域名解析,然后是对目标主机发起TCP连接;发起TCP连接的时候,iptables规则起到对国内和国外IP分别处理的作用。这个方案是列表内不走代理,列表外走代理,因此读入chnroute文件,将文件中所有的IP段保存在一个ipset中;此时做出判断,目标主机IP在ipset中时候,跳回正常的处理过程,直连;如果不在ipset中,将数据包转发至ss-redir的1080本地端口,交由ss-redir处理。ss-redir会对数据包做出相应处理后,经过加密发送至服务端。对国内国外IP的区分,全都是iptables规则配合ipset功能实现的,都是一条条的防火墙规则。而shadowsocks只是负责建立加密代理通讯,转发相应数据包。
      4、如果想要更深入一些了解一些细节,这里有一篇文,讲的是iptables的用法,也讲了很多理论知识,适合细读:
      http://man.chinaunix.net/network/iptables-tutorial-cn-1.1.19.html

      1. Nemo 回复

        连接文章太专业太长看不下去,而且我现在也没有能力开发工具,只想把大神的工具用好;呵呵

  7. Nemo 回复

    博文里面说:

    方案1, client>dnsmasq>chinadns>unbound>server
    方案2, client>dnsmasq>chinadns>pdnsd>server

    方案2的pdnsd性能比unbound好, pdnsd和unbound的主要功能都是使DNS查询走TCP方式,还有ttl时间改善之类的,结果博文里面却显示

    query_method=udp_only; # 只使用UDP,保留默认,

    是错误的写成udp_only了吧,难道不应该是tcp_only?

  8. Nemo 回复

    博文回复说用pdnsd代替unbound,前端的dnsmasq不变,结果后面又说下面这段:

    最后,把dnsmasq的dns服务端口改成别的,把53留给pdnsd,反正不是53而且不和其他程序冲突就行了,可以在Luci里面修改(你也可以改/etc/dnsmasq.conf):

    ip = 127.0.0.1; # 填写DNS的IP地址,多个地址逗号分隔,可以换行,分号结尾
    port = 5353; # 填写DNS的端口,我这里上一级是路由器上的ChinaDNS,监听的5353
    # 所以填写了IP:127.0.0.1 端口:5353,如果使用114DNS等公共
    # DNS 这里端口号应该是53,或者删除该行也行

    分明是pdnsd代替了dnsmasq和unbound,,,,,,,,,,,天啦,博主你都写了些什么啊???

    1. cokebar 文章作者 回复

      那几篇文章都是单独的讨论一种情况 和你要用的方案又不同 这篇pdnsd只是单独讨论pdnsd代替dnsmasq的方式 主要是介绍pdnsd的用法 我肯定是单独介绍工具用法 怎么搭配看自己 方案多种多样
      不要总想着依葫芦画瓢 我的目标是授人以渔 而且我在TCP解析那篇很清楚的用加粗的字体说明了 pdnsd的用法可以参考这篇但这篇的应用情景和那篇不同,这篇写的日期早多了,这篇写的时候墙还不会随机IP的污染:

      “可以参照这篇:改善DNS解析 – OpenWRT安装配置pdnsd(讲的内容不大相同但可以参照,把tcp_udp换成tcp_only,其他的酌情调节一些就可以了)”

    2. cokebar 文章作者 回复

      我自TCP方式我只写了unbound方案 而且博文也有时效性 过一段不合适了 我不可能把每篇之前的都更新了

      1. Nemo 回复

        在你的博客里面绕来绕去,头都晕了,

        真要授人以渔,还是有空写个纲领性的博文,基本思路,有哪些工具,工具的作用,其实也就 DNS这一块吧

        1. cokebar 文章作者

          唉。。我说啥好呢。。。
          你仔细回头看看自己的回复想想自己的心理,你就是想要一个和你需求完全相同的方案的教程。这就是典型伸手党心理。
          再分析一下你为什么会看晕,看晕是因为有不懂的地方,我刚开始搞的时候也晕,同样一个软件一篇博文这样说另一篇那样说,有时候也遇到一篇博文讲的是老版本但软件更新步骤变化了。这怎么办?网上查这些资料永远都是讲的只是”点“,不像教材讲的是”面“。中国应试教育惯了,习惯固定步骤套公式,这些问题永远没有固定解。我的思路是,这些文章虽说没法一下子照搬过来,讲的案例很多情况和我的需求并不相同,但都有基本用法的介绍,也给出了官方文档的链接,结合多篇文章我搞清楚用法,理解了,我就可以按照自己的需修去应用。

        2. Nemo

          你说的在理,主要是我网络方面的知识太少,所以建议你写纲领性的东西,就那么几个工具,功能都摆在哪里,原理搞清楚了,调试手段知道了,大家自己组合搭配用,就容易了;新手不能一上来就理解很深,就能有自己的想法,都是在别人的照搬别人的东西,基本上成功了,才会有兴趣研究里面的东西,才有新的原创的东西

        3. cokebar 文章作者

          我毕竟水平有限 我的模式是有问题留言交流 你要我做提纲整理。。。我估计没那水平整理清楚 像现在每篇文章可以有自己的案例 文章之间案例不同没有问题 但整理到一块儿你就要考虑关联性了 就要尽量做到设计统一的案例情景 整理好文章结构。而且做到那些还得有一定程度的文字量积累。我不觉得我又那么高的水平。这块的知识需要了解的很广,没法一蹴而就,而且也很难讲需要的知识系统的整理到一起做成教材性质的东西。
          极其建议恶补一下网络知识,考级的教材就不错,这东西有兴趣就学的很快。还有Linux系统的知识。当初我是对shell script,init.d这些东西完全不懂。。。刚拿到openwrt时候太痛苦了,官方的文档看不懂,后来也是找资料补知识,谷歌这方面强太多了

    3. cokebar 文章作者 回复

      这篇当时写的目的是pdnsd替代dnsmasq羸弱的缓存功能加快解析。
      而你的情况是使用pdnsd完成TCP转发功能

  9. Nemo 回复

    dnsmasq结合GFWLIST和ChinaList,用的114和谷歌dns,测试结果可以接受,
    由于单位网络端口限制,家里的网络的isp的dns和自建dns还没有试用
    目前的基础上,有什么改进建议?unbound或者pdnsd吗?

  10. Saramande 回复

    想请教下这篇博文截图中为什么Openwrt高级设置->DNS服务器端口设置成5555。
    无论是前文中pdnsd的配置文件编辑还是关于chinadns的端口都没有提到这个端口号,设置成这个端口号是要和什么对应起来么?还是说在ChinaDNS的设置中需要连带改动些什么设置?

    1. cokebar 文章作者 回复

      感谢你发现这个问题 是因为最近一次编辑把一部分内容误删了

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

请输入验证码 *