114DNS在最近,实在是抽的不成样,TTL缓存的时间无比之长,导致我的DNS记录在dnspod上修改完(TTL 600)半小时后获取的dns记录依然没变化,此时 8.8.8.8 早已去拉取最新记录了,于是乎切换大名鼎鼎的 119.29.29.29 DNS(dnspod的,号称延迟最低,还支持google那个什么协议的),使用过一段时间之后就发现了另外一个问题:DNS污染。

其实这问题很久之前就知道了,只是之前在 fuck gfw 的时候是直接在pc建立npv通道的,所以dns的解析是走npv通道的,未出现问题,于是乎就懒得去处理污染这事了。最近直接在网关(Routeros)上配置路由规则到通道,但是在DNS上却出现了些问题,如果你设置主DNS服务器为国内的DNS运营商呢,各种被 gfw block 的站点就无法访问,因为DNS污染,而如果换8.8.8.8,延迟至少100+不说,偶尔还可能因为gfw抽抽风被block,于是乎花了一个晚上自建了个DNS递归服务器,完美解决问题,而且由于服务器跟博主是一个地区的,所以延迟甚至比dnspod还低,4ms~~~~

此文的大部分配置内容由 phoenixlzx 博文(本文底部有引用链接)提供,只是他那边不知道是使用什么环境安装的啥的,我这边把各种环境的安装也给出,还有是遇到一些问题这边也做了些说明。

2017-11-01:牛逼了,GFW真的对HTTPS通道进行脑残式的ban了,从那个什么会开始,直到今天,我自己才能正常打开本blog,至于境外HTTPS被ban的同学想搞dns服务的,你们就自己看着办了,自己写自定义协议还是啥的。
请注意GFW对境外IP提供的53端口dns服务有匹配拦截规则,实测深圳电信,在香港阿里云HK机器下使用53端口提供DNS服务,对 www.google.com.hk 或其他被ban的站点的DNS查询结果会被GFW投毒直接return回来,导致查询结果不正确,如换成非53端口则一切正常,不过如果使用非53端口提供服务,那么客户端就要纠结了,dns服务使用53端口,而路由器或者其他终端设备的操作系统都遵循这个约定,所以一般不会提供给你自定义DNS端口的设置,于是乎你就得在本地使用一些dns客户端了,本文提及的dnscrypt实际就是一个dns客户端,跨平台的,其他版本有需要的话可以去官网下载。

准备工作

需要的程序:

  1. unbound
  2. dnscrypt-proxy
  3. gcc make
  4. git
  5. libsodium
  6. dnsmasq-china-list

对以上组件做一些说明,gcc make git就不用说了吧,玩linux的都懂。

libsodium是一个加密库,dnscrypt-proxy组件待会会用到这个东西。

dnscrypt-proxy看名字就知道是啥了,它是一个dns加密代理程序,我们要正确获取各种被ban的站点的dns记录就靠这货了,他可以与国外上游dns服务器建立加密通道进行dns记录迭代查询,gfw表示对此无能为力(不排除以后gfw直接ban掉加密的dns通道,那就gg了)。

接着就是主角unbound,一个挺老牌的dns服务器软件了吧,dns解析和各种规则全靠它了。

libsodium安装

我用的是Centos7 x64,gcc make git你们就自己安装了,yum一句指令就完了。先安装libsodium,点此下载源码包。

cd /usr/local/src
wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.9.tar.gz
tar -zxvf libsodium-1.0.9.tar.gz
cd libsodium-1.0.9
./configure
make && make install

安装完成之后执行以下指令刷新链接库(许多教程就缺少以下这句,导致待会安装dnscrypt-proxy的时候依赖检测不通过)

echo /usr/local/lib > /etc/ld.so.conf.d/usr_local_lib.conf

然后执行

ldconfig

如果没执行以上指令,待会将会遇到以下错误:

configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details
configure: error: ./configure failed for src/libevent-modified

dnscrypt-proxy安装与启动

点此下载源码包,注意bz2的才是源码包。
执行以下解压配置编译安装指令:

wget https://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-proxy-1.7.0.tar.bz2
bunzip2 -cd dnscrypt-proxy-*.tar.bz2 | tar xvf -
cd dnscrypt-proxy-*
./configure && make
make install

如果没指定安装路径,dnscrypt-proxy执行文件路径默认在/usr/local/sbin/dnscrypt-proxy。

安装完成如果不看文档直接启动,先丢给你个错误再说:

[root@iZ94ufdvy1jZ ~]# /usr/local/sbin/dnscrypt-proxy 
[ERROR] Resolver information required.
[ERROR] The easiest way to do so is to provide a resolver name.
[ERROR] Example: dnscrypt-proxy -R mydnsprovider
[ERROR] See the file [/usr/local/share/dnscrypt-proxy/dnscrypt-resolvers.csv] for a list of compatible public resolvers
[ERROR] The name is the first column in this table.
[ERROR] Alternatively, an IP address, a provider name and a provider key can be supplied.
[ERROR] Please consult https://dnscrypt.org and the dnscrypt-proxy(8) man page for details.

可以看到他提示我们缺少解析器信息,我们打开提示指示的文件:
QQ截图20160828233328
其实看一下大概就可以猜到了,这个文件里面预定义了许多上游DNS服务器,可以供dnscrypt-proxy迭代查询,这个文件里的每一行的第一个列的内容就是解析器的名字,选择一个待会启动的时候需要填入。

接下来我们用以下参数启动:

dnscrypt-proxy --resolver-name=cisco --local-address=127.0.0.1:5353 --logfile=/dnscrypt.log --daemonize --ephemeral-keys --tcp-only

解释一下各参数:

  1. resolver-name,这个应该不用说了吧,我这里用了思科的dns。
  2. local-address 提供服务的网卡IP和端口,我们这里设置本地地址并将端口改为5353,其实我们这是在为待会的unbound让道,因为待会unbound会使用53端口对外提供服务,所以这里使用其他端口给unbound提供迭代查询功能。
  3. logfile 日志路径。
  4. daemonize 后台执行。
  5. ephemeral-keys 启用混淆。(近期GFW越来越强悍了 建议开启)
  6. tcp-only。顾名思义

查看完整的参数列表:

dnscrypt-proxy -h

各参数的说明可以在github主页上查看,或者在源码包README里看。

生成dnsmasq-china-list加速国内域名解析

其实如果我们直接将unbound的上游迭代服务器设置为我们刚刚在dnscrypt-proxy绑定的地址,那么就跟直接设置 8.8.8.8 没多大区别了,因为cisco的服务器在国外,延迟也很高,如果全部的解析无论国内国外还是被block的都走cisco的话那速度简直了,所以我们需要把国内的域名交由国内的dns运营商来解析,而dnsmasq-china-list就是这样的一份国内域名列表。

用git clone这个仓库到本地,然后修改 Makefile 文件里面的第一行 SERVER=119.29.29.29,改为你觉得最合适的国内缓存 DNS 服务器,这里我用了dnspod的。

执行 make unbound,然后在克隆的仓库根目录下会生成一份unbound的配置(accelerated-domains.china.unbound.conf),copy到合适的路径下待用,这里我直接丢到unbound的配置目录 /etc/unbound/

unbound安装配置

接下来就是主角了,unbound,还好,在centos下可以直接使用 yum 安装,节省不少时间:

yum -y install unbound

修改文件 /etc/unbound/unbound.conf。没有这个文件的话(咱这里用yum安装的,肯定有这个配置文件),一般需要找一下软件包里提供的配置 example 文件复制过去。这里列出的仅包含需要修改的部分,其他的按照默认配置一般没有问题。

num-threads: 2 # 线程数可以修改为物理核心数
interface: 0.0.0.0 # 侦听所有 IPv4 地址
interface: ::0 # 侦听所有 IPv6 地址
# 如果只需要本机使用,则一个 interface: 127.0.0.1 即可
so-rcvbuf: 4m
so-sndbuf: 4m # 本机使用的话,这俩 buf 可以取消注释
so-reuseport: yes # 如果开了多线程,就写 yes
msg-cache-size: 64m # 本机可以设置 4m 或者更小
rrset-cache-size: 128m # 本机可以设置 4m 或者更小
cache-max-ttl: 3600 # 建议设置一个不太大的值...专治各种运营商 DNS 缓存不服
outgoing-num-tcp: 256 # 限制每个线程向上级查询的 TCP 并发数
incoming-num-tcp: 1024 # 限制每个线程接受查询的 TCP 并发数
# 下面这四个不需要解释了吧,不想用那个就写 no
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
tcp-upstream: no # 默认是 no,隧道状态比较稳的话也不需要写 yes。一些情况下强制使用 tcp 连上游的话写 yes
access-control: 0.0.0.0/0 allow # 本机用的话建议设置 127.0.0.0/8 allow,局域网用适当调整
root-hints: "/etc/unbound/root.hints" # 没有的话在 ftp://FTP.INTERNIC.NET/domain/named.cache 下载一份
hide-identity: yes # 不返回对 id.server 和 hostname.bind 的查询。
hide-version: yes # 不返回对 version.server 和 version.bind 的查询。
# 不过下面有 identity 和 version 的自定义选项,不隐藏这些的话,修改下选项还可以卖个萌(´・ω・`)
harden-glue: yes # 建议打开
module-config: "iterator" # 禁用 DNSSEC 检查,如果上游不支持 DNSSEC 就关掉。注意这个选项有可能在其他 include 的文件里
unwanted-reply-threshold: 10000000 # 针对各种网络不服,数值为建议值,具体可以自己修改看看效果
do-not-query-localhost: no # 一般是为了防止扯皮丢包开着,不过等下要用 DNSCrypt 所以关掉
prefetch: yes # 蛮好用的,开着吧
minimal-responses: yes # 省带宽,开着吧。本机用可以关掉
# 关键部分来了,把默认查询全部丢给 DNSCrypt。使用 [地址]@[端口] 指定查询地址和端口,默认端口 53。
# 然后把国内的地址丢给国内的缓存服务器。这两个选项的顺序不能错哟。
# 如果使用隧道查询,把这个地址改为隧道对端的地址,或者一个国外的 DNS 服务器都可以,例如 8.8.8.8。
# 具体看是在对端开 DNS 还是直接用国外的服务器。后者的话,前面 outgoing-interface 可以直接设置隧道本地端的地址,不过要配合 dnsmasq-china-list 的话,还是写路由表比较合适,否则不够灵活。
include: "/etc/unbound/accelerated-domains.china.unbound.conf"
forward-zone:
    name: "."
    forward-addr: 127.0.0.1@5353

然后直接 unbound 启动即可,unbound自己会在后台运行。

如果你要使用unbound的远程控制功能,那你配置中的 remote-control 项需要开启(默认似乎是开启的),还需要执行以下指令安装远程功能,其实感觉这指令只是给你在unbound的配置目录生成了自签SSL证书而已。

unbound-control-setup

完成之后就可以使用 unbound-control 指令来对dns服务器执行各种操作了,比如你可以查看服务器状态,你可以刷新某一条dns记录,你可以直接参考官方文档获取各个参数作用,或者直接 -h

openssl生成证书签名请求(CSR)

本文介绍了如何在Linux上使用openssl生成证书签名请求和证书私钥 输入以下指令生成一个加密的私钥文件,指令中的2048为加密位数。你会被要求为该私钥设置一...

阅读全文

linux上编译curl出现 undefined reference to ‘SSL_CTX_set_alpn_protos’

linux上编译curl出现 undefined reference to `SSL_CTX_set_alpn_protos' 或 undefined reference to `SSL_get0_alpn_selected' 解决方案。 最近编译Apache...

阅读全文

Apache配置SSL并反向代理Tomcat

记录记录,Apache配置SSL并反向代理Tomcat,本文不包含环境编译配置,如有需求请参考本博其他文章 环境搭建参考 Apache:https://stacktrace.tech/2015-12-0...

阅读全文

23 条评论

  1. [1483781232] unbound[22749:0] error: can’t bind socket: Cannot assign requested address
    [1483781232] unbound[22749:0] debug: failed address ::1 port 8953
    [1483781232] unbound[22749:0] error: cannot open control interface ::1 8953
    [1483781232] unbound[22749:0] fatal error: could not open ports
    博主这是什么鬼 8953打开了

    1. 没看见完整日志也不好判断,猜测是unbound在连接dnscrypt服务的时候输出的错误日志? 8953是你dnscrypt的端口吗,是不是dnscrypt没启动或者监听的端口错了

      1. 是remote control的锅,8953是remote的端口,我把remote control改成no,执行unbound没有任何输出,lsof 53没有输出,DNS也无法使用,您能贴一份完整的conf吗?

        1. 成功启动是否有输出success之类的log,这个真忘了,一个月前启动的了,手动ps看一下unbound进程在不在吧。完整的config太长了不贴出了,我的config就和上面贴出的一样,除了 root-hintsinclude 的文件名使用自己实际文件名之外,上面的config没列出的项采用config文件里面的默认值。我觉得你重点留意一下dnscrypt的监听端口还有对外的端口防火墙配置,unbound起来之后将主机的dns设置为本地,然后dig看一下是否解析成功,如果本地解析成功那就是对外防火墙配置问题了。

          1. 需要吧example conf的注释全部去掉吗?root-hints的名字是name-cache

            1. 肯定不用呀,全去掉肯定起不来,采取默认的配置项加上上述列出的配置

  2. 很好,可以解决问题,但我发现make unbound生成的列表,每个域名后面都有一个“.”
    例如
    forward-zone:
    name: “taobao.com.”
    unbound的manpage是并没有加“.”的,这个是bug还是必需要加上的?

  3. 你好,按你的办法在安装过程libsodium中报错
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    CC crypto_onetimeauth/poly1305/sse2/libsse2_la-poly1305_sse2.lo
    CC crypto_pwhash/scryptsalsa208sha256/sse/libsse2_la-pwhash_scryptsalsa208sha256_sse.lo
    CCLD libsse2.la
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    CC crypto_generichash/blake2b/ref/libssse3_la-blake2b-compress-ssse3.lo
    CC crypto_pwhash/argon2/libssse3_la-argon2-fill-block-ssse3.lo
    CC crypto_stream/chacha20/dolbeau/libssse3_la-chacha20_dolbeau-ssse3.lo
    CCLD libssse3.la
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    CC crypto_generichash/blake2b/ref/libsse41_la-blake2b-compress-sse41.lo
    CCLD libsse41.la
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    CC crypto_generichash/blake2b/ref/libavx2_la-blake2b-compress-avx2.lo
    CC crypto_pwhash/argon2/libavx2_la-argon2-fill-block-avx2.lo
    CC crypto_stream/chacha20/dolbeau/libavx2_la-chacha20_dolbeau-avx2.lo
    CC crypto_stream/salsa20/xmm6int/libavx2_la-salsa20_xmm6int-avx2.lo
    CCLD libavx2.la
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    CC crypto_pwhash/argon2/libavx512f_la-argon2-fill-block-avx512f.lo
    CCLD libavx512f.la
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    CCLD libsodium.la

    请问是什么原因!!!本人小白一个!如果可以。请加我QQ:16523772指导一下我。谢谢!

  4. 你好,按你的办法在安装过程dnscrypt-proxy中报错
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    libtool: warning: ‘-release’ is ignored for convenience libraries
    CCLD libevent_core.la
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    libtool: warning: ‘-release’ is ignored for convenience libraries
    CCLD libevent_extra.la
    libtool: warning: ‘-version-info/-version-number’ is ignored for convenience libraries
    libtool: warning: ‘-release’ is ignored for convenience libraries

    pid_file.c: 在函数‘pid_file_write’中:
    pid_file.c:103:9: 警告:忽略声明有 warn_unused_result 属性的‘ftruncate’的返回值 [-Wunused-result]
    (void) ftruncate(fd, (off_t) 0);
    ^
    请问是什么原因!!!本人小白一个!如果可以。请加我QQ:16523772指导一下我。谢谢!

      1. 感谢回复!!!这前些天有点忙。暂时放了放,这个星期加完班。重新弄!!!以后有问题再联系你!

  5. 你好!安装好unbound之后。配置文件。测试运行。提示

    [root@dns ~]# unbound-checkconf
    /etc/unbound/unbound_server.key: No such file or directory
    [1509945291] unbound-checkconf[31175:0] fatal error: server-key-file: “/etc/unbound/unbound_server.key” does not exist

    配置文件默认相关项目为
    # unbound server key file.
    server-key-file: “/etc/unbound/unbound_server.key”

    # unbound server certificate file.
    server-cert-file: “/etc/unbound/unbound_server.pem”

    # unbound-control key file.
    control-key-file: “/etc/unbound/unbound_control.key”

    # unbound-control certificate file.
    control-cert-file: “/etc/unbound/unbound_control.pem”

    查看相关文件夹下发现没有这四个文件!我百度找不到相关资料!没办法!
    请问我需要如何解决!!!!

      1. 感谢回复。当时已经发现。
        现在出现新的问题
        运行 unbound-checkconf
        unbound-checkconf: no errors in /etc/unbound/unbound.conf
        这应该是配置文件没有错误!
        运行 unbound
        Nov 07 16:55:45 unbound[5245:0] error: bind: address already in use
        Nov 07 16:55:45 unbound[5245:0] fatal error: could not open ports

        第一个错误是地址已经在使用!?
        第二个错误是未能打开端口!~?
        我已经打过关闭防火墙的命令了
        systemctl stop firewalld
        还是会出错!~
        运行 unbound-control stop
        [1510045180] unbound-control[5370:0] debug: address 127.0.0.1 port 8953
        [1510045180] unbound-control[5370:0] error: connect: Connection refused
        这两个错误我需要在什么地方相应改正!?

  6. 博主,你好。运行错误的问题我已经解决。原来是dnsmasq默认在后台。暂用了53端口。我把相应的进程kill掉就可以了
    现在又出现问题
    forward-zone:
    name: “.”
    forward-addr: 119.29.29.29
    解释超时

    forward-zone:
    name: “example.com”
    forward-addr: 119.29.29.29
    或#注释掉时,解释。正常!!
    按文档说明。应该是用 name: “.”才正确。问题是这样写。超时了!请问是何种原因!?
    感谢!!!

    1. 😐 不好意思哇了,看到你的回复通知邮件了,但是我博客在公司线路被墙了(真是耻辱……),这段时间上不来就懒得去处理了。

      使用“.” 才是对的没错,表示根域,转发所有dns请求到119.29.29.29去解析,至于超时,log是如何显示的,请贴log。如果确实超时,你直接在你的服务器上dig一下,并指定dns服务器为119.29.29.29 以确认119.29.29.29提供的服务在你的机器上是可用的

欢迎留言