Total Pageviews

Thursday 12 October 2017

一个Google DNS的代理程序-PRCDNS


这是一个Google DNS的代理。
不同之处在于CDN友好,根据你的IP返回最优的解析结果.

原理

DNS-over-HTTPS API
它支持edns_client_subnet,把你的IP作为参数提交,它会返回最优的解析结果,所以说它 是我见过的最完美的DNS解决方案。

测试

#本人北京联通,对比OPENDNS进行测试,证明PRCDNS是CDN友好的
#23.106.151.177:3535 是我搭建的测试地址,遇到攻击可能会关闭
#seaof-153-125-234-242.jp-tokyo-12.arukascloud.io:31910 部署在日本樱花docker
#208.67.222.222:443  OPENDNS
dig @23.106.151.177 +tcp -p 3535 google.com.hk
dig @208.67.222.222 +tcp -p 443 google.com.hk

dig @23.106.151.177 +tcp -p 3535 img.alicdn.com #123.125.18.108北京联通
dig @seaof-153-125-234-242.jp-tokyo-12.arukascloud.io +tcp -p 31910 img.alicdn.com #123.125.18.108北京联通
dig @208.67.222.222 +tcp -p 443 img.alicdn.com  #69.192.12.15香港

注意事项:PRCDNS前面一定要放pdnsd或者unbound

  1. PRCDNS只支持TCP查询
  2. PRCDNS没有缓存
很多二级运营商为了节省成本,减少外网之间的带宽结算费用,对DNS查询做了重点照顾, 防止用户使用114、百度、阿里的公共DNS,强制用户将某些流量大的域名指向它的缓存服务器, 于是UDP成了重灾区,目前TCP没事,114已经支持TCP,百度、阿里还不行。PRCDNS前面放 pdnsd、unbound,即解决了缓存问题,又解决了UDP的问题

安装

基于Python 3.5
sudo pip3 install PRCDNS

使用

如果你把PRCDNS部署到VPS上,和SS做邻居,这样在家、公司都能用
PRCDNS
如果把PRCDNS部署到自己本地的机器或者路由器上,请将SS通过polipo转为http类型,以便于PRCDNS可以访问https://developers.google.com
PRCDNS -r http://127.0.0.1:8123
请使用Supervisor保证PRCDNS一直运行

参数

--debug 调试模式 选填 默认false
-l 监听IP 选填 默认0.0.0.0
-p 监听端口 选填 默认3535
-r http_proxy 如果PRCDNS可以访问https://developers.google.com就不用填写
欢迎通过Issue讨论、提问和给予指导

更多文档

docker 方式运行

  1. build: docker build -t prcdns:latest .
  2. run: docker run -p 3535:3535 -d --name prcdns prcdns:latest

from https://github.com/lbp0200/PRCDNS
------------

使用Asyncio实现的DNS Over Https


基本就是一个类似PRCDNS的轮子,不过做了一些修改和优化。思路基本和PRCDNS是一样的,其实Google DNS本身就支持EDNS Client IP这个功能,但UDP查询基本都被污染,TCP查询的Client IP是基于实际的连接IP,考虑国内网络状况,实际连接IP根本不可能是你本地IP,所以DNS Over Https这种可以自己指定Client IP的才是最好解决办法。

项目地址

项目的最新情况请参考Github的README

为什么要重复造轮子?

  1. 学习AsyncIO,尤其是UDP Server,就这么简单。
  2. PRCDNS仅仅支持TCP,操蛋的是Dnsmasq不支持TCP Query Only,还得加一层PDNSD才行,这个太浪费了。虽然考虑到UDP DNS查询的严重劫持情况和UDP本身无连接的脆弱,其实TCP查询是合理的,不过我的想法更简单:只把这玩意部署在路由器上,出去的只有到Google Https的连接。至于怎么连接到Google Https,你路由器不可能没有SS吧,所以我没有做额外的Socks支持。至于什么样的路由器才能支持Python3和aiohttp,x86软路由当然是王道
  3. PRCDNS没有考虑到一种情况:很多网站其实我们都是走代理的,基于本地IP去做edns client ip查询其实是不合理的。例如用中国IP去查Google的地址,返回的基本都是台湾的IP,可你的代理如果在日本甚至美国,这个就比较尴尬了,会增加50ms甚至100ms的延迟。
  4. DNS Over Https有一个鸡生蛋蛋生鸡的尴尬:如果DNS Over Https是唯一的解析器,现在你想解析域名就要去访问dns.google.com,可是你不知道dns.google.com的地址,于是你向自己查询,然后你自己又去问dns.google.com这个dns.google.com的地址是什么,于是。。。。
  5. PRCDNS只解析A记录,这个,如果只作为抗污染辅助手段还是可以的,如果要作为主DNS服务器,这个还是有点不能接受的,毕竟这是残缺的。

Help:

usage: AsyncHttpsDNS [-h] [-p [PORT]] [-i [IP]] [-f [FILE]] [-d [DEBUG]]
                     [-s [SOCKS]]

optional arguments:
  -h, --help            show this help message and exit
  -p [PORT], --port [PORT]
                        Port for async dns server to listen
  -i [IP], --ip [IP]    IP of proxy server to bypass gfw
  -f [FILE], --file [FILE]
                        file that contains blocked domains
  -d [DEBUG], --debug [DEBUG]
                        enable debug logging
  -s [SOCKS], --socks [SOCKS]
                        socks proxy IP:Port in format like: 127.0.0.1:1086
  1. AsyncHttpsDNS=>直接启动一个在5454端口的DNS服务器,无代理(如果你可以直连dns.google.com的话),无翻墙域名优化,
  2. AsyncHttpsDNS -s 127.0.0.1:1086,同上,但使用127.0.0.1:1086地址上的socks5代理(shadowsocks默认地址),
  3. AsyncHttpsDNS -s 127.0.0.1:1086 -i 45.32.15.77,同上,但请求被墙的域名是使用45.32.15.77作为client ip,对应域名解析的结果为此IP优化,
  4. AsyncHttpsDNS -s 127.0.0.1:1086 -i 45.32.15.77 -f mydomains.txt,同上,但使用当前目录的mydomains.txt文件作为被墙域名列表,
  5. sudo AsyncHttpsDNS -s 127.0.0.1:1086 -i 45.32.15.77 -f mydomains.txt -p 53,同上,但监听本地53端口。

使用注意:

  1. 默认监听5454端口,无缓存,配合dnsmasq使用已经足够了,如果要改成53端口,需要有sudo权限。
  2. 默认使用114和腾讯DNS解析dns.google.com地址,这个在国内用基本没啥问题,如果你本地的114和腾讯DNS都会被污染,自己改代码,为这个加参数挺无聊的。
  3. foreign_domains.txt保存的是国外域名的地址,其实这个就是gfwlist域名,原因不用解释。实际上这个列表不需要这么大,只需要被屏蔽的又有CDN服务器的域名即可。
  4. 重点!!使用-i参数指定你的代理服务器IP地址,默认的是日本Vultr地址,不一定合适你。

安装

直接:
pip3 install asynchttpsdns
from https://lifetyper.com/posts/async_dns_over_https.html

No comments:

Post a Comment