加密DNS

在这片神奇的土地上,上个网并不是件容易的事情,因为会遇到以下问题

  • DNS 污染,比如您请求某些站点,返回给你的IP是被污染的 IP 而非站点的真实 IP
  • DNS 劫持,比如请求谷歌,返回给你的却不是谷歌的 IP

这个问题是谁做的,我们不需要知道,或者知道了但是也不能奈何他,面对强权,我们个人的力量实在是太渺小了。当然还有其他的,比如钓鱼网站啊,垃圾弹窗啊,各种广告啊这种都会影响到我们的访问。

但是,我们有拒绝这种行为的方法。在正式讲解之前,我们先看下传统的DNS是怎么去获取网站的IP 地址的

早上互联网初期,网站是很少的,那个时候基本上把IP对应的域名写到 HOSTS文件就可以搞定了

但是,随着联网设备越来越多,这种做法显得很不合理,因此就有了 DNS。

什么是 DNS

DNS 是目前互联网的一项服基础服务,他用来将域名和 IP地址相互映射的一个分布式数据库,可以把他想象成一个巨大的电话本,对应这手机号和姓名;他使用的是TCP和UDP的53端口,但是基本上都是使用UDP 因为TCP要建立三次握手,查询会非常慢,不过随着最近几年的DNS 污染 劫持越来越严重,很多DNS都利用其他端口了比如OPENDNS使用5353或其他端口。

DNS是怎么工作的呢?我们看下下图

我们使用dig这个命令来看下可以给我们列出来a-m这么些个根服务器

➜  www dig

; <<>> DiG 9.8.3-P1 <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55650
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;.                IN    NS

;; ANSWER SECTION:
.            518400    IN    NS    a.root-servers.net.
.            518400    IN    NS    b.root-servers.net.
.            518400    IN    NS    c.root-servers.net.
.            518400    IN    NS    d.root-servers.net.
.            518400    IN    NS    e.root-servers.net.
.            518400    IN    NS    f.root-servers.net.
.            518400    IN    NS    g.root-servers.net.
.            518400    IN    NS    h.root-servers.net.
.            518400    IN    NS    i.root-servers.net.
.            518400    IN    NS    j.root-servers.net.
.            518400    IN    NS    k.root-servers.net.
.            518400    IN    NS    l.root-servers.net.
.            518400    IN    NS    m.root-servers.net.

;; Query time: 126 msec
;; SERVER: 127.0.0.54#53(127.0.0.54)
;; WHEN: Mon Aug 28 14:03:05 2017
;; MSG SIZE  rcvd: 239

比如我们要查询 awen.me 从本地解析到 IP 地址这个过程都是怎么样查到的,我们可以通过 dig awen.me +trace 去查看,先找到根服务器,然后找到根下面的.me服务器 然后找到 dnspod 的 ns 服务器然后找到绑定的 A 记录地址。

➜  ~ dig awen.me +trace

; <<>> DiG 9.8.3-P1 <<>> awen.me +trace
;; global options: +cmd
.            82701    IN    NS    e.root-servers.net.
.            82701    IN    NS    a.root-servers.net.
.            82701    IN    NS    d.root-servers.net.
.            82701    IN    NS    k.root-servers.net.
.            82701    IN    NS    i.root-servers.net.
.            82701    IN    NS    j.root-servers.net.
.            82701    IN    NS    b.root-servers.net.
.            82701    IN    NS    m.root-servers.net.
.            82701    IN    NS    f.root-servers.net.
.            82701    IN    NS    h.root-servers.net.
.            82701    IN    NS    g.root-servers.net.
.            82701    IN    NS    l.root-servers.net.
.            82701    IN    NS    c.root-servers.net.
;; Received 239 bytes from 127.0.0.1#53(127.0.0.1) in 5800 ms

me.            172800    IN    NS    b0.nic.me.
me.            172800    IN    NS    a0.nic.me.
me.            172800    IN    NS    c0.nic.me.
me.            172800    IN    NS    b2.nic.me.
me.            172800    IN    NS    a2.nic.me.
;; Received 334 bytes from 192.33.4.12#53(192.33.4.12) in 2155 ms

awen.me.        86400    IN    NS    f1g1ns1.dnspod.net.
awen.me.        86400    IN    NS    f1g1ns2.dnspod.net.
;; Received 79 bytes from 199.249.119.1#53(199.249.119.1) in 588 ms

awen.me.        600    IN    A    35.194.252.98
awen.me.        86400    IN    NS    f1g1ns1.dnspod.net.
awen.me.        86400    IN    NS    f1g1ns2.dnspod.net.
;; Received 105 bytes from 101.226.220.16#53(101.226.220.16) in 8 ms

关于DNS的原理,更具体的可以参考这篇文章http://www.ruanyifeng.com/blog/2016/06/dns.html

DNS 为什么会被劫持

因为 DNS 是明文传输的,当你访问一个网站,查询到的 IP 地址,有些人或黑客都是可以看到的。因此他可以在传输中就把你的内容给替换了。所以返回给你的不一定就是正确的 IP 了。

加密查询

我们可以通过 dnscrypt 来加密查询内容https://dnscrypt.org/

以mac为例,下载后安装完毕(需要重启一次),然后启动,勾选开启和关闭ipv6选项

当出现一个加锁的图标,就表示开启成功了

然后我们 dig 一个域名看看结果会发现查询的DNS是127.0.0.54的53端口

自己搭建本地的dns服务器加密查询

brew cask reinstall dnscrypt
brew install dnscrypt-proxy
brew install dnsmasq

配置 dnsmasq

1.拷贝配置文件

sudo cp  /usr/local/etc/dnsmasq.conf.default  /usr/local/etc/dnsmasq.conf

配置参考https://awen.me/post/9868.html

然后在 /usr/local/etc/ 创建一个文件 resolv.dnsmasq.conf

➜  etc git:(master) ✗ cat resolv.dnsmasq.conf
nameserver 119.29.29.29
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 42.120.21.30
nameserver 168.95.1.1
nameserver 115.231.100.106

2.解析都在dnsmasq.d目录下

## 配置 dnscrypt-proxy

配置文件在 /usr/local/etc/dnscrypt-proxy.conf ,修改 LocalAddress 的值,注意不要为53以外的其他端口,因为53端口要给 dnsmasq 用

LocalAddress 127.0.0.1:40

然后测试

dig awen.me -p 40 @127.0.0.1

; <<>> DiG 9.8.3-P1 <<>> awen.me -p 40 @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51383
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1252
;; QUESTION SECTION:
;awen.me.            IN    A

;; ANSWER SECTION:
awen.me.        15    IN    A    35.194.252.98

;; Query time: 719 msec
;; SERVER: 127.0.0.1#40(127.0.0.1)
;; WHEN: Tue Aug 29 19:59:31 2017
;; MSG SIZE  rcvd: 52

抓包分析下,可以看到本地和服务器的 443 端口通信

然后我们修改dnsmasq的配置,添加 server=127.0.0.1#40

cat dnsmasq.conf| grep ^server
server=127.0.0.1#40

最后,修改本机 DNS 为 127.0.0.1 ,搞定。

国内域名不加密

git clone https://github.com/felixonmars/dnsmasq-china-list.git 

将里面的配置文件全部复制到dnsmasq.d去 重启

sudo brew services restart dnsmasq

sudo brew services restart dnscrypt-proxy