曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3698|回复: 0
打印 上一主题 下一主题

[系统应用] openwrt 上通过 pdnsd 和 dnsmasq 解决 dns 污染

[复制链接]

716

主题

734

帖子

2946

积分

超级版主

Rank: 9Rank: 9Rank: 9

积分
2946
跳转到指定楼层
楼主
发表于 2014-11-3 17:04:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以前一直在路由器上改域名 ip 来解决 google 系列服务无法使用的问题, 不过斯巴达以来 google 就没有一个相对稳定的 ip 可以指定了, 经常是好了一天第二天又失效了, 被逼着走代理之类的, 真心的烦躁.
不过浏览器啥的都还好, 走走代理无所谓但对于一些应用比如 Things 或者 nvALT 之类用 GAE 同步的软件就比较麻烦了. 那些软件本身并不能代理设置只有系统全局的, 但全局的又会导致那些国内的软件缓慢.
当然要解决上述问题方法有很多, 但如果可以通过 dns 来解决的话, 只要能在路由器上设置下. 下面的所有设备就自然而然的解决的, 特别是对于那些不能 root 的 android 或者 iphone 来说, 会方便很多很多.
当然修改 dns 之类的只能解决污染问题, 对于 ip 封锁或者 关键字封锁也是没有任何办法的. 所以只有那种全面启用了 https 并且 在全球有很多服务器那种网站才能完美的解决, 典型的例子就是 google .
目前 dns 污染流程
当需要访问某个网站的时候, 系统自动的向 dns 查询当前这个域名对应的 ip 地址, 如果当前 dns 无法回答时候, 它又会向它的上级 dns 取查询直到找到为止. 但那些 dns 服务器如果在 GFW 外的话, 当经过 GFW 时, GFW 就会检测请求的域名. 如果是被屏蔽的话, 就会返回一个错误的 ip 导致网站无法访问.


经过搜索和研究后发现, 这么多年了过去了 dns 污染还是只污染 UDP 协议, 如果可以用 TCP 协议进行 dns 请求的话就可以得到正确的结果.
不过找了很久都没找到一个比较好的既支持 tcp dns 请求, 又可以很好可以根据域名来分别处理的软件. 最终还是把方案定为 dnsmasq + pdnsd 的方案. pdnsd 主要提供一个无污染的 dns, dnsmasq 主要根据域名来切换相应的 dns.
pdnsd
主要用来解决污染问题, 在 openwrt 上直接找到 pdnsd 包安装就可以了.
[Bash shell] 纯文本查看 复制代码
opkg update
opkg install pdnsd


安装好以后还需要修改 /etc/pdnsd.conf, 其主要配置如下:
[Bash shell] 纯文本查看 复制代码
global {
        # debug = on;          # 调试模式, 日志会写入 /var/pdnsd/pdnsd.debug
        perm_cache=1024;
        cache_dir="/var/pdnsd";
        run_as="nobody";
        server_port = 1053;    # 使用 1053 作为 dns 端口, 默认是 53
        server_ip = any;
        status_ctl = on;
        query_method=tcp_only; # 最重要的配置, 只使用 tcp 查询上级 dns
        min_ttl=15m;
        max_ttl=1w;
        timeout=10;
}

server {
        label= "wido";           # 这个随便写
        ip = ${UPSTREAM_DNS_IP}; # 这里为上级 dns 的 ip 地址
        root_server = on;        # 设置为 on 后, 就代替系统默认的 dns 了.
        uptest = none;           # 不去检测 dns 是否无效.
}

source {
        owner=localhost;
#        serve_aliases=on;
        file="/etc/hosts";
}

rr {
        name=localhost;
        reverse=on;
        a=127.0.0.1;
        owner=localhost;
        soa=localhost,root.localhost,42,86400,900,86400,86400;
}

其中的 ${UPSTREAM_DNS_IP} 需要设置成, 支持 TCP dns 查询的服务器.
可以用 8.8.8.8 这个 google 的 dns 但不是很推荐, 主要是他返回的 ip 虽然没污染, 但这个 ip 很可能也是被封的. 最好是那些 台湾, 日本, 或者美国东部的 dns. 目前大陆默认走的就是香港的 google 服务器, 所以香港的 dns 也不予考虑.
当然最好的方案还是, 如果你自己在海外有 VPS 那就在服务器上装个 pdnsd 来做 dns 服务器吧.
可以用命令
[Bash shell] 纯文本查看 复制代码
dig @8.8.8.8 +tcp [url=http://www.google.com]www.google.com[/url]

来做测试, 不过也遇到过 +tcp 可以访问但实际无法用 pdnsd 连接的情况具体原因未知. 我这是自己服务器搭了 pdnsd 解决的.
在找到可用的 dns 后, 接着修改回 pdnsd.conf 文件后输入
[Bash shell] 纯文本查看 复制代码
/etc/init.d/pdnsd enable
/etc/init.d/pdnsd start

启动路由器上的 pdnsd 服务之后就可以通过命令 (@192.168.2.1 根据自己家的网络情况改)
[Bash shell] 纯文本查看 复制代码
dig @192.168.2.1 -p 1053 [url=http://www.google.com]www.google.com[/url]

来检测是否已配置好, 还是不行的话, 可以尝试开启 pdnsd.conf 的 dubug 模式看详细的日志, 配合 pdnsd-ctl help 来做进一步处理.
dnsmasq
本来指望 pdnsd 把 dnsmasq 的任务也一并解决的, 不过研究后发现他并不能将特殊的域名交给特殊的 dns 处理, 所以这部分功能还需要交给 dnsmasq.
对于 openwrt 来说默认就安装好了 dnsmasq, 所以这里只需要简单的编辑 /etc/dnsmasq.conf, 再最后加入
[Bash shell] 纯文本查看 复制代码
conf-dir=/etc/dnsmasq.d

让 dnsmasq 会去加载 /etc/dnsmasq.d 目录下所有的配置.
然后在建一个 /etc/dnsmasq.d/gfw.conf 这样的文件, 把需要进化的域名代理给 pdnsd 就可以了, 例如:
[Bash shell] 纯文本查看 复制代码
# google
server=/.google.com/127.0.0.1#1053
server=/.gstatic.com/127.0.0.1#1053
server=/.googleusercontent.com/127.0.0.1#1053
server=/.appspot.com/127.0.0.1#1053
server=/.googlecode.com/127.0.0.1#1053
server=/.googleapis.com/127.0.0.1#1053
server=/.gmail.com/127.0.0.1#1053
server=/.google-analytics.com/127.0.0.1#1053
server=/.youtube.com/127.0.0.1#1053
server=/.blogspot.com/127.0.0.1#1053
server=/.blogger.com/127.0.0.1#1053

之后重启 dnsmasq 服务
[Bash shell] 纯文本查看 复制代码
/etc/init.d/dnsmasq restart


一般来说这样折腾以后 google 系列的服务应该就可以访问了, 当然也可以按这个写法自己加其他的域名. 比如 .facebook.com, 具体的还得是满足 ip 没被封且关键字不被过滤(https) 的网站才行.
参考资料

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-3 13:23 , Processed in 0.067856 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表