DNS是域名系統(DomainNameSystem)的縮寫,該系統用於命名組織到域層次結構中的計算機和網絡服務。域名是由圓點分開一串單詞或縮寫組成的,每個域名都對應一個唯一的IP地址,在Internet上域名與IP地址之間是一一對應的,DNS就是進行域名解析的服務器。DNS命名用於Internet等TCP/IP網絡中,經過用戶友好的名稱查找計算機和服務。DNS是因特網的一項核心服務,它做爲能夠將域名和IP地址相互映射的一個分佈式數據庫。前端
當咱們發起一個網絡請求,首先要通過DNS服務,將域名轉化爲IP地址,而後經過IP地址創建鏈接。DNS的工做流程以下圖所示。java
那麼,傳統的Local DNS有什麼缺陷呢。就目前端上而言,主要有幾個問題:android
域名劫持是互聯網攻擊的一種方式,經過攻擊域名解析服務器(DNS),或僞造域名解析服務器(DNS)的方法,把目標網站域名解析到錯誤的地址從而實現用戶沒法訪問目標網站的目的。git
DNS劫持示例圖以下:github
DNS劫持會致使端上網絡鏈接失敗或者DNS解析失敗,嚴重影響用戶使用,在以前,端上採用備用域名的機制去解決這個問題,可是效果並非很好。數據庫
DNS解析分爲遞歸查詢和迭代查詢兩種。緩存
遞歸查詢:若是主機所詢問的本地域名服務器不知道被查詢域名的 IP 地址,那麼本地域名服務器就以 DNS 客戶的身份,向其餘根域名服務器繼續發出查詢請求報文,而不是讓該主機本身進行下一步的查詢。安全
迭代查詢:當根域名服務器收到本地域名服務器發出的迭代查詢請求報文時,要麼給出所要查詢的 IP 地址,要麼告訴本地域名服務器:你下一步應當向哪個域名服務器進行查詢。而後讓本地域名服務器進行後續的查詢,而不是替本地域名服務器進行後續的查詢。服務器
因爲遞歸模式會致使DNS服務器流量很大,因此如今大多數採用迭代模式。微信
因爲端上網絡環境的複雜性已經DNS解析的流程也較爲複雜,有些場景下DNS解析時間高達幾百毫秒,對於一次網絡請求來講,是至關緩慢的。
HTTPDNS 是面向移動開發者推出的一款域名解析產品,具備域名防劫持、精準調度等特性。
目前來講,騰訊和阿里都有本身的HTTPDNS解決方案。HTTPDNS有如下特性:
在阿里雲HTTPDNS文檔中,有所謂的「最佳方案」,包含SNI場景、OkHttp場景等等,可是,這對於咱們來講,接入量仍是偏大,且覆蓋的場景依然有限。若是咱們想很簡單的接入,且覆蓋全量Java場景,如何作呢。首先,咱們看一下Android側DNS解析的調用流程,以API 28爲例。
InetAddress#getAllByName()
->Inet6AddressImpl#lookupHostByName()
->Libcore.os.android_getaddrinfo()
複製代碼
而Libcore代碼以下Libcore源碼:
public final class Libcore {
private Libcore() { }
/** * Direct access to syscalls. Code should strongly prefer using {@link #os} * unless it has a strong reason to bypass the helpful checks/guards that it * provides. */
public static Os rawOs = new Linux();
/** * Access to syscalls with helpful checks/guards. */
public static Os os = new BlockGuardOs(rawOs);
}
複製代碼
經過簡單的代碼跟蹤能夠發現,他們實現Os這個接口 ,接口?對哦,動態代理。是的,咱們能夠經過動態代理的方式,去hook掉Java層發起的DNS解析請求。
上面的代碼,已經開源在KIDDNS-Android
Android P hide API的問題相信困擾了很多同窗,那麼下期,我們一塊兒瞭解下如何在Android P上使用hide API!
歡迎你們關注個人我的微信公衆號《Andorid小茶館》!主要內容是移動端,主要是Android方向,技術交流,開源分析,架構淺談。