章 強(qiáng), 彭 飛
(揚(yáng)州職業(yè)大學(xué), 江蘇 揚(yáng)州 225009)
域名系統(tǒng)(以下簡(jiǎn)稱DNS)是互聯(lián)網(wǎng)的核心基礎(chǔ)設(shè)施,它是一個(gè)分布式的分層數(shù)據(jù)庫(kù),存儲(chǔ)A、MX、AAAA、CNAME等資源記錄。整個(gè)DNS被分為三層:根、頂級(jí)域名(TLD)和各級(jí)權(quán)威DNS服務(wù)器。DNS因此成為互聯(lián)網(wǎng)重要的基礎(chǔ)設(shè)施之一。也正是這個(gè)原因,DNS服務(wù)器一直是互聯(lián)網(wǎng)被攻擊的主要目標(biāo),攻擊方法如放大攻擊、緩存中毒攻擊、DDoS攻擊、DNS劫持等[1-2]。
DNS協(xié)議被認(rèn)為是一種安全的通信協(xié)議,連接到互聯(lián)網(wǎng)的每臺(tái)計(jì)算機(jī)都信任從其所查詢DNS權(quán)威服務(wù)器收到的名稱解析結(jié)果。但是,DNS數(shù)據(jù)都是通過(guò)明文發(fā)送的,在一個(gè)遞歸名稱解析過(guò)程中,DNS查詢中的每次迭代引用都容易受到惡意攻擊。比如網(wǎng)絡(luò)攻擊者可以通過(guò)中間人攻擊等手段竊取DNS請(qǐng)求,用惡意記錄和正確的ID字段構(gòu)建一個(gè)惡意的響應(yīng)數(shù)據(jù)包,并在合法響應(yīng)數(shù)據(jù)到達(dá)之前競(jìng)相發(fā)送惡意響應(yīng),如果惡意記錄的生存響應(yīng)延遲(TTL)再被設(shè)置為一個(gè)非常高的數(shù)值,那么受害者將在很長(zhǎng)一段響應(yīng)時(shí)間內(nèi)緩存這些惡意域名解析記錄,導(dǎo)致終端客戶被引導(dǎo)訪問(wèn)惡意網(wǎng)站。一個(gè)典型的案例是DNS Kaminsky攻擊[3],它實(shí)際上是利用截獲DNS消息中的查詢ID,采用中間人攻擊手段,使DNS解析器接受偽裝的DNS響應(yīng)。
為了有效解決DNS安全防護(hù)的問(wèn)題,互聯(lián)網(wǎng)工程任務(wù)組(IETF)開(kāi)發(fā)了DNS安全擴(kuò)展(以下簡(jiǎn)稱DNSSEC)協(xié)議[4],DNSSEC采用非對(duì)稱加密機(jī)制來(lái)驗(yàn)證記錄完整性和真實(shí)性。為實(shí)現(xiàn)DNS有效防護(hù),每個(gè)區(qū)域必須至少提供下列三種記錄類型:(1)DNSKEY記錄。該記錄是公鑰,每個(gè)Zone區(qū)用相應(yīng)的私鑰簽署DNS記錄,解析器使用DNSKEY來(lái)驗(yàn)證這些簽名。Zone區(qū)通常創(chuàng)建兩個(gè)DNSKEY記錄(KSK和ZSK)來(lái)簽署DNS記錄:KSK的私鑰用于簽署DNSKEY記錄,ZSK的私鑰用于簽署所有其他記錄;(2)RRSIG(資源記錄簽名)記錄。它是使用DNSKEY對(duì)應(yīng)私鑰簽署其他記錄的加密簽名;(3)DS記錄。它是由域名注冊(cè)商上傳到父區(qū)的DNSKEY的哈希值。為了確保完整性,DS記錄也需要由父區(qū)簽署(在DS記錄的RRSIG中)。
因此,只有當(dāng)從根區(qū)到葉區(qū)都有有效的DS記錄時(shí),DNSSEC才能正常運(yùn)行,從而建立起一個(gè)信任鏈。圖1是一個(gè)三層信任鏈的模型(子區(qū)、父區(qū)和根區(qū)各擁有一個(gè)ZSK和一個(gè)KSK)。
圖1 基于信任鏈的DNS來(lái)源與完整性認(rèn)證
因此,如果一個(gè)解析器被配置了像信任密鑰一樣的根區(qū)的KSK,它將能夠通過(guò)建立圖1這樣的信任鏈來(lái)檢查子區(qū)域的信息,實(shí)現(xiàn)DNS數(shù)據(jù)的來(lái)源、完整性驗(yàn)證,確保了DNS消息來(lái)源的權(quán)威性和可靠性。
盡管DNSSEC設(shè)計(jì)了理論上近乎完美的DNS保護(hù)機(jī)制,它從1995年就開(kāi)始發(fā)展,第一個(gè)DNSSEC已經(jīng)被開(kāi)發(fā)和標(biāo)準(zhǔn)化了二十多年,但其在互聯(lián)網(wǎng)上的實(shí)際部署率卻不理想,只有47%的ccTLDs(國(guó)家代碼頂級(jí)域)簽署了DNSSEC。[5]經(jīng)過(guò)分析,筆者認(rèn)為主要存在以下四個(gè)方面的問(wèn)題:
在DNSSEC中,DNS響應(yīng)的完整性是通過(guò)使用公鑰加密技術(shù)和數(shù)字簽名來(lái)保證的,因此權(quán)威服務(wù)器必須定期正確地維護(hù)(更換)私鑰和公鑰對(duì)。數(shù)量龐大的各層級(jí)權(quán)威服務(wù)器顯然需要高昂的維護(hù)成本。
在一般情況下,DNSSEC驗(yàn)證是在DNS全解析器上進(jìn)行的,以便實(shí)際使用其緩存功能,因此DNSSEC驗(yàn)證過(guò)程中復(fù)雜的密鑰計(jì)算也將大大增加DNS全解析器的工作負(fù)荷,從而導(dǎo)致域名解析性能的下降。
由于DNSSEC驗(yàn)證主要是在DNS全解析器上完成的,所以終端用戶電腦上的存根解析器并沒(méi)有被DNSSEC的安全名稱解析所覆蓋。在許多網(wǎng)絡(luò)環(huán)境的主機(jī)中,因?yàn)榻K端用戶操作系統(tǒng)的存根DNS解析器不支持DNSSEC,所以終端用戶不能使用DNSSEC,存在安全短板。
由于采用簽名認(rèn)證機(jī)制,每個(gè)記錄都要有一個(gè)簽名記錄RRSIG記錄, DNSSEC需要傳輸這些非標(biāo)準(zhǔn)的DNS數(shù)據(jù)包,DNSKEY 和 RRSIG 記錄實(shí)際響應(yīng)包長(zhǎng)度均比標(biāo)準(zhǔn) UDP 的DNS數(shù)據(jù)包(通常小于512 B)大很多。根據(jù)統(tǒng)計(jì),Zone區(qū)數(shù)據(jù)一般要擴(kuò)大10倍以上(具體實(shí)際數(shù)值與采用的密鑰長(zhǎng)度關(guān)聯(lián)),相應(yīng)的網(wǎng)絡(luò)流量肯定也要相應(yīng)放大,過(guò)強(qiáng)的流量放大效應(yīng)將更容易造成針對(duì)DNS的大規(guī)模DDoS 攻擊[3]。
針對(duì)DNSSEC部署存在的上述缺陷,如果嘗試在解析器之間使用一個(gè)不同的、外部的信任源(比如PKI),是否有可能在不依靠驗(yàn)證證書(shū)鏈的情況下保證DNS域名解析服務(wù)事實(shí)上的安全性?筆者嘗試采用基于PKI 的外部CA證書(shū)的思路來(lái)解決DNS信任鏈的問(wèn)題。
公鑰基礎(chǔ)設(shè)施(PKI)是一個(gè)管理數(shù)字證書(shū)和公鑰加密的系統(tǒng),PKI基于數(shù)字證書(shū),它由證書(shū)機(jī)構(gòu)(CA)頒發(fā)[6]。例如在PKI中最常用的X.509證書(shū)包括代表域名的通用名稱,一個(gè)公鑰。CA有它的根證書(shū),根證書(shū)簽署次級(jí)證書(shū)。用戶可以用父級(jí)證書(shū)驗(yàn)證子級(jí)證書(shū),也同樣可以建立一個(gè)信任鏈[7]。
超文本安全協(xié)議(HTTPS)就是使用數(shù)字證書(shū)進(jìn)行安全數(shù)據(jù)傳輸?shù)囊粋€(gè)例子。由一個(gè)特定的CA頒發(fā)的證書(shū)將給定的域名與證書(shū)受讓人、申請(qǐng)?jiān)撟C書(shū)的實(shí)體、證書(shū)有效期等信息結(jié)合起來(lái),CA用于向?yàn)g覽器證明網(wǎng)絡(luò)服務(wù)器代表了客戶所要求的域名,在成功認(rèn)證后,瀏覽器和網(wǎng)絡(luò)服務(wù)器之間會(huì)建立一個(gè)TLS連接。隨著TLS連接的建立,瀏覽器和網(wǎng)絡(luò)服務(wù)器之間的通信將被加密,并防止任何第三方的竊聽(tīng)。通過(guò)HTTPS,網(wǎng)絡(luò)服務(wù)器使用數(shù)字證書(shū)來(lái)加密他們與客戶之間的所有通信。根據(jù)谷歌統(tǒng)計(jì)[7],目前全世界大約96%的網(wǎng)頁(yè)都是通過(guò)HTTPS加載的。與DNSSEC相比,數(shù)字證書(shū)的部署率非常高。
由于DNSSEC的層次結(jié)構(gòu),在父域部署DNSSEC之前,子域無(wú)法部署DNSSEC。此外,其上傳DS記錄的過(guò)程中,一些子域名服務(wù)器忘記上傳DS記錄或上傳錯(cuò)誤,大約30%的簽名域名在其父區(qū)沒(méi)有DS記錄。而本文所提出解決方案的關(guān)鍵思路是驗(yàn)證記錄而不是上傳DS記錄,ProxyDNS使用基于PKI的CA數(shù)字證書(shū),而不是信任鏈。在DNSSEC中,名稱服務(wù)器中的記錄是由ZSK簽署的。這些ZSK再由KSK簽署。KSK以DS記錄的形式上傳到父域。這就形成了一個(gè)從記錄到根KSK的信任鏈。
而在ProxyDNS中,名稱服務(wù)器用他們自己的證書(shū)簽署記錄,這些證書(shū)由基于PKI的CA頒發(fā)。ProxyDNS不需要向父區(qū)上傳任何記錄。
筆者使用CA證書(shū)來(lái)驗(yàn)證數(shù)據(jù)的完整性,而不是使用DS記錄。每個(gè)權(quán)威名稱服務(wù)器用CA頒發(fā)給它的數(shù)字證書(shū)來(lái)簽署他們的記錄。每個(gè)記錄的信任錨移到他們的CA上,消除了DNSSEC中父域、子域之間的依賴性。在這個(gè)場(chǎng)景中,記錄驗(yàn)證過(guò)程如下:(1)權(quán)威名稱服務(wù)器擁有由CA頒發(fā)的數(shù)字證書(shū),并用證書(shū)的私鑰生成記錄的簽名;(2)當(dāng)ProxyDNS代理(或解析器)收到查詢時(shí),代理客戶請(qǐng)求DNS查詢記錄、生成簽名和證書(shū)。在證書(shū)鏈被驗(yàn)證后,公鑰被從證書(shū)中提取出來(lái)并被緩存,如果驗(yàn)證有效,則將記錄發(fā)送給客戶。
ProxyDNS作為一個(gè)代理程序在終端用戶機(jī)器上運(yùn)行??蛻舳瞬恢涝摯淼拇嬖?并像往常一樣向DNS解析器發(fā)送請(qǐng)求。代理程序會(huì)截獲該查詢請(qǐng)求,并將其發(fā)送給DNS解析器。ProxyDNS代理驗(yàn)證了這些記錄,然后將查詢的答案再發(fā)送給終端用戶??蛻舳舜淼膶?shí)現(xiàn)也滿足了向后的兼容性,保證了端到端的DNS安全性。
由CA頒發(fā)給權(quán)威名稱服務(wù)器的證書(shū)被用于DNS記錄驗(yàn)證,由于簽名是通過(guò)使用證書(shū)的私鑰產(chǎn)生的,代理通過(guò)使用配對(duì)的公鑰來(lái)驗(yàn)證DNS記錄,為了讓代理接觸到證書(shū),該證書(shū)必須作為記錄存儲(chǔ)在權(quán)威名稱服務(wù)器中。根據(jù)RFC4398,數(shù)字證書(shū)可以被儲(chǔ)存為一條記錄,這里取名為CERT記錄,其結(jié)構(gòu)主要包括:主機(jī)名、記錄類型、證書(shū)類型、密鑰標(biāo)簽、用于生成證書(shū)的算法類型、TTL、以及用Base64編碼的證書(shū)。
在生成簽名的情況下,使用TXT記錄。在ProxyDNS中,為每個(gè)RRset生成簽名,類似于DNSSEC的RRSIG簽名[7]。例如,為A記錄RRset創(chuàng)建一個(gè)簽名,首先使用SHA256函數(shù)創(chuàng)建一個(gè)摘要。如果有多條A記錄,每條記錄被連接成一個(gè)字符串,中間用冒號(hào)分隔,然后生成一個(gè)摘要。有了這個(gè)摘要,采用OpenSSL證書(shū)的私鑰為A記錄創(chuàng)建一個(gè)簽名。最后,簽名用Base64進(jìn)行編碼,作為TXT記錄上傳。由于TXT記錄有255個(gè)字符的限制[4],簽名被分成200個(gè)字節(jié),并與包含簽名所屬記錄信息的頭部一并存貯。
當(dāng)收到來(lái)自客戶端的查詢時(shí),代理按圖2順序操作。
圖2 ProxyDNS記錄驗(yàn)證的流程
第一步:創(chuàng)建一個(gè)查詢,獲取記錄(這里是TXT記錄)的簽名。在獲取TXT記錄后,代理找到帶有ProxyDNS頭的字符串,然后解析TXT記錄并重建簽名,最后代理得到了記錄的簽名;第二步:檢查緩存。如果記錄的公鑰被緩存了,代理就會(huì)加載緩存的公鑰,如果沒(méi)有緩存,則創(chuàng)建一個(gè)CERT記錄的查詢來(lái)獲取CERT記錄。當(dāng)CERT記錄被獲取時(shí),它的證書(shū)鏈被驗(yàn)證,并且公鑰被從CERT記錄的證書(shū)中提取,公鑰被緩存在代理處。第三步:驗(yàn)證該記錄。利用重建的簽名和證書(shū)中的公鑰,對(duì)記錄進(jìn)行驗(yàn)證。
按照這個(gè)ProxyDNS代理的設(shè)計(jì)思路,筆者使用C語(yǔ)言開(kāi)發(fā)了一個(gè)原型程序,搭建了一個(gè)仿真測(cè)試環(huán)境。
假設(shè)驗(yàn)證“www. yzpc-dns-test.com”的A記錄。客戶端像往常一樣發(fā)送DNS查詢??蛻舳诉\(yùn)行“dig www. yzpc-dns-test.com/A”命令。這個(gè)請(qǐng)求被轉(zhuǎn)發(fā)給代理,代理向本地解析器請(qǐng)求一個(gè)相應(yīng)的A記錄。然后返回“www. yzpc-dns-test.com”包含其 IP 地址的 A 記錄。
在獲取A記錄后,對(duì)TXT記錄的查詢被發(fā)送到解析器。檢查已經(jīng)收到的TXT記錄,找到帶有ProxyDNS頭的字符串。例如,A記錄的頭部看起來(lái)像 “ProxyDNS-Base64-A-1”“ProxyDNS-Base64-A-2”“ProxyDNS-Base64-A-n”等。對(duì)頭文件進(jìn)行解析,重建簽名,并通過(guò)Base64進(jìn)行解碼,最后,使用SHA256算法生成IP地址的摘要。
在重構(gòu)簽名后,檢查緩存。由于最初沒(méi)有任何緩存,緩存沒(méi)有命中,相應(yīng)記錄的CERT記錄被ProxyDNS查詢到,該證書(shū)位于該記錄的權(quán)威DNS服務(wù)器上。如果“www. yzpc-dns-test.com”的權(quán)威名稱服務(wù)器是“ns. yzpc-dns-test.com”,就會(huì)向“ns. yzpc-dns-test.com”生成新的CERT記錄查詢。當(dāng)從本地解析器獲取“ns. yzpc-dns-test.com”的CERT記錄時(shí),首先對(duì)證書(shū)鏈進(jìn)行驗(yàn)證。假設(shè)根證書(shū)和中間證書(shū)都存儲(chǔ)在客戶端,證書(shū)鏈將使用OpenSSL進(jìn)行驗(yàn)證。當(dāng)證書(shū)鏈被確認(rèn)后,ProxyDNS檢查證書(shū)的公共名稱是否為“ns. yzpc-dns-test.com”。這是因?yàn)樾枰獧z查該證書(shū)是否是用于記錄驗(yàn)證的正確證書(shū)。當(dāng)證書(shū)的驗(yàn)證完成后,使用OpenSSL從證書(shū)中提取公鑰并進(jìn)行緩存,公鑰被緩存為一個(gè)文件。
有了摘要、公鑰和簽名,記錄就可以用OpenSSL進(jìn)行驗(yàn)證。當(dāng)驗(yàn)證完成后,返回客戶端的響應(yīng)。
在數(shù)據(jù)中心私有云上安裝一個(gè)DNS解析器虛擬機(jī),使用Bind9來(lái)刷新緩存。從域名服務(wù)商注冊(cè)“yzpc-dns-test.com”域名用于權(quán)威服務(wù)器的記錄管理?!皔zpc-dns-test.com”區(qū)的權(quán)威名稱服務(wù)器也使用Bind9安裝在數(shù)據(jù)中心私有云虛擬機(jī)上。
從響應(yīng)延遲、存儲(chǔ)消耗開(kāi)銷的角度對(duì)ProxyDNS和DNSSEC進(jìn)行比較。
為了比較DNSSEC和ProxyDNS的響應(yīng)延遲開(kāi)銷,使用“dig”命令測(cè)量解析響應(yīng)延遲,客戶端收到查詢響應(yīng)的響應(yīng)延遲。使用“dig”命令發(fā)送了對(duì)A記錄的查詢,在正常情況下,它是在關(guān)閉ProxyDNS和DNSSEC功能的情況下測(cè)量的。在開(kāi)啟DNSSEC的場(chǎng)景下,它是在關(guān)閉ProxyDNS功能的場(chǎng)景下設(shè)置了DNSSEC后測(cè)量的。在啟用ProxyDNS的場(chǎng)景下,它是在關(guān)閉DNSSEC并只使用ProxyDNS的功能時(shí)測(cè)量的。響應(yīng)延遲數(shù)據(jù)分別是三種場(chǎng)景各測(cè)量20次的結(jié)果平均值(見(jiàn)表1)。
表1 DNS、DNSSEC和ProxyDNS響應(yīng)時(shí)間比較 單位:s
在沒(méi)有任何安全擴(kuò)展的情況下,A記錄的解析響應(yīng)延遲約為0.21s。當(dāng)部署了DNSSEC后,解析響應(yīng)延遲增加到約0.46s,幾乎慢了2倍多。在采用ProxyDNS的情況下,解析響應(yīng)延遲約為0.28s,幾乎比DNSSEC快40%。
為了比較DNSSEC和ProxyDNS中父區(qū)的存儲(chǔ)消耗開(kāi)銷,可查看每個(gè)系統(tǒng)中使用的記錄(見(jiàn)表2)。RRSIG和TXT記錄的比較被排除在外,因?yàn)镈NSSEC和ProxyDNS都是用相同的方法來(lái)生成和管理簽名。
表2 DNSSEC和ProxyDNS存儲(chǔ)消耗比較
當(dāng)使用DNSSEC時(shí),會(huì)生成一個(gè)DNSKEY記錄,并以DS記錄的形式上傳到父域。在一個(gè)權(quán)威服務(wù)器中,DNSKEY的開(kāi)銷不大,但在必須存儲(chǔ)DS記錄的父域(如TLD)中,存儲(chǔ)消耗開(kāi)銷很大。根據(jù)statdns[8],在“.com”域中大約有440萬(wàn)條DS記錄被上傳。假設(shè)所有這些DS記錄都是用SHA-256算法上傳的,計(jì)算下來(lái)相當(dāng)于300MiB左右。而在ProxyDNS中,上傳DS記錄的過(guò)程是不需要的,所有的DS記錄都可以用一個(gè)CERT記錄代替。一個(gè)CERT記錄僅占2KiB,與使用DS記錄相比,可以將存儲(chǔ)消耗開(kāi)銷降低到DNSSEC方案的0.0008%。
文章分析了目前作為DNS防護(hù)主要解決方案DNSSEC部署率過(guò)低的原因,研究得出DNSSEC的分層結(jié)構(gòu)中證書(shū)鏈驗(yàn)證開(kāi)銷過(guò)大是DNSSEC部署率偏低的一個(gè)主要因素。提出了通過(guò)減少證書(shū)鏈簽名驗(yàn)證的數(shù)量,將大部分的計(jì)算、帶寬、存儲(chǔ)開(kāi)銷成本盡可能降低的思路來(lái)克服DNSSEC目前實(shí)際部署存在的困難。筆者開(kāi)發(fā)的基于PKI的ProxyDNS原型程序,在沒(méi)有分層證書(shū)驗(yàn)證的情況下提供了DNS查詢數(shù)據(jù)的完整性和真實(shí)性驗(yàn)證,使用PKI公鑰基礎(chǔ)設(shè)施中的CA數(shù)字證書(shū)進(jìn)行數(shù)據(jù)驗(yàn)證,由于不需要向上層域上傳記錄,因此可以消除證書(shū)鏈的層次結(jié)構(gòu)。最后測(cè)量ProxyDNS響應(yīng)延遲和數(shù)據(jù)存儲(chǔ)開(kāi)銷。仿真測(cè)試結(jié)果表明:與DNSSEC方案相比,可以用很少的額外開(kāi)銷來(lái)維持DNSSEC幾乎同等的DNS安全水平,特別在性能方面比DNSSEC有明顯的提升,可以作為實(shí)現(xiàn)DNS安全的一個(gè)輕量化解決方案。