資安

移動互聯網時代 , 如何優化你的網絡 —— 域名解析篇

移動互聯網時代 , 如何優化你的網絡 —— 域名解析篇

阿里雲 移動服務

泠茗

dns_domain_name_server_1021x580

域名(Domain Name),是由一串用點分隔的名字組成的互聯網上某臺計算機或某組計算機的標識,它的目的是為了方便人們更簡單便捷地訪問互聯網上的服務。在實際的系統實現中,域名通過DNS(Domain Name System)系統轉化為服務器的IP地址,以方便機器通過IP進行尋址和通信。上述行為,我們稱之為域名解析。

作為一次網絡通信最前置的環節,域名解析的重要性不言而喻。在傳統的基於瀏覽器的網站訪問場景下,域名解析環節由瀏覽器內核實現,網站開發者無需關心域名解析的細節。But there are always two sides to every coin,一旦域名解析環節發生異常,開發者面對這樣的黑盒架構就會顯得束手無策,一個很典型的例子即域名劫持問題,關於這一點我們在後文會有更詳細的介紹。

進入移動互聯網時代,大量的應用基於C/S架構構建。相較於傳統的面向瀏覽器的Web App,C/S架構的應用賦予了我們非常大的軟件定製空間,開發者甚至可以滲透到整個應用的底層網絡實現當中,域名解析環節的優化因此變為了可能。本篇文章我們就一起來看一看傳統域名解析存在的問題,對應的根源,以及可能的優化方案。


關於域名解析,你應該知道的基本概念

在瞭解傳統域名解析的流程之前,有幾個專有名詞我們需要了解一下:

根域、頂級域、二級域

DNS系統一般採用樹狀結構進行組織,以ru.wikipedia.org為例,org為頂級域名,wikipedia為二級域名,ru為三級域名,域名樹狀組織結構如下圖所示。

52e57c5c96885ac93fe63ee949fc6068a996949a

權威DNS

權威DNS即最終決定域名解析結果的服務器,開發者可以在權威DNS上配置、變更、刪除具體域名的對應解析結果信息。阿里云云解析( https://wanwang.aliyun.com/domain/dns )即權威DNS服務提供商。

遞歸DNS

遞歸DNS又稱為Local DNS,它沒有域名解析結果的決定權,但代理了用戶向權威DNS獲取域名解析結果的過程。遞歸DNS上有緩存模塊,當目標域名存在緩存解析結果並且TTL未過期時(每個域名都有TTL時間,即有效生存時間,若域名解析結果緩存的時間超過TTL,需要重新向權威DNS獲取解析結果),遞歸DNS會返回緩存結果,否則,遞歸DNS會一級一級地查詢各個層級域名的權威DNS直至獲取最終完整域名的解析結果。關於域名解析的具體流程下文會舉例說明。

公共DNS

公共DNS是遞歸DNS的一種特例,它是一種全網開放的遞歸DNS服務,而傳統的遞歸DNS信息一般由運營商分發給用戶。一個比較典型的公共DNS即Google的8.8.8.8,我們可以通過在操作系統配置文件中配置公共DNS來代替Local DNS完成域名解析流程。

在實際的使用過程中,我們通常不需要手工指定自己的Local DNS地址。運營商會通過DHCP協議在系統網絡初始化階段將Local DNS地址分配給我們的計算機。當我們需要使用公共DNS服務時,我們就必須手工指定這些服務的地址。以Linux為例,我們可以通過在'/etc/resolv.conf'中添加Local DNS地址項來改變本機Local DNS的地址。

瞭解了上述域名解析相關的常見術語,我們再來仔細看一看一次域名解析流程具體是如何發生的。

a33d57c0a93ebf9eacf090e6f81a98bcda023334

如上圖所示,以訪問www.taobao.com為例,一次完整的域名解析流程包括:

  • 終端向Local DNS發起域名解析請求;
  • Local DNS在獲取到域名解析請求後首先從Root hints獲取根域名服務器的地址(Root hints包含了互聯網DNS根服務器的地址信息);
  • 獲取了根域名服務器地址後Local DNS向根域名服務器發起DNS解析請求,根域名服務器返回com頂級域名服務器地址;
  • 隨後Local DNS向com域名服務器發起解析請求,並得到taobao.com二級域名服務器的地址;
  • Local DNS向taobao.com二級域名服務器發起解析請求,並最終獲得了www.taobao.com的IP地址信息;
  • Local DNS將遞歸查詢獲得的IP地址信息緩存並返回給客戶端;

Local DNS服務器包含緩存模塊,在實際域名解析過程中Local DNS服務器會首先查詢緩存,緩存命中且解析結果TTL未過期的情況下直接返回,否則才啟動遞歸查詢的流程。


傳統的域名解析面臨的問題

瞭解了域名解析的基本概念和整體流程,我們再一起來探究一下傳統域名解析存在的一系列問題。

域名劫持

域名劫持一直是困擾許多開發者的問題之一,其表現即域名A應該返回的DNS解析結果IP1被惡意替換為了IP2,導致A的訪問失敗或訪問了一個不安全的站點。下面我們一起看看幾種常見的域名劫持的場景。

一種可能的域名劫持方式即黑客侵入了寬帶路由器並對終端用戶的Local DNS進行篡改,指向黑客自己偽造的Local DNS,進而通過控制Local DNS的邏輯返回錯誤的IP信息進行域名劫持。另一方面,由於DNS解析主要是基於UDP協議,除了上述攻擊行為外,攻擊者還可以監聽終端用戶的域名解析請求,並在Local DNS返回正確結果之前將偽造的DNS解析響應傳遞給終端用戶,進而控制終端用戶的域名訪問行為。

a23608ec76095d6bed4b7243db5468edc9681ae1

上述攻擊行為的影響面相對比較有限,另一種我們最常碰到的域名劫持現象是緩存汙染。我們知道在接收到域名解析請求時,Local DNS首先會查找緩存,如果緩存命中就會直接返回緩存結果,不再進行遞歸DNS查詢。這時候如果Local DNS針對部分域名的緩存進行更改,比如將緩存結果指向第三方的廣告頁,就會導致用戶的訪問請求被引導到這些廣告頁地址上。

0e34b8f0d2470234749829ed3db428ec1b432cbd

對比第一種攻擊,這類緩存汙染往往能帶來更明顯的群體傷害,比如某個省份某個運營商的用戶群可能因為該地區Local DNS的緩存汙染而導致訪問服務異常。這類緩存汙染行為往往是間歇性、局部性發生的,沒有明顯的規律,導致開發者很難對其進行量化、評估、預防。

有的同學可能會問,“我使用了HTTPS,是否就可以避免域名劫持的問題”,答案是否定的。域名解析環節發生在網絡加密請求交互之前,試想一下,如果客戶端還沒有服務端的確切地址信息,我們又如何知道應該和誰進行加密的握手協商與通信呢?

調度不精準

除了域名劫持問題,基於傳統Local DNS的域名解析還會帶來域名調度精準性的問題。對於類似CDN域名訪問這類需要按地域、運營商進行智能解析調度的場景,精準調度的訴求是十分強烈的。

關於調度不精準的原因,我們主要可以從兩個方面來探究一下。第一個常見的問題即解析轉發。

caea530e4b496790e5d86fd8476cb14ca7fe4767

部分Local DNS供應商為了降低運營成本,會將請求到自己節點的域名解析請求轉發給其他供應商的Local DNS節點,如上圖所示。假如用戶請求解析一個CDN域名cdn.aliyun.com,用戶分配到的Local DNS A為了節省成本,把該次請求轉發給了另一運營商的Local DNS B,權威DNS在進行域名解析時會根據Local DNS的IP信息進行智能調度,即權威DNS會根據Local DNS B的IP78.29.29.1進行調度,分配與78.29.29.1相同運營商並且地理位置最近的CDN節點78.29.29.2,然而這個CDN節點對於終端135.35.35.1而言並不是最優的CDN節點,他們分屬不同的運營商,並且地理位置上可能相隔很遠。這類解析轉發行為會嚴重影響域名解析的精準性並對用戶業務訪問延遲帶來影響。

除了解析轉發對調度精準性帶來的影響外,Local DNS的佈署情況同樣影響著域名智能解析的精準性。

8c0b59d3eddfd9452a77c6bb7e394953f6c605f8

如上圖所示,部分運營商Local DNS的布點受成本因素制約分佈並不均勻,比如在東部地區部署比較密集,但在西部地區部署比較稀疏。這時候當一位西藏的用戶準備訪問CDN節點時,我們預期他應該會被調度到西藏的CDN節點A上以實現就近接入和訪問加速。但由於Local DNS的資源有限,西部地區的終端用戶被統一調度到青海的Local DNS B上,這時候權威DNS根據Local DNS B的IP進行CDN域名的智能解析,並將青海的CDN節點B返回給西藏用戶,導致用戶的網絡訪問延遲上升。另一種我們實際發現的情況是Local DNS的分配甚至並非遵循就近原則,比如有實際案例顯示西藏的用戶甚至被分配了北京的Local DNS節點C,導致西藏的用戶在進行CDN資源訪問時被調度到了北京的CDN節點C上,類似的由於調度精度的缺失帶來的訪問體驗的影響是非常嚴重的。

解析生效滯後

部分業務場景下開發者對域名解析結果變更的生效時間非常敏感(這部分變更操作是開發者在權威DNS上完成的),比如當業務服務器受到攻擊時,我們需要最快速地將業務IP切換到另一組集群上,這樣的訴求在傳統域名解析體系下是無法完成的。

6cf97722b3205f644ca6b713c80821e9b394afc8

Local DNS的部署是由各個地區的各個運營商獨立部署的,因此各個Local DNS的服務質量參差不齊。在對域名解析緩存的處理上,各個獨立節點的實現策略也有區別,比如部分節點為了節省開支忽略了域名解析結果的TTL時間限制,導致用戶在權威DNS變更的解析結果全網生效的週期非常漫長(我們已知的最長生效時間甚至高達48小時)。這類延遲生效可能直接導致用戶業務訪問的異常。

延遲大

DNS首次查詢或緩存過期後的查詢,需要遞歸遍歷多個DNS服務器以獲取最終的解析結果,這增加了網絡請求的前置延時時間。特別是在移動互聯網場景下,移動網絡質量參差不齊,弱網環境的RTT時間可能高達數百毫秒,對於一次普通的業務請求而言,上述延時是非常沉重的負擔。另一方面,弱網環境下的解析超時、解析失敗等現象屢見不鮮,如何合理優化DNS解析對於整體網絡訪問質量的提升至關重要。


HTTPDNS

通過上文的介紹,聰明的讀者應該可以發現,傳統域名解析面臨的諸多問題與挑戰本質根源在於Local DNS的服務質量不可控,如果有一個更安全、穩定、高效的遞歸DNS服務幫助我們代理了域名解析的過程,上述問題看起來就可以徹底地得到解決。

HTTPDNS在這樣的背景下應運而生。我們一起來看看HTTPDNS的基本概念以及它是如何解決傳統DNS解析面臨的問題的。

防域名劫持

HTTPDNS使用HTTP協議進行域名解析,代替現有基於UDP的DNS協議,域名解析請求直接發送到HTTPDNS服務端,從而繞過運營商的Local DNS,如下圖所示。

6c4402618b6f9580255ba88ea28fa518947629ae

HTTPDNS代替了傳統的LocalDNS完成遞歸解析的功能,基於HTTP協議的設計可以適用於幾乎所有的網絡環境,同時保留了鑑權、HTTPS等更高安全性的擴展能力,避免惡意攻擊劫持行為。另一方面,商業化的HTTPDNS服務( https://www.aliyun.com/product/httpdns )緩存管理有嚴格的SLA保障,避免了類似Local DNS的緩存汙染的問題。

精準調度

傳統域名解析的調度精準性問題,本質根源在於Local DNS的部署和分配機制上。由於碎片化的管理方式,這些環節的服務質量同樣很難得到保障。HTTPDNS在遞歸解析實現上優化了與權威DNS的交互,通過edns-client-subnet協議( https://datatracker.ietf.org/doc/rfc7871 )將終端用戶的IP信息直接交付給權威DNS,這樣權威DNS就可以忽略Local DNS IP信息,根據終端用戶的IP信息進行精準調度,避免Local DNS的座標干擾(當然上述精準調度方案的前提是權威DNS需要支持edns-client-subnet,可喜的是當前主流的權威DNS服務都已支持該協議)。精準調度的流程示例如下。

ab293d37d4e472dd0ee2facf85e2929ce11a177a

實時生效

在域名解析生效週期方面,HTTPDNS也有著傳統域名解析體系所無法具備的能力。前文中我們提到由於各個地區的Local DNS是獨立維護的,服務質量參差不齊,緩存實現不一,因此導致的解析變更全網生效滯後的問題,在商業化的HTTPDNS服務上就不會存在(HTTPDNS嚴格遵循DNS TTL限制進行緩存更新)。另一方面,即便我們假設Local DNS嚴格遵循域名TTL時間進行緩存管理(這裡我們假設開發者配置的域名TTL時間為5min),當開發者業務受到攻擊並需要快速進行切換時,Local DNS也會遵循域名TTL,在持續5min的時間段內返回舊IP信息,這5min的業務影響對於中大型企業而言是一個不小的損失(對於電商類的大型企業,5min的訪問異常可能意味著幾百萬的交易額下跌)。以阿里雲HTTPDNS服務( https://www.aliyun.com/product/httpdns )為例,HTTPDNS在快速生效方面有專有的方案,配合阿里雲的權威DNS服務雲解析( https://wanwang.aliyun.com/domain/dns ),用戶在權威DNS變更的解析結果將快速同步給HTTPDNS,覆蓋原有的緩存記錄,幫助用戶實現秒級的域名解析切換。

在DNS解析延遲方面,由於HTTPDNS基於HTTP協議,而HTTP基於TCP協議,對比傳統的UDP傳輸多了一些冗餘的握手環節,因此從原理上而言網絡請求方面的開銷並沒有降低。但在實際使用過程中,我們可以通過端上的策略來實現一個零延遲DNS解析的方案。接下來我們一起來看看HTTPDNS服務在移動端的最佳實踐方案。實時生效的流程如下圖所示。

ca22e0de56ff0cdb0340bf3c0744b0fd80c1924a


域名解析最佳實踐

通過HTTPDNS服務,我們可以實現包括防止域名劫持、精準調度、實時解析生效等功能,但在DNS解析開銷的優化上,我們需要客戶端一起配合。

預解析

絕大多數的APP在應用初始化階段都有一個啟動期,我們可以在這個啟動期做一些preflight工作,即在初始化階段我們可以針對業務的熱點域名在後臺發起異步的HTTPDNS解析請求。這部分預解析結果在後續的業務請求中可以直接使用,進而消除首次業務請求的DNS解析開銷,提升APP首頁的加載速度。

在客戶端實際使用HTTPDNS的過程中,有一個大家需要關注的點。標準的Web服務器(以Nginx為例)一般會將HTTP請求頭中的Host頭的值作為請求的域名信息進行處理(取決於服務端的配置,但一般情況都如此)。比如當我們通過標準的網絡庫訪問www.aliyun.com/index.html這個地址時,發出的網絡請求一般是這樣的:

> GET /index.html HTTP/1.1
> Host: www.aliyun.com
> User-Agent: curl/7.43.0
> Accept: /

使用HTTPDNS後,我們需要將HTTP請求URL中的Host域(注意這裡的Host域指的是URL中的Host字段,而非HTTP請求頭中的Host頭)替換為HTTPDNS解析獲得的IP,這時由於標準的網絡庫會將URL中的Host域賦值給HTTP請求頭中的Host頭,發出的網絡請求如下:

> GET /index.html HTTP/1.1
> Host: 140.205.63.8
> User-Agent: curl/7.43.0
> Accept: /

上述Host信息將導致服務端的解析異常(服務端配置的是域名信息,而非IP信息,試想一下如果我們的服務端服務了兩個域名www.a.comwww.b.com,這時候它接收到一個140.205.63.8/index.html請求,它如何判斷應該返回a的首頁還是b的首頁信息呢?)。為了解決這個問題,我們需要主動設置HTTP請求Host頭的值,以Android的官方網絡庫HttpURLConnection為例:

String originalUrl = “http://www.aliyun.com/index.html";
URL url = new URL(originalURL);
String originalHost = url.getHost();
// 同步獲取IP
String ip = httpdns.getIpByHost(originalHost);
HttpURLConnection conn;
if (ip != null) {
// 通過HTTPDNS獲取IP成功,進行URL替換和Host頭設置
url = new URL(originalUrl.replaceFirst(originalHost, ip));
conn = (HttpURLConnection) url.openConnection();
// 設置請求Host頭
conn.setRequestProperty("Host", originHost);

} else {

conn = (HttpURLConnection) url.openConnection();

}

主動設置Host頭後,發出的網絡請求就與未替換URL的網絡請求一模一樣了。

智能緩存

通過預解析獲取的IP有一定的TTL有效時間,我們需要合理地緩存下來進行管理。操作系統本身的DNS緩存粒度比較粗,在客戶端我們可以應用更細粒度的緩存管理來提升解析效率。比如在不同的網絡運營商環境下,對CDN域名的解析結果會發生變化,當我們使用電信WIFI時,DNS解析會返回就近的電信CDN節點IP,當我們使用聯通3G時,DNS解析會返回就近的聯通CDN節點IP,針對不同運營商的解析結果緩存可以確保我們在網絡切換時能夠快速地進行網絡請求,減免DNS解析帶來的額外開銷。甚至更激進的,我們可以做本地的持久化緩存,當下一次APP啟動時直接讀取緩存用於網絡訪問,以提升首屏加載的速度。

懶加載

懶加載策略的實施可以讓我們真正實現DNS的零延遲解析。所謂懶加載策略,核心的實現思路如下:

  • 業務層的域名解析請求只和緩存進行交互,不實際發生網絡解析請求。如果緩存中存在記錄,不論過期與否,直接返回業務層緩存中的記錄;
  • 如果緩存中的記錄已過期,後臺發起異步網絡請求進行HTTPDNS解析;

有的同學可能會有疑惑,返回一個過期的IP豈不是違背了TTL設計的初衷?的確,上述行為並不符合標準的規範,但是當我們重新審視一下自己的業務特點,上述的變通策略就顯得非常有意義了。絕大多數的業務場景下我們的後端IP是固定的若干個節點,因此連續的解析結果在環境不變的情況下有很大概率是保持一致的,這在一定程度上保證了懶加載的可行性。另一方面,即便我們由於返回過期IP導致了訪問異常的行為,後臺很快會進行新IP的異步解析和緩存更新,業務本身可以進行重試和快速的復原,因此上述行為帶來的影響也是非常小的。再進一步,TTL過期的IP的服務在絕大多數場景下還是持續的,可預期的,因此懶加載可能帶來的業務風險是完全可控的。通過0.1%場景下的業務瞬時訪問風險來換取99.9%場景下的用戶體驗提升,這筆買賣還是非常划算的(當然懶加載的使用有賴於合適的業務場景,如果你的業務場景下IP變化頻繁,並且TTL過期的IP訪問不可用,是不建議應用懶加載策略的)。

下圖描繪了預解析+懶加載的實現框架:

2cd2f32b7dfd7f1b277cf06146a158a9d40d98c4

綜上可以看到,當我們需要實現零延遲解析的效果時,在客戶端還是有比較多的工作需要做的。商業化的HTTPDNS服務( https://www.aliyun.com/product/httpdns )提供了終端SDK方便開發者進行終端上的集成和使用,推薦大家可以嘗試一下。

 

Leave a Reply

Your email address will not be published. Required fields are marked *