dnspeep:監(jiān)控 DNS 查詢的工具
在過去的幾天中,我編寫了一個(gè)叫作 dnspeep 的小工具,它能讓你看到你電腦中正進(jìn)行的 DNS 查詢,并且還能看得到其響應(yīng)。它現(xiàn)在只有 250 行 Rust 代碼。
我會討論如何去嘗試它、能做什么、為什么我要編寫它,以及當(dāng)我在開發(fā)時(shí)所遇到的問題。
如何嘗試
我構(gòu)建了一些二進(jìn)制文件,因此你可以快速嘗試一下。
對于 Linux(x86):
wget https://github.com/jvns/dnspeep/releases/download/v0.1.0/dnspeep-linux.tar.gztar -xf dnspeep-linux.tar.gzsudo ./dnspeep
對于 Mac:
wget https://github.com/jvns/dnspeep/releases/download/v0.1.0/dnspeep-macos.tar.gztar -xf dnspeep-macos.tar.gzsudo ./dnspeep
它需要以超級用戶身份運(yùn)行,因?yàn)樗枰L問計(jì)算機(jī)正在發(fā)送的所有 DNS 數(shù)據(jù)包。 這與 tcpdump 需要以超級身份運(yùn)行的原因相同:它使用 libpcap,這與 tcpdump 使用的庫相同。
如果你不想在超級用戶下運(yùn)行下載的二進(jìn)制文件,你也能在 https://github.com/jvns/dnspeep 查看源碼并且自行編譯。
輸出結(jié)果是什么樣的
以下是輸出結(jié)果。每行都是一次 DNS 查詢和響應(yīng):
$ sudo dnspeepquery name server IP responseA firefox.com 192.168.1.1 A: 44.235.246.155, A: 44.236.72.93, A: 44.236.48.31AAAA firefox.com 192.168.1.1 NOERRORA bolt.dropbox.com 192.168.1.1 CNAME: bolt.v.dropbox.com, A: 162.125.19.131
這些查詢是來自于我在瀏覽器中訪問的 neopets.com,而 bolt.dropbox.com 查詢是因?yàn)槲艺谶\(yùn)行 Dropbox 代理,并且我猜它不時(shí)會在后臺運(yùn)行,因?yàn)槠湫枰健?/p>
為什么我要開發(fā)又一個(gè) DNS 工具?
之所以這樣做,是因?yàn)槲艺J(rèn)為當(dāng)你不太了解 DNS 時(shí),DNS 似乎真的很神秘!
你的瀏覽器(和你電腦上的其他軟件)一直在進(jìn)行 DNS 查詢,我認(rèn)為當(dāng)你能真正看到請求和響應(yīng)時(shí),似乎會有更多的“真實(shí)感”。
我寫這個(gè)也把它當(dāng)做一個(gè)調(diào)試工具。我想“這是 DNS 的問題?”的時(shí)候,往往很難回答。我得到的印象是,當(dāng)嘗試檢查問題是否由 DNS 引起時(shí),人們經(jīng)常使用試錯(cuò)法或猜測,而不是僅僅查看計(jì)算機(jī)所獲得的 DNS 響應(yīng)。
你可以看到哪些軟件在“秘密”使用互聯(lián)網(wǎng)
我喜歡該工具的一方面是,它讓我可以感知到我電腦上有哪些程序正使用互聯(lián)網(wǎng)!例如,我發(fā)現(xiàn)在我電腦上,某些軟件出于某些理由不斷地向 ping.manjaro.org 發(fā)送請求,可能是為了檢查我是否已經(jīng)連上互聯(lián)網(wǎng)了。
實(shí)際上,我的一個(gè)朋友用這個(gè)工具發(fā)現(xiàn),他的電腦上安裝了一些以前工作時(shí)的企業(yè)監(jiān)控軟件,但他忘記了卸載,因此你甚至可能發(fā)現(xiàn)一些你想要?jiǎng)h除的東西。
如果你不習(xí)慣的話, tcpdump 會令人感到困惑
當(dāng)我試圖向人們展示他們的計(jì)算機(jī)正在進(jìn)行的 DNS 查詢時(shí),我的第一感是想“好吧,使用 tcpdump”!而 tcpdump 確實(shí)可以解析 DNS 數(shù)據(jù)包!
例如,下方是一次對 incoming.telemetry.mozilla.org. 的 DNS 查詢結(jié)果:
11:36:38.973512 wlp3s0 Out IP 192.168.1.181.42281 > 192.168.1.1.53: 56271+ A? incoming.telemetry.mozilla.org. (48)11:36:38.996060 wlp3s0 In IP 192.168.1.1.53 > 192.168.1.181.42281: 56271 3/0/0 CNAME telemetry-incoming.r53-2.services.mozilla.com., CNAME prod.data-ingestion.prod.dataops.mozgcp.net., A 35.244.247.133 (180)
絕對可以學(xué)著去閱讀理解一下,例如,讓我們分解一下查詢:
192.168.1.181.42281 > 192.168.1.1.53: 56271+ A? incoming.telemetry.mozilla.org. (48)
A?意味著這是一次 A 類型的 DNS 查詢incoming.telemetry.mozilla.org.是被查詢的名稱56271是 DNS 查詢的 ID192.168.1.181.42281是源 IP/端口192.168.1.1.53是目的 IP/端口(48)是 DNS 報(bào)文長度
在響應(yīng)報(bào)文中,我們可以這樣分解:
56271 3/0/0 CNAME  telemetry-incoming.r53-2.services.mozilla.com., CNAME  prod.data-ingestion.prod.dataops.mozgcp.net., A 35.244.247.133 (180)
3/0/0是在響應(yīng)報(bào)文中的記錄數(shù):3 個(gè)回答,0 個(gè)權(quán)威記錄,0 個(gè)附加記錄。我認(rèn)為 tcpdump 甚至只打印出回答響應(yīng)報(bào)文。CNAME telemetry-incoming.r53-2.services.mozilla.com、CNAME prod.data-ingestion.prod.dataops.mozgcp.net.和A 35.244.247.133是三個(gè)響應(yīng)記錄。56271是響應(yīng)報(bào)文 ID,和查詢報(bào)文的 ID 相對應(yīng)。這就是你如何知道它是對前一行請求的響應(yīng)。
我認(rèn)為,這種格式最難處理的是(作為一個(gè)只想查看一些 DNS 流量的人),你必須手動匹配請求和響應(yīng),而且它們并不總是相鄰的行。這就是計(jì)算機(jī)擅長的事情!
因此,我決定編寫一個(gè)小程序(dnspeep)來進(jìn)行匹配,并排除一些我認(rèn)為多余的信息。
我在編寫時(shí)所遇到的問題
在撰寫本文時(shí),我遇到了一些問題:
- 我必須給 
pcap包打上補(bǔ)丁,使其能在 Mac 操作系統(tǒng)上和 Tokio 配合工作(這個(gè)更改)。這是其中的一個(gè) bug,花了很多時(shí)間才搞清楚,用了 1 行代碼才解決 :smiley: - 不同的 Linux 發(fā)行版似乎有不同的 
libpcap.so版本。所以我不能輕易地分發(fā)一個(gè)動態(tài)鏈接 libpcap 的二進(jìn)制文件(你可以 在這里 看到其他人也有同樣的問題)。因此,我決定在 Linux 上將 libpcap 靜態(tài)編譯到這個(gè)工具中。但我仍然不太了解如何在 Rust 中正確做到這一點(diǎn)作,但我通過將libpcap.a文件復(fù)制到target/release/deps目錄下,然后直接運(yùn)行cargo build,使其得以工作。 - 我使用的 
dns_parsercarte 并不支持所有 DNS 查詢類型,只支持最常見的。我可能需要更換一個(gè)不同的工具包來解析 DNS 數(shù)據(jù)包,但目前為止還沒有找到合適的。 - 因?yàn)?nbsp;
pcap接口只提供原始字節(jié)(包括以太網(wǎng)幀),所以我需要 編寫代碼來計(jì)算從開頭剝離多少字節(jié)才能獲得數(shù)據(jù)包的 IP 報(bào)頭。我很肯定我還遺漏了一些情形。 
我對于給它取名也有過一段艱難的時(shí)光,因?yàn)橐呀?jīng)有許多 DNS 工具了(dnsspy!dnssnoop!dnssniff!dnswatch!)我基本上只是查了下有關(guān)“監(jiān)聽”的每個(gè)同義詞,然后選擇了一個(gè)看起來很有趣并且還沒有被其他 DNS 工具所占用的名稱。
該程序沒有做的一件事就是告訴你哪個(gè)進(jìn)程進(jìn)行了 DNS 查詢,我發(fā)現(xiàn)有一個(gè)名為 dnssnoop 的工具可以做到這一點(diǎn)。它使用 eBPF,看上去很酷,但我還沒有嘗試過。
可能會有許多 bug
我只在 Linux 和 Mac 上簡單測試了一下,并且我已知至少有一個(gè) bug(不支持足夠多的 DNS 查詢類型),所以請?jiān)谟龅絾栴}時(shí)告知我!
盡管這個(gè) bug 沒什么危害,因?yàn)檫@ libpcap 接口是只讀的。所以可能發(fā)生的最糟糕的事情是它得到一些它無法解析的輸入,最后打印出錯(cuò)誤或是崩潰。
編寫小型教育工具很有趣
最近,我對編寫小型教育的 DNS 工具十分感興趣。
到目前為止我所編寫的工具:
- https://dns-lookup.jvns.ca(一種進(jìn)行 DNS 查詢的簡單方法)
 - https://dns-lookup.jvns.ca/trace.html(向你顯示在進(jìn)行 DNS 查詢時(shí)內(nèi)部發(fā)生的情況)
 - 本工具(
dnspeep) 
以前我盡力闡述已有的工具(如 dig 或 tcpdump)而不是編寫自己的工具,但是經(jīng)常我發(fā)現(xiàn)這些工具的輸出結(jié)果讓人費(fèi)解,所以我非常關(guān)注以更加友好的方式來看這些相同的信息,以便每個(gè)人都能明白他們電腦正在進(jìn)行的 DNS 查詢,而不僅僅是依賴 tcmdump。















 
 
 



 
 
 
 