2016年3月14日星期一

在 OS X 上 避免 DNS 泄露

什么是DNS泄露
最近墙越来越高了,随着法西斯节和月饼的关系,不少梯子也被拆了。甚至几个梯子开发者也被🍵,所以说,除了“如何科学上网”这个问题之外,“如何安全上网”这个问题也变得越来越不可让人忽略。

不仅仅是为了你我都懂的用途,就是一般的使用电脑上网,我觉得这个问题也应当得到重视。你在网络上面的一言一行都被你的服务商、ISP事无巨细地记录着……这原本是好的目的——一旦歹徒在通过网络行凶,我们就能够快速将其抓获——不过,一旦这些信息落入了坏人之手,那将不堪设想。

一般我们会想,那些浏览记录什么的有什么重要的呢?只要我的账号密码安全就好了啊!事实上,正是这些信息,给了黑客可乘之机。你的这些材料,都将成为社会工程学的攻击素材。

那么DNS泄露又是什么呢?

使用浏览器上网,你输入的域名就要依靠DNS来翻译成IP地址——电脑可不懂什么是域名。所以,也许你访问的内容经过了https加密,但ISP一样可以记录你究竟访问了那些网站!

就算你使用了VPN等代理来访问网络,你的DNS仍然有可能是本地解析的,这将导致你的隐匿行踪变得毫无意义!——这就是个人隐私的头号威胁:DNS泄露。

目前来讲,当你使用VPN的时候,DNS应该是远程解析的,但有些提供商并不支持它;另外如果你使用socks代理,那么只有 5 才支持远程DNS解析

另外

你如果使用了pac,那你需要一份按照域名来选择代理的 pac 而不是IP。——因为它还是会先解析出IP再判断是否需要代理。
否则,你就可能泄露了DNS:

什么是DNS泄露
什么是DNS泄露
DNS透明转发

这时候就有人提出,如果使用VPN,为了避免DNS污染(其实也是泄露的一种),要使用第三方的公共DNS服务,比如谷歌的 8.8.8.8 ,但如果你的DNS泄露了,即使使用了公共DNS也无济于事:

DNS透明转发
DNS透明转发
你以为你访问到了第三方的公共DNS上,其实你还是访问了ISP的DNS服务器上。

关于DNS泄露的更多内容访问:https://dnsleaktest.com/what-is-a-dns-leak.html

要测试DNS泄露,访问:https://dnsleaktest.com
使用 dnscrypt 和 dnsmasq

dnscrypt 是 Open DNS 的一个项目,它允许你加密地访问DNS服务器,并解析域名。就好像使用https访问网站一样。而 dnsmasq 则是一个轻量级的DNS服务器,我们本地架设它来缓存DNS解析回复,这样就不用在同一时间里重复解析同一域名多次了——毕竟加密DNS解析不比明文解析快的。

注意

其实大多数 Linux 系统当中 dnsmasq 都是默认自带的——它并不臃肿,也不会耗费多少资源。
准备

为了安装 dnscrypt 和 dnsmasq ,你需要安装 Xcode ——我们需要用到Xcode 附带的一些命令行工具。

在安装了Xcode之后,使用命令来安装Homebrew:

1
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
它是个类似 apt-get 或者 yum 的包管理器,安装它之后,你或许需要如下设置:

brew update 慢 解决办法 镜像更新源

安装 dnsmasq

使用 brew install dnsmasq 来安装它。

我们编辑它的配置:

1
2
3
mkdir -p /usr/local/etc
cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf
vim /usr/local/etc/dnsmasq.conf
比如说如下配置:

1
2
3
4
5
6
7
8
# Never forward plain names
domain-needed

# Never forward addresses in the non-routed address spaces
bogus-priv

# Forward queries to dnscrypt on localhost
server=127.0.0.1#5355
再写入一条额外的配置: echo "conf-dir=/usr/local/etc/dnsmasq.d" >> /usr/local/etc/dnsmasq.conf 来让配置目录生效以放入更多规则:

1
2
3
4
5
6
7
mkdir /usr/local/etc/dnsmasq.d
//创建配置目录

wget -4 --no-check-certificate -O /usr/local/etc/dnsmasq.d/accelerated-domains.china.conf https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/accelerated-domains.china.conf
//为国内常用网站取消DNS加密
对于国内比如淘宝京东这类网站,我想你不会去代理,那么也就没必要加密处理了,由于国内多用了cdn加速,我们有国外DNS解析的话会导致走到国外线路上,速度很慢。如果你需要加密,就跳过这一步即可👌。
设置启动:

1
2
3
sudo cp -fv /usr/local/opt/dnsmasq/*.plist /Library/LaunchDaemons
sudo chown root /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
使用 sudo lsof -ni UDP:53 或者 ps -ef | grep '[d]nsmasq' 来验证dnsmasq已经启动。

dnsmasq 虽然被用作了DNS缓存,它一般也会用在微型服务器上比如OpenWRT上作为DHCP服务器。事实上它在这方面用的更多。不过不用担心,我们安装的dnsmasq默认不开启DHCP功能。
安装 dnscrypt

使用 brew install dnscrypt-proxy 来安装dnscrypt。

设置启动:

1
2
sudo cp -fv /usr/local/opt/dnscrypt-proxy/*.plist /Library/LaunchDaemons
sudo chown root /Library/LaunchDaemons/homebrew.mxcl.dnscrypt-proxy.plist
编辑配置文件,把本地监听地址改为 127.0.0.1:5355来配合dnsmasq:

1
sudo vi /Library/LaunchDaemons/homebrew.mxcl.dnscrypt-proxy.plist
在 <string>/usr/local/opt/dnscrypt-proxy/sbin/dnscrypt-proxy</string> 这行下面插入: <string>--local-address=127.0.0.1:5355</string> ,好避免和dnsmasq冲突并只允许dnsmasq访问到它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-/Apple/DTD PLIST 1.0/EN" "http:/www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>homebrew.mxcl.dnscrypt-proxy</string>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/opt/dnscrypt-proxy/sbin/dnscrypt-proxy</string>
<string>--local-address=127.0.0.1:5355</string>
<string>--ephemeral-keys</string>
<string>--resolvers-list=/usr/local/Cellar/dnscrypt-proxy/1.6.0/share/dnscrypt-proxy/dnscrypt-resolvers.csv</string>
<string>--resolver-name=dnscrypt.eu-dk</string>
<string>--user=nobody</string>
</array>
<key>UserName</key>
<string>root</string>
<key>StandardErrorPath</key>
//余下部分省略不写。
最后,使用 sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnscrypt-proxy.plist 启动服务。

使用 sudo lsof -ni UDP:5355 或者 ps -ef | grep '[d]nscrypt' 来验证服务已经生效。

dnscrypt 还有个对应的 dnscrypt-wrapper,它兼容dnscrypt-proxy的加密——也就是说你可以用它来搭建自己的dnscrypt服务器而不必使用公用dnscrypt服务器。——这用来抵御DNS污染~你可以参考页尾“延伸阅读”里的链接来了解更多。
配置网络

打开 偏好设置→网络→高级→DNS选项卡 ,只填入 127.0.0.1 并保存即可。

设置DNS
设置DNS
验证

使用dig来分别验证二者是否正常工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
╰─➤ dig www.twitter.com @127.0.0.1 -p 5355

; <<>> DiG 9.8.3-P1 <<>> www.twitter.com @127.0.0.1 -p 5355
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12542
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 4, ADDITIONAL: 5

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

;; ANSWER SECTION:
www.twitter.com. 490 IN CNAME twitter.com.
twitter.com. 16 IN A 199.16.156.6
twitter.com. 16 IN A 199.16.156.102
twitter.com. 16 IN A 199.16.156.198
twitter.com. 16 IN A 199.16.156.230

;; AUTHORITY SECTION:
twitter.com. 112220 IN NS ns4.p34.dynect.net.
twitter.com. 112220 IN NS ns2.p34.dynect.net.
twitter.com. 112220 IN NS ns3.p34.dynect.net.
twitter.com. 112220 IN NS ns1.p34.dynect.net.

;; ADDITIONAL SECTION:
ns1.p34.dynect.net. 40536 IN A 208.78.70.34
ns2.p34.dynect.net. 40536 IN A 204.13.250.34
ns3.p34.dynect.net. 40536 IN A 208.78.71.34
ns4.p34.dynect.net. 40536 IN A 204.13.251.34

;; Query time: 423 msec
;; SERVER: 127.0.0.1#5355(127.0.0.1)
;; WHEN: Wed Sep 2 21:10:55 2015
;; MSG SIZE rcvd: 272

//你可能需要稍微等一会dnscrypt才能够建立连接。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
─➤ dig www.google.com @127.0.0.1

; <<>> DiG 9.8.3-P1 <<>> www.google.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6714
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 4, ADDITIONAL: 5

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

;; ANSWER SECTION:
www.google.com. 297 IN A 173.194.112.116
www.google.com. 297 IN A 173.194.112.112
www.google.com. 297 IN A 173.194.112.113
www.google.com. 297 IN A 173.194.112.114
www.google.com. 297 IN A 173.194.112.115

;; AUTHORITY SECTION:
google.com. 112253 IN NS ns3.google.com.
google.com. 112253 IN NS ns2.google.com.
google.com. 112253 IN NS ns1.google.com.
google.com. 112253 IN NS ns4.google.com.

;; ADDITIONAL SECTION:
ns1.google.com. 300608 IN A 216.239.32.10
ns2.google.com. 300608 IN A 216.239.34.10
ns3.google.com. 300608 IN A 216.239.36.10
ns4.google.com. 300608 IN A 216.239.38.10

;; Query time: 519 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Sep 2 21:10:22 2015
;; MSG SIZE rcvd: 259
//第一次查询略慢,因为要走dnscrypt。

╰─➤ dig www.google.com @127.0.0.1

; <<>> DiG 9.8.3-P1 <<>> www.google.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64399
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.google.com. IN A

;; ANSWER SECTION:
www.google.com. 105 IN A 173.194.112.116
www.google.com. 105 IN A 173.194.112.115
www.google.com. 105 IN A 173.194.112.114
www.google.com. 105 IN A 173.194.112.113
www.google.com. 105 IN A 173.194.112.112

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Sep 2 21:13:34 2015
;; MSG SIZE rcvd: 112
//注意查询时间为0,以后的一段时间内,DNS就被缓存了:)
来自丹麦的dnscrypt服务器
来自丹麦的dnscrypt服务器
延伸阅读

编译安装 dnscrypt-wrapper 搭建防污染 DNS 服务器

dnsmasq (简体中文)

OS X 上的隐私安全指南


https://www.logcg.com/archives/1311.html