Linux 下使用 Pdnsd 避免 DNS 污染

2012年11月04日 , (Shadow Ma)

使用公共 DNS 服務可以避免運營商的 DNS 劫持,但除了這個外在兲朝還存在着 DNS 緩存污染的問題,以前使用 GoAgent 等工具時沒有注意到這個,一直在運行着的 dnsmasq 也只用來作簡單的緩存服務,最近開始長時間掛着 VPN 有時卻打不開 Twitter,才發現是這個問題在作怪。

分析

在中國大陸,對於所有經過防火長城的在UDP的53埠上的域名查詢進行IDS入侵檢測,一經發現與黑名單關鍵詞相匹配的域名查詢請求,其會馬上偽裝成標的域名的解析伺服器給查詢者返回虛假結果。由於通常的域名查詢沒有任何認證機制,而且域名查詢通常基於的UDP協議是無連線不可靠的協議,查詢者只能接受最先到達的格式正確結果,並丟棄之後的結果。

也就是說就算使用的是牆外的 DNS 服務器也仍然會被污染。像我的情況,因爲使用了本地的 DNS 緩存服務和 chnroutes 的原因,不是所有的 DNS 記錄都是使用 VPN 通道的 DNS 服務器查詢的,所以出現了掛着 VPN 卻打不開 Twitter 的情況,DNS 查詢到的是錯誤的 ip。

思路

  1. 連接 VPN 後重啓 DNS 緩存服務,只對於像我這樣使用 VPN 且本地有緩存服務的,只需要在之前設置的連接腳本裏加上重啓服務的命令就行(當然還需要把緩存服務的上遊 DNS 設成牆外的服務器)
  2. 使用 tcp 方式查詢,tcp 的 DNS 請求會出現被 reset 的情況
  3. 把 DNS 服務轉發到非標準端口,這個需要自己有牆外的服務器資源
  4. 使用提供非標準端口服務的 DNS,只有很少的服務器支持

因爲提供非標準端口服務的 DNS 太少,而且在我這兒速度都不快,權衡來看,可以優先使用不算太穩定的 tcp 方式查詢,把非標準端口的 upd 查詢作爲 fallback,對於 linux 來說可以通過設置防火牆規則定義 DNS 存取方式,不過還是推介配置本地的 DNS 轉發服務更爲簡單方便。

因爲之前一直用的 dnsmasq 不支持 tcp 方式查詢,Google 發現了 pdnsd 後就立即換了上來,相對於 dnsmasq 來說功能單一,但更爲強大,單就作 DNS 緩存來說 dnsmasq 就不能修改 TTL。

操作

對於 Arch 來說直接 yaourt -S pdnsd 安裝就好,然後創建配置文件

sudo cp /etc/pdnsd.conf.sample /etc/pdnsd.conf

修改配置文件

/etc/pdnsd.conf
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
global {
        perm_cache=4096;
        cache_dir="/var/cache/pdnsd";
#       pid_file = /var/run/pdnsd.pid;
        run_as="nobody";
        server_ip = 127.0.0.1;  # Use eth0 here if you want to allow other machines on your network to query pdnsd.
        status_ctl = on;
        paranoid=on;            # This option reduces the chance of cache poisoning but may make pdnsd less efficient, unfortunately.
        query_method=tcp_udp;   # 優先使用 tcp 方式查詢
        min_ttl=1d;             # 緩存記錄最少保存一天
        max_ttl=1w;             # One week.
        timeout=10;             # Global timeout option (10 seconds).
        neg_domain_pol=on;
        udpbufsize=1024;        # Upper limit on the size of UDP messages.
        tcp_qtimeout=1;         # tcp 查詢超時
        par_queries=2;          # 同時從兩組服務器查詢
}

server {
        label= "myisp";
        ip = 114.114.114.114;
        timeout=4;
        uptest=ping;
        ping_timeout = 100;
        interval=10m;
        purge_cache=off;
        edns_query=off;
        policy=excluded;
        include=.cn,
                .xn--fiqs8s,   # .中国
                .115.com,
                .126.com,
                .126.net,
                .163.com,
                .17173.com,
                .17cdn.com,
                .51.la,
                .6rooms.com,
                .91.com,
                .alimama.com,
                .alipay.com,
                .atpanel.com,
                .baidu.com,
                .bdimg.com,
                .bilibili.tv,
                .ccb.com,
                .cdn20.com,
                .cnepub.com,
                .cnzz.com,
                .douban.com,
                .douban.fm,
                .duomi.com,
                .gtimg.com,
                .hdslb.com,
                .hiapk.com,
                .hoopchina.com,
                .hupu.com,
                .iask.com,
                .ifeng.com,
                .ifengimg.com,
                .ijinshan.com,
                .iqiyi.com,
                .jing.fm,
                .kandian.com,
                .kandian.net,
                .kanimg.com,
                .kdnet.net,
                .koudai8.com,
                .ku6cdn.com,
                .ku6.com,
                .letv.com,
                .loli.mg,
                .loli.vg,
                .lxdns.com,
                .mapbar.com,
                .microsoft.com,
                .mop.com,
                .mydrivers.com,
                .netease.com,
                .pengyou.com,
                .qiyi.com,
                .qiyipic.com,
                .qq.com,
                .qqmail.com,
                .qstatic.com,
                .renren.com,
                .sdo.com,
                .sina.com,
                .sinaedge.com,
                .sogou.com,
                .sohu.com,
                .soso.com,
                .tanx.com,
                .taobaocdn.com,
                .taobao.com,
                .tbcache.com,
                .tdimg.com,
                .tencent.com,
                .thawte.com,
                .tianyaui.com,
                .tmall.com,
                .tudou.com,
                .tudouui.com,
                .weibo.com,
                .wrating.com,
                .xiami.com,
                .xiami.net,
                .xiaonei.com,
                .xlpan.com,
                .xunlei.com,
                .ydstatic.com,
                .ykimg.com,
                .youdao.com,
                .youku.com,
                .zbjimg.com,
                .zhubajie.com;
}

# The servers provided by OpenDNS are fast, but they do not reply with
# NXDOMAIN for non-existant domains, instead they supply you with an
# address of one of their search engines. They also lie about the addresses of 
# of the search engines of google, microsoft and yahoo.
# If you do not like this behaviour the "reject" option may be useful.
server {
        label = "opendns";
        ip = 208.67.222.222, 208.67.220.220;
        reject = 208.69.32.0/24,  # You may need to add additional address ranges
                 208.69.34.0/24,  # here if the addresses of their search engines
                 208.67.219.0/24, # change.
                 208.67.217.0/24,
                 208.67.216.0/24;
        reject_policy = fail;     # If you do not provide any alternative server sections, like the following root-server example, "negate" may be more appropriate here.
        port = 5353;              # 指定支持的非標準端口
        timeout = 4;
        uptest = ping;            # Test availability using ICMP echo requests.
        ping_timeout = 100;       # ping test will time out after 10 seconds.
        interval = 15m;           # Test every 15 minutes.
        preset = off;
}

server {
        label= "v2ex";
        ip = 199.91.73.222;       # v2ex 只有這個地址有非標準端口所以單獨放出來
        port = 3389;              # 指定支持的非標準端口
        timeout=4;
        uptest=ping;
        ping_timeout = 100;
        interval=10m;
        purge_cache=off;
        edns_query=off;
}

server {
        label= "hinet";
        ip = 168.95.1.1, 168.95.192.1, 168.95.192.2;
        timeout=4;
        uptest=ping;
        ping_timeout = 100;
        interval=10m;
        purge_cache=off;
        edns_query=off;
}

server {
        label= "google dns";
        ip = 8.8.8.8, 8.8.4.4;
        timeout=4;
        uptest=ping;
        ping_timeout = 100;
        interval=10m;
        purge_cache=off;
        edns_query=off;
}

全局配置中 query_method 可以設爲 tcp_only,我設置成 tcp_udp 優先使用 tcp 方式查詢所以還得設置 tcp_qtimeout,tcp 方式查詢超時就放棄。

我把 ISP 或者國內的 DNS 服務器放到了最前面,只查詢指定的域名,解決某些國內網站因爲是國外 DNS 請求而返回了過慢的 CDN 線路的 ip,網站列表來源於 http://felixc.at/Dnsmasq ,之後先放上提供非標準端口服務的 DNS 服務器,在 tcp 無法查詢轉而使用 udp 方式時使用非標準端口避免 DNS 污染,最後放上我常用的中華電信和 Google 的 DNS,都支持 tcp 方式查詢。

啓動服務

sudo systemctl start pdnsd.service

設爲開機啓動

sudo systemctl enable pdnsd.service

測試

DNS 被污染,返回了錯誤的 ip

成功得到正確 ip

使用本地的轉發服務查詢 twitter.com 返回正確 ip,說明在服務器最前列的國內的 DNS 的確沒查詢列表外的域名。

疑難解答

系統啓動時不可用

因爲 pdnsd 服務啓動時網絡還沒連接上,服務器無法通過檢測被忽略,導致無服務器可進行查詢,請將至少將一組服務器中的 uptest 設爲 none,並設置 preset 爲 on,讓服務器初始爲可用。

後記

從之後的測試來看上面的方案並不可靠,原本優先使用 tcp 的原因是希望有更好的速度,但爲了預防查詢失敗仍然不得不把支持非標準端口查詢但在我這兒速度較慢的服務器放在前列,這樣還不如直接用非標準端口的 udp 方式從這些服務器查詢,而且在 tcp_udp 模式下,tcp 查詢超時就會轉而使用 udp 方式,但 tcp 請求被重置,會被當作 negative 結果返回,這樣的話就要把 neg_domain_pol 設爲 off,不緩存 negative 結果,要不很長一段時間都無法訪問這域名,但所有的 negative 結果都不緩存的話,會增加不必要的查詢請求,耗費資源。

總之,現階段最好的方案是直接使用非標準端口的 udp 查詢,把 query_method 設成 udp_only,刪去不支持非標準端口查詢的服務器,要是自已有境外的服務器資源的話,可以把自己要用的 DNS 服務器轉發到非標準端口來用。

完全從頭開始了 Google 你個傻逼
點擊查看評論
返回首頁 返回頂部