Total Pageviews

Wednesday 6 July 2016

在linux vps上,编译dnscrypt-wrapper,搭建防污染的DNS服务器

众所周知,在我朝局域网当中想要获取国外 DNS 信息,必定会遭到关键字污染。为此,有人想到了使用异常端口,比如5353而不使用 DNS 专用端口53——因为目前 Girl Friend Wall 只污染53;也有人想到了使用 TCP 连接请求,因为 DNS 的应答机制决定了它会接受第一个返回的响应,后边的会被丢弃,而使用 TCP 则强制接受选定的数据包;甚至有人想到了把那些发污染包的 IP 地址收集起来,然后在客户端处过滤——加入黑名单,这样最终就会收到正确的响应包。
总之,这些都不是什么长久之计,使用 OpenDNS 出品的 dnscrypt 是一个不错的选择,它在 DNS 的基础之上增加了加密的选项,让你的 DNS 请求能够像使用 ssl 一样加密地请求服务器,这样便从根本上杜绝了 DNS 污染问题。

那么问题来了,就算你是用了dnscrypt-proxy,可是公共服务器的IP 被认证了呢?答案是——这就是最近 dnscrypt 越来越不给力的原因。另外,OpenDNS 虽然捣鼓出了这么个给力的玩意儿,但是他们却没有公开服务端——也就是说你必须使用那有限的几个国外的服务器,速度绝对快不到哪里去。

所以,我朝有大神根据 dnscrypt 的客户端dnscrypt-proxy写出了牛逼闪闪的服务端:dnscrypt-wrapper,
https://github.com/Cofyc/dnscrypt-wrapper

我们现在可以自己在境外服务器搭建一个 dnscrypt 服务器,本地来连接它就好了——你可以选择一个速度比较快的 vps。

dnscrypt的服务端dnscrypt-wrapper的搭建(按此文,我成功搭建了dnscrypt-wrapper)

前言

DNS解析的记录可能会被劫持,这里用Dns Crypt加密DNS的解析请求,这里介绍其服务端dnscrypt-wrapper的搭建。

相关依赖

dnscrypt-wrapper需要libsodium和libevent 2.1.1+。
安装编译需要的依赖:
  1. sudo apt-get install build-essential autoconf

libsodium

  1. git clone https://github.com/jedisct1/libsodium
  2. cd libsodium
  3. ./configure && make -j2 && make install
  4. ldconfig

libevent

  1. wget -O /root/libevent-2.1.8-stable.tar.gz https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz --no-check-certificate
  2. tar zxvf /root/libevent-2.1.8-stable.tar.gz
  3. cd /root/libevent-2.1.8-stable
  4. ./configure
  5. make
  6. make install
  7. ldconfig

dnscrypt-wrapper

安装好相关依赖之后就可以编译dnscrypt-wrapper了。

安装

  1. git clone git://github.com/cofyc/dnscrypt-wrapper.git
  2. cd dnscrypt-wrapper
  3. make configure
  4. ./configure
  5. make install

设置

  1. mkdir /root/dnskey && cd /root/dnskey
  2. dnscrypt-wrapper --gen-provider-keypair --provider-name=2.dnscrypt-cert.example.com --ext-address=your-vps-ip:5353 --nofilter
  3. 会显示:
    Generate provider key pair... ok. Stamp for dnscrypt-proxy 2.x: sdns://AQQAAAAAAAAADjE3NC4xMzcuNTAuMjAzICkuKSNXqJUumXpZw6oWeC-i9dcBdu-DLhKoeWz6YG9mGzIuZG5zY3J5cHQtY2VydC5leGFtcGxlLmNvbQ Parameters for dnscrypt-proxy 1.x: dnscrypt-proxy --provider-key=292E:2923:57A8:952E:997A:59C3:AA16:782F:A2F5:D701:76EF:832E:12A8:796C:FA60:6F66 --resolver-address=your-vps-ip:5353
    --provider-name=2.dnscrypt-cert.example.com Keys are stored in public.key & secret.key.
  1. dnscrypt-wrapper --gen-crypt-keypair --crypt-secretkey-file=example.com.key
  2. dnscrypt-wrapper --gen-cert-file --crypt-secretkey-file=example.com.key --provider-cert-file=example.com.cert --provider-publickey-file=public.key --provider-secretkey-file=secret.key --cert-file-expire-days=365d
  3. #将证书过期时间设置为365天。这也意味着你需要在365天以后再运行上面这行命令,然后重启dnscrypt-wrapper.
  4. dnscrypt-wrapper --resolver-address=8.8.8.8:53 --listen-address=0.0.0.0:5353 --provider-name=2.dnscrypt-cert.example.com --crypt-secretkey-file=example.com.key --provider-cert-file=example.com.cert -d
  5. #其中的--provider-name=必须是以2.dnscrypt-cert.开头.

自启动设置。在支持systemd的系统上:
nano /etc/systemd/system/dnscrypt-wrapper.service
其内容为:
  1. [Unit]
  2. Description=dnscrypt-wrapper
  3. After=network.target
  4. [Service]
  5. ExecStart=/usr/local/sbin/dnscrypt-wrapper --resolver-address=8.8.8.8:53 --listen-address=0.0.0.0:5353 --provider-name=2.dnscrypt-cert.example.com --crypt-secretkey-file=/root/dnskey/example.com.key --provider-cert-file=/root/dnskey/example.com.cert
  6. Restart=always
  7. [Install]
  8. WantedBy=multi-user.target
  9.  
    然后运行:
  1. systemctl enable dnscrypt-wrapper
  2. systemctl start dnscrypt-wrapper

在mac上,参见http://briteming.blogspot.com/2016/04/macdnscrypt-proxy.html,搭建客户端程序:dnscrypt-proxy。 
dnscrypt-proxy安装好后,
运行:
sudo dnscrypt-proxy --local-address=127.0.0.1:53 --provider-name=2.dnscrypt-cert.example.com --provider-key=292E:2923:57A8:952E:997A:59C3:AA16:782F:A2F5:D701:76EF:832E:12A8:796C:FA60:6F66 --resolver-address=your-vps-ip:5353 --tcp-only
------------------------------------------------------------

教程开始

作为演示,我这里的服务器是 ubuntu 14.04.

编译库文件

dnscrypt-wrapper 依赖 libsodium 和 libevent2;前者一般源里没有,后者一般默认版本不是2而是比较旧的1,我们得先来手动编译这两个库。

我们从这里http://download.libsodium.org/libsodium/releases/下载 libsodium 的最新版本 ,截止到本文完成时,最新版本为1.0.10:

然后我们从这里下载 libevent2 ,这里我们选择 2.0.22 稳定版:

编译 dnscrypt-wrapper

搞定两个依赖库之后,就可以开始编译 dnscrypt-wrapper 啦:
如果你在 make configure 这一步出错,你可能需要先安装 autoconfig:
如果没什么问题,那么就可以开始编译安装了:

至此编译完成。

dnscrypt-wrapper 的配置和使用

这里系统会反馈一个指纹信息(即--provider-key的值),这个信息就是客户端配置时候需要的“provider_public_key”!所以一定要保存好。
类似这个样子:
然后,我们使用命令生成有时限的加密密钥对以及生成预签名证书:
这样,dnscrypt-wrapper 就已经准备好了。
使用命令来运行 dnscrypt-wrapper,用“-VV”来显示比较详细的 debug 信息:
其中的--provider-name=的值必须是以 2.dnscrypt-cert.开头。
然后在linux desktop os,安装客户端:
安装好后配置一下:
保存后使用如下命令重启客户端服务,如果你的端口没有被防火墙撸掉,那服务器那边就应该能够看到 debug 信息,表示已经有客户端接入。
使用命令来测试一下:
多次重复命令,发现获取到的 IP 均相同且为真正的正确 IP 地址,服务生效。

创建脚本

每次直接运行命令多少有些不方便,即使使用“-d”来后台执行,一样让人感到不适,我们使用 shell 来创建一个启动 dnscrypt-wrapper 的脚本。
以后则只需要使用 sh start-dnscrypt-wrapper.sh 就可以启动了。
——至于关闭嘛,使用命令“killall dnscrypt-wrapper”。
--------------

centos下编译dnscrypt-wrapper

dnscrypt可谓是防DNS污染的神器,是opendns官方的客户端工具,用于加密dns传输,有点类似http和https的区别。服务端和客户端都使用密钥进行传输,是所有抗DNS污染里面最强的手段了。然而国内的网络状况并不理想,很多时候连不上opendns(你懂的),或者我们搭建代理的时候想使用远程vps当地的dns解析结果来加速被wall网站的访问,这个时候想到能不能自己搭建一个dnscrypt的服务端呢?找了一圈,发现opendns官方并没有提供服务端源码╮(╯▽╰)╭……
不过在中国这个神奇的国度,总不缺乏大神,在v2ex上找到了@Cofyc 大神的自己写的dnscry-wrapper服务端,以下是原文:
写了一个 dnscrypt 的服务器端:dnscrypt-wrapper
https://github.com/Cofyc/dnscrypt-wrapper
dnscrypt 是 opendns.com 设计的给 dns 协议加密的协议,类似 https与 http 的关系。
opendns 有实现一个客户端代理 dnscrypt-proxy,但目前以我所知只有 opendns 的 dns 服务器上有实现 dnscrypt 协议。
dnscrypt-wrapper 是从 dnscrypt-proxy 修改而来,给任意 dns server 在服务端增加 dnscrypt 加密支持。
适合想使用 dnscrypt 但想自架 dns 服务器的情形。
我在自己服务器上有架设一个测试 dns,可以使用以下命令测试:
$ sudo ./dnscrypt-proxy -a 127.0.0.1:55 –provider-name=2.dnscrypt-cert.yechengfu.com -r 106.187.34.45:53 –provider-key=4298:5F65:C295:DFAE:2BFB:20AD:5C47:F565:78EB:2404:EF83:198C:85DB:68F1:3E33:E952
$ dig -p 55 google.com @127.0.0.1
参考:
– http://dnscrypt.org/
– dnscrypt-proxy https://github.com/opendns/dnscrypt-proxy
– http://www.opendns.com/technology/dnscrypt/
嗯,于是我兴冲冲地跑去下载编译了,过程中遇到不少问题,折腾了两小时,原作者也比较热心解决我的问题,现在我把编译过程(CentOS x86)分享下,希望对你有帮助:
更新软件源。
libsodium这个库centos可能没有……于是自己下载编译:
我选择的是当前最新的libsodium(下载可能会卡,毕竟服务器在国外):
解压好就进去编译安装:
至此libsodium安装完毕。
centos软件源上的libevent也不是最新的,而服务端要求2.0以上的版本,软件源提供的是1.4版本,因此导致编译出错。二话不说跑去官网下载源码编译:
下载地址:http://libevent.org/
我选择的是当前最新的稳定版本:
编译安装:
至此libevent安装完毕。

现在可以下载dnscrypt-wrapper源码来编译了:
如果执行./configure有出现错误,请根据错误信息找原因,基本上库完整的话没什么问题。有问题欢迎留言。./configure检查通过的话,我们就可以直接执行make命令来编译了。最后生成dnscrypt-wrapper可执行文件。
[root@centos dnscrypt-wrapper]# make install
install -d -m 755 ‘/usr/local/bin’
install -p dnscrypt-wrapper ‘/usr/local/bin’

dnscrypt-wrapper的使用方法

先来看看程序自带的Usage:
Usage: dnscrypt-wrapper [options]
-h, --help show this help message and exit
-v, --version show version info
-a, --listen-address=<str> local address to listen (default: 0.0.0.0:53)
-r, --resolver-address=<str> upstream dns resolver server (<address:port>)
-u, --user=<str> run as given user
-d, --daemonize run as daemon (default: off)
-p, --pidfile=<str> pid stored file
-U, --unauthenticated allow and forward unauthenticated queries (default: off)
-V, --verbose show verbose logs (specify more -VVV to increase verbosity)
-l, --logfile=<str> log file path (default: stdout)
--gen-provider-keypair generate provider key pair
--crypt-publickey-file=<str> crypt public key file
--crypt-secretkey-file=<str> crypt secret key file
--gen-crypt-keypair generate crypt key pair
--provider-publickey-file=<str> provider public key file
--provider-secretkey-file=<str> provider secret key file
--gen-cert-file generate pre-signed certificate
--cert-file-expire-days=<int> cert file expire days (default: 365)
--provider-name=<str> provider name
--provider-cert-file=<str> use this to self-serve cert file
(大神你为啥不写个中文版guide.红色的为运行必需项)
用法:dnscrypt-wrapper[选项]
-h,--help #显示此帮助信息并退出
-v,--version #显示版本信息
-a,--listen-address=XXX #本地地址侦听(默认值:0.0.0.0:53),提供DNS服务的端口
-r,--resolver-address=XXX #上游DNS解析服务器(<地址:端口>例如8.8.8.8:53)
-u,--user =XXX #用指定用户运行
-d,--daemonize #开启守护进程(默认关闭)
-p,--pidfile =XXX  #PID存储的文件
-U,--unauthenticated #允许和转发未经身份验证的查询(默认值:关闭)
-V,--verbose #显示详细日志(指定更多-vvv增加详细程度,例如-VV)
-l,--logfile = XXX #日志文件路径(默认:标准输出)
--gen-provider-keypair  #生成provider密钥对
--crypt-publickey-file=XXX #导入crypt公钥文件
--crypt-secretkey-file==XXX #导入crypt私钥文件
--gen-crypt-keypair #生成crypt密钥对
--gen-cert-file  #生成预签名证书
--cert-file-expire-days=XXX #证书文件有效天数(默认值:365)
--provider-publickey-file= XXX #r导入provide公钥文件
--provider-secretkey-file=XXX #导入provider私钥文件
--provider-name=XXX #dnscrypt证书服务域名。例如2.dnscrypt-cert.example.com
--provider-cert-file=XXX #使用自定义服务证书文件 如果2.dnscrypt-cert.yourdomain.com添加了证书二进制的TXT记录,则不必附带这个选项,程序会通过 provider-name 从 DNS 商那里获取证书文件。
首先,我们要生成provider-key:
注:这个就是Provider public key!dnscrypt客户端dnscrypt-proxy需要用这个provider-key,例如dnscrypt-proxy –provider-key=DA79:C……05:F5BC,请注意保存
然后生成crypt key:
Generate crypt key pair… ok.
Keys are stored in crypt_public.key & crypt_secret.key.
接着用上面的密钥对生成预签名证书:
这里注意,如果你要做域名的TXT记录的话(如果2.dnscrypt-cert.yourdomain.com添加了证书二进制的TXT记录,则启动dnscrypt-wrapper不必附带--provider-cert-file=XXX这个选项,程序会会通过 provider-name 从 DNS 商那里获取证书文件),把上面的
* Record for nsd:
2.dnscrypt-cert 86400 IN TXT “DNSC\000………………010”
内容复制下来做TXT解析:
2.dnscrypt-cert.yourdomain.com TXT  “DNSC\000………………010”
可以使用dig TXT 2.dnscrypt-cert.opendns.com这个命令查看opendns的TXT记录是这样的:
不过,一般情况下这个证书太长了,dns解析商一般不允许设置这么长的字符串……当然你也可以搭建本地dns服务器来储存这玩意……因为dnscrypt-wrapper有--provider-cert-file=XXX的命令,所以这步不是必须的。
经过上面的步骤应该生成了以下的文件:
[root@centos dnskey]# ls
crypt_public.key crypt_secret.key dnscrypt.cert public.key secret.key
然后用生成的证书启动程序:
解释下命令参数:-r 8.8.8.8:53是使用8.8.8.8:53作为dns的上游服务器,-a 0.0.0.0:5353是指定对外服务的端口,你可以随便定义只要不跟其他端口冲突例如121;-VV是显示调试信息,其他的都是必需参数,不解释了,可以看上面的命令翻译。
注意:2.dnscrypt-cert.xxx.com前面的2.dnscrypt-cert.是固定的,不能改成3.dnscrypt-cert.什么的
好了现在我们要来测试下是否搭建成功了正常运行了,原作者的readme是这样测试的:
简单解释下,就是在服务器本地运行dnscrypt客户端dnscrypt-proxy,指定127.0.0.1端口55,然后用dig命令(一个查询dns的命令,centos没有),指定本地的127.0.0.1服务器55端口去解析google.com的域名,解析成功就工作正常了。
但是这个对我来说麻烦死了……因为我得又来编译一次dnscrypt-proxy的客户端(本来打算编译的,下了代码然后说明不怎么详细,然后……然后折腾了半天懒得弄了),centos又没有dig命令,我还得编译一个dig……OMG……烦(懒)死了,而且测试完本地我还得测试远程实际好不好使,我们直接一步到位吧,用本地的windows客户端去测试远程的服务器,能用就是绝对好使的了!
首先我们要配置下防火墙,对外开放你定义的端口(例如上面我定义的是5353):
然后我们就可以下载windows客户端去测试了,由于dnscrypt的官网被墙,我这里直接提供现成的客户端给大家测试用吧,省得找了,想要自己找的话可以去dnscrypt.org上翻去。
我就是现成的客户端没错点我吧
打开客户端目录下的dnscrypt-resolvers.csv文件,仿照上面的数据格式添加一行:
NameFull nameDescriptionLocationCoordinatesURL
lingsanDNSlingsanDNSlingsanDNS不填不填不填
VersionDNSSEC validationNo logsNamecoinResolver address
1nonono你的ip:端口
Provider nameProvider public keyProvider public key TXT record
2.dnscrypt-cert.yourdomain.com上面生成的照填,我大字标红的那个不填
其实参照其他的随便填就是,关键参数是Provider public key和Resolver address。
然后你打开客户端就会看到新的dns选项了:
没错,点击启用,把网卡dns改成本地127.0.0.1就可以测试了。

解析结果正确:

这还不够,我们还要测试dns是否是从远程送过来的,这样才能达到代理加速的效果!怎么测试呢?告诉你,万能的淘宝在国外是有服务器的(剁手无国界),我们看看淘宝的解析结果如果是在国外就是达到理想效果了!
  
很好,终于成功了!!!
-d开启守护进程啊添加开机启动啊计划任务啊那些我就不罗嗦了,自己用心去体会吧
----------------

DNSCrypt-wrapper服务器搭建小记

想尝试一下加密DNS查询,于是折腾了DNSCrypt这个家伙。
首先摘录一段DNSCrypt官网上的介绍:
DNSCrypt is a protocol that authenticates communications between a DNS client and a DNS resolver. It prevents DNS spoofing. It uses cryptographic signatures to verify that responses originate from the chosen DNS resolver and haven’t been tampered with.
Implementations are available for most operating systems, including Linux, OSX, Android, iOS, BSD and Windows.
DNSCrypt is not affiliated with any company or organization, is a documented protocol using highly secure, non-NIST cryptography, and its reference implementations are open source and released under a very liberal license.
Please note that DNSCrypt is not a replacement for a VPN, as it only authenticates DNS traffic, and doesn’t prevent “DNS leaks”, or third-party DNS resolvers from logging your activity.
再丢几篇官方文档:
在此选用的客户端是Openwrt版dnscrypt-proxy,选用的服务端是dnscrypt-wrapper。

配置
“你真的以为我会写配置?” “蛤?不写?信不信我打死你!” “好,我写,我写。”

服务端
其实没什么好说的,官方文档已经说明了一切。

在按照官方文档安装及生成密钥之后(前面数步只要复制黏贴命令+按下回车就行了),启动dnscrypt-wrapper:

dnscrypt-wrapper --resolver-address=8.8.8.8 --listen-address=0.0.0.0:1053 \
                 --provider-name=2.dnscrypt-cert.example.com --crypt-secretkey-file=1.key \
                 --provider-cert-file=1.cert --daemonize

唔,稍稍解释一下,resolver-address项设置上游服务器,listen-address项设置dnscrypt-wrapper的工作端口,provider-name项就是给你的服务器设置一个帅气的名称(需要注意的是这个帅气的名称必须以2.dnscrypt-cert.开头,另外域名不存在也无所谓),后两项指定之前步骤中生成的密钥和证书,--daemonize(即-d)参数允许程序(作为守护进程)在后台运行。

如果并不能确定dnscrypt-proxy是否可以和dnscrypt-wrapper建立连接,可以在dnscrypt-wrapper启动命令中添加-VV参数并删去--daemonize参数,这样详细信息会被打印在屏幕上。此外可以使用--logfile=/path/file.log指定日志文件位置

当然以上信息只要运行dnscrypt-wrapper --help就可以得知了

客户端
其一
这里参照Openwrt的官方文档进行配置。

在安装完成之后(注意:请根据路由器的硬件平台和固件版本选择合适的安装方式)

vi /etc/config/dnscrypt-proxy

默认文件是以下这个样子:
config dnscrypt-proxy ns1
       option address          '127.0.0.1'
       option port             '5353'
       #option resolver        'cisco'
       #option resolvers_list  '/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv'
       # Ephemeral keys option requires extra CPU cycles and can cause huge sys
       # Disable it in case of performance problems.
       #option ephemeral_keys  '1'
   
#config dnscrypt-proxy ns2
#       option address          '127.0.0.1'
#       option port             '5454'
#       #option resolver        'd0wn-random-ns1'
#       #option resolvers_list  '/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv'
#       #option ephemeral_keys  '1'

唔,不去动它也能用,不过既然要使用私人服务器,自然要进行一定的修改。

vi /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv
在末尾参照样例形式输入:
e.g.DNS,ExampleDNS,this is just a config example,Mars,http://example.com,1,no,yes,no,your.vps.ip.address:port,2.dnscrypt-cert.example.com,XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX,^M

那一大堆X就是填写之前在服务端上生成的公钥。至于DNSSEC validation和Namecoin项,只能说请自行谷歌吧。

这样设定之后,/etc/config/dnscrypt-proxy就可以改成这个样子:

config dnscrypt-proxy ns1
       option address         '127.0.0.1'
       option port            '5353'
       option resolver        'e.g.DNS'
       option resolvers_list  '/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv'
       option ephemeral_keys  '1'

以后如果需要使用Public Key Client Authentication功能就可以简单运行如下命令:

dnscrypt-proxy --client-key=/file-path/client-secret.key -R e.g.DNS -a 127.0.0.1:local_port
当然这是后话了。最后,别忘了

/etc/init.d/dnscrypt-proxy start
/etc/init.d/dnscrypt-proxy enable


其二
其实上述配置方案可能已经过时,在此仍然予以保留。

上次更新服务器后,在客户端使用了另外一种配置方式,即无视dnscrypt-proxy安装后自带的配置文件,使用bash脚本控制dnscrypt-proxy。

在此先贴出主命令格式:
dnscrypt-proxy -a 127.0.0.1:local_port -r remote_address:remote_port\
    -N 2.dnscrypt-cert.example.com -k XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX\
    -d
详细的脚本将会在下一次更新本文(又是不知道猴年马月了)时贴出。

与Dnsmasq联合使用对DNS解析进行分流
同样可以在Openwrt的官方文档上找到所需的信息。

先是将Dnsmasq上游DNS设置为DNSCrypt。只需要在/etc/config/dhcp之中添加
list server        '127.0.0.1#5353'
option noresolv    1
这两行信息,并将option resolvfile行注释掉。

当然还有另外一种方法,就是直接修改/etc/resolv.conf,不过修改这个文件可不是简单的:wq就能解决的了,具体的其实在之前的文章中也提到过:
rm /etc/resolv.conf
echo "nameserver 127.0.0.1:5353">>/etc/resolv.conf
reboot

至于分流问题,则还是:
修改dnsmasq.conf,在末尾添加conf-dir=/etc/dnsmasq.d
mkdir /etc/dnsmasq.d
复制这个项目: https://github.com/felixonmars/dnsmasq-china-list 所提供的文件到/etc/dnsmasq.d下,并根据需要进行一定修改.
/etc/init.d/dnsmasq restart
结语
我觉得我应该说点什么。
唔,在配置完之后,可以使用dig命令进行检验和调试。
-----------------