简介

有时候方案一些网站的时候,会由于 DNS 解析出问题,即使网络情况很好,也会出现无法访问的情况, 而最近很流行的 DNS over HTTPS 更是十分的稳定安全,所以,通过自建 DNS,可以精确的得到解析结果。

文章中的所有文件可以直接在我的仓库中找到:

Archlinux dot file

方案

dnsmasq

dnsmasq 是一个十分老牌的软件了,可以提供 DNS 缓存和 DHCP 服务功能,还带了一个 PXE 服务器,但是这些都不是我们需要关注的点,我们只看 DNS

作为域名解析服务器 DNSdnsmasq 可以通过缓存 DNS 请求来提高对访问过的网址的连接速度,所以有一些结果虽然第一次比较耗时,但是后续就可以直接用本地结果了。

最重要的是 dnsmasq 轻量而且容易配置,几乎默认的配置就足够我们使用了。

DNS over HTTPS

DNS over HTTPS 也就是常见的 DoH

没什么问题是加一层解决不了的,如果有,那个加两层。

DNS 经常出问题,那就把 UDP 换成 TCP ,还解决不了?那就再上一层 TLS

由于 HTTP 协议需要多次数据交互,还有 TLS 的加解密,所以在时间上,耗时比传统的 DNS 高了不少。 上文也提到了 dnsmasq 有缓存作用,所以也一定程度缓解了这个问题。

Cloudflare 1.1.1.1

Cloudflare 本来是一个主打 CDN权威 DNS 的企业,在 2018 年的时候强势推出了 1.1.1.1local DNS , 还带着 DNS over HTTPS 支持。 目前比较有名的 DoH 服务就只有 CloudflareGoogle ,而这是 Cloudflare 的主战场,自然也就是一个优选。

  • Cloudflare DoH Client

    Cloudflare 还提供了一个 Golang 开发的 DoH 客户端,可以直接在本地把 DoH 转为传统 DNS

    得益于 Golang 开发,所以所有需要下载的内容就是一个二进制文件: cloudflared 。当然如果对应 Linux 发行版 ,想安装 deb 或者 rpm ,官网也是有的。

    运行方式也只需要如下命令即可:

    cloudflared proxy-dns --address 0.0.0.0 --port 5353
    

    dnsmasq china list

    上文提到了, DoH 相对比较耗时,而 DNS 的问题更多地出现在国外的域名上,所以国内的域名,我们其实直接用传统方案就可以了, dnsmasq china list 就是一个国内的域名列表,而最方便的地方在于可以直接生成 dnsmasq 的配置文件。

    安装

    考虑到这是一个服务,需要长期运行,所以我们使用 systemd 来运行。

    配置文件如下,考虑到文章不一定能及时更新,可以看我的 dot file repo

    Cloudflare

    [Unit]
    Description=cloudflare DoH
    Documentation=cloudflare DNS over HTTPS
    
    [Service]
    Type=simple
    ExecStart=/home/username/.bin/cloudflared proxy-dns --address 0.0.0.0 --port 5353
    ExecStop=kill $MAINPID
    Restart=always
    
    [Install]
    WantedBy=default.target
    

dnsmasq

dnsmasq 直接使用自已安装的时候带的 systemd 配置文件就足够了,主要是改一下 dnsmasq配置文件/etc/dnsmasq.conf

no-hosts
no-resolv

server=127.0.0.1#5353
conf-dir=/etc/dnsmasq.d/

log-queries
log-facility=/var/log/dnsmasq/dnsmasq.log

然后安装 dnsmasq-china-list ,简单地来说,运行一个脚本就可以:

wget https://raw.githubusercontent.com/zwpaper/dotfile/master/archlinux/config/dnsmasq/install.sh
sudo bash install.sh

效果

到此,安装就完成了,目前的效果

国内域名:

# dig @127.0.0.1 163.com

; <<>> DiG 9.14.3 <<>> @127.0.0.1 163.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3825
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;163.com.                       IN      A

;; ANSWER SECTION:
163.com.                98      IN      A       123.58.180.7
163.com.                98      IN      A       123.58.180.8

;; Query time: 44 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Jun 30 17:19:54 HKT 2019
;; MSG SIZE  rcvd: 68

查看日志:

Jun 30 17:19:54 dnsmasq[20723]: query[A] 163.com from 127.0.0.1
Jun 30 17:19:54 dnsmasq[20723]: forwarded 163.com to 180.76.76.76
Jun 30 17:19:54 dnsmasq[20723]: forwarded 163.com to 114.114.115.115
Jun 30 17:19:54 dnsmasq[20723]: forwarded 163.com to 114.114.114.114
Jun 30 17:19:54 dnsmasq[20723]: reply 163.com is 123.58.180.7
Jun 30 17:19:54 dnsmasq[20723]: reply 163.com is 123.58.180.8

可以看到 dnsmasq 转发了三个请求到国内的 local dns 了。

国外的请求

# dig @127.0.0.1 google.com

; <<>> DiG 9.14.3 <<>> @127.0.0.1 google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36565
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
; PAD (69 bytes)
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             272     IN      A       216.58.217.206

;; Query time: 251 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Jun 30 17:30:37 HKT 2019
;; MSG SIZE  rcvd: 138

看日志,转发到 127.0.0.1 了,因为我们的 cloudflared 是运行在本地的。

Jun 30 17:30:36 dnsmasq[20723]: query[A] google.com from 127.0.0.1
Jun 30 17:30:36 dnsmasq[20723]: forwarded google.com to 127.0.0.1
Jun 30 17:30:37 dnsmasq[20723]: reply google.com is 216.58.217.206

Cache

再发起一次请求,看日志,直接从 cache 返回了:

Jun 30 17:31:31 dnsmasq[20723]: query[A] google.com from 127.0.0.1
Jun 30 17:31:31 dnsmasq[20723]: cached google.com is 216.58.217.206