以前一直在路由器上改域名 ip 来解决 google 系列服务无法使用的问题, 不过斯巴达以来 google 就没有一个相对稳定的 ip 可以指定了, 经常是好了一天第二天又失效了, 被逼着走代理之类的, 真心的烦躁.
不过浏览器啥的都还好, 走走代理无所谓但对于一些应用比如 Things 或者 nvALT 之类用 GAE 同步的软件就比较麻烦了. 那些软件本身并不能代理设置只有系统全局的, 但全局的又会导致那些国内的软件缓慢.
当然要解决上述问题方法有很多, 但如果可以通过 dns 来解决的话, 只要能在路由器上设置下. 下面的所有设备就自然而然的解决的, 特别是对于那些不能 root 的 android 或者 iphone 来说, 会方便很多很多.
当然修改 dns 之类的只能解决污染问题, 对于 ip 封锁或者 关键字封锁也是没有任何办法的. 所以只有那种全面启用了 https 并且 在全球有很多服务器那种网站才能完美的解决, 典型的例子就是 google .
当需要访问某个网站的时候, 系统自动的向 dns 查询当前这个域名对应的 ip 地址, 如果当前 dns 无法回答时候, 它又会向它的上级 dns 取查询直到找到为止. 但那些 dns 服务器如果在 GFW 外的话, 当经过 GFW 时, GFW 就会检测请求的域名. 如果是被屏蔽的话, 就会返回一个错误的 ip 导致网站无法访问.
经过搜索和研究后发现, 这么多年了过去了 dns 污染还是只污染 UDP 协议, 如果可以用 TCP 协议进行 dns 请求的话就可以得到正确的结果.
不过找了很久都没找到一个比较好的既支持 tcp dns 请求, 又可以很好可以根据域名来分别处理的软件. 最终还是把方案定为 dnsmasq + pdnsd 的方案. pdnsd 主要提供一个无污染的 dns, dnsmasq 主要根据域名来切换相应的 dns.
主要用来解决污染问题, 在 openwrt 上直接找到 pdnsd 包安装就可以了.
opkg update
opkg install pdnsd
安装好以后还需要修改 /etc/pdnsd.conf
, 其主要配置如下:
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 服务器吧.
可以用命令
dig @8.8.8.8 +tcp www.google.com
来做测试, 不过也遇到过 +tcp
可以访问但实际无法用 pdnsd 连接的情况具体原因未知. 我这是自己服务器搭了 pdnsd 解决的.
在找到可用的 dns 后, 接着修改回 pdnsd.conf 文件后输入
/etc/init.d/pdnsd enable
/etc/init.d/pdnsd start
启动路由器上的 pdnsd 服务之后就可以通过命令 (@192.168.2.1
根据自己家的网络情况改)
dig @192.168.2.1 -p 1053 www.google.com
来检测是否已配置好, 还是不行的话, 可以尝试开启 pdnsd.conf 的 dubug 模式看详细的日志, 配合 pdnsd-ctl help
来做进一步处理.
本来指望 pdnsd 把 dnsmasq 的任务也一并解决的, 不过研究后发现他并不能将特殊的域名交给特殊的 dns 处理, 所以这部分功能还需要交给 dnsmasq.
对于 openwrt 来说默认就安装好了 dnsmasq, 所以这里只需要简单的编辑/etc/dnsmasq.conf
, 再最后加入
conf-dir=/etc/dnsmasq.d
让 dnsmasq 会去加载 /etc/dnsmasq.d
目录下所有的配置.
然后在建一个 /etc/dnsmasq.d/gfw.conf
这样的文件, 把需要进化的域名代理给 pdnsd 就可以了, 例如:
# 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 服务
/etc/init.d/dnsmasq restart
一般来说这样折腾以后 google 系列的服务应该就可以访问了, 当然也可以按这个写法自己加其他的域名. 比如 .facebook.com
, 具体的还得是满足 ip 没被封且关键字不被过滤(https) 的网站才行.