本文檔只針對WkWebView情境下如何使用HTTPDNS解析出的IP,關於HTTPDNS本身的解析服務,請先查看iOS SDK接入手冊。
1. 前言
通過iOS端Native情境使用HTTPDNS這篇文檔,我們已經知道如何在iOS平台上的Native情境中如何使用HTTPDNS,實現防劫持、調度精準、解析及時生效的能力。
而iOS上還有一個頻繁發生網路請求的情境:WkWebView。WKWebView是WebKit架構提供的一個現代Web視圖,用於在iOS應用中顯示網頁內容。它替代了舊的UIWebView,提供了更好的效能、更多的功能和更高的安全性。我們期望,在WkWebView載入網頁的時候,也能使用HTTPDNS,提升網路安全性與網路效能。
2. 技術現狀
隨著iOS系統的不斷髮展,WKWebView整合HTTPDNS的技術方案也在持續演化:
iOS 17.0之前:Apple官方並未在WkWebView上開放DNS解析相關的hook介面,也並未直接開放自訂網路請求實現的介面,需要通過hook 私人API攔截流量的複雜方案實現。
iOS 17.0及以後:Apple引入了ProxyConfiguration相關API,為WKWebView提供了官方的代理配置能力,可以通過“接近完美”的方式攔截所有網路請求,使得優雅整合HTTPDNS成為可能。
根據Apple官方統計資料(截至2025年6月4日),在系統版本分布上,iOS 17+已經佔全部iPhone裝置的85%以上,且在持續增長中。因此,考慮到HTTPDNS為WkWebView情境帶來的是防劫持、調度精準、解析及時生效等非功能性提升,建議直接通過本方案接入HTTPDNS,覆蓋大部分客戶,且舊版本系統使用者,也會在後續的陸續版本升級中,逐漸享受這個能力。
3. 推薦方案:iOS 17+基於本地代理的方案
3.1 方案概述
iOS 17.0引入了ProxyConfiguration相關API,允許應用為WKWebView配置本地Proxy 伺服器。通過這種方式,我們可以在本地啟動一個Proxy 伺服器,攔截WKWebView的所有網路請求,在代理層面實現HTTPDNS網域名稱解析,然後將請求轉寄到真實伺服器。

相比傳統技術方案,本地代理方案具有以下顯著優勢:
穩定性:基於iOS 17+官方API,無需依賴私人API或混淆技術,穩定性和相容性最佳。
適用性:對WebView完全透明,無需處理cookie、重新導向、CORS等複雜細節。支援HTTP/HTTPS/WebSocket等所有協議,覆蓋面更廣。
安全性:本地代理獨立在App沙箱內,並未向外界暴露,也無可利用的操作空間;
高效能:純本地實現,所有網路資料只多了一次記憶體級拷貝,對於用戶端來說是可以忽略不計的消耗;
易維護:實現邏輯清晰,維護成本相對較低。
3.2 接入參考
考慮建立本地代理服務、解析HTTP請求、基於HTTPDNS解析結果建立串連、資料轉寄等步驟有一定實現成本,我們在github上開源了一份實現:開源地址,並打包為SDK發布。您可以結合業務實際情況,按需調整這份實現,使得更符合您的業務需要。
3.2.1 Cocoapods整合
在Podfile中添加EMASLocalProxy依賴:
source 'https://github.com/aliyun/aliyun-specs.git'
target 'yourAppTarget' do
use_framework!
pod 'AlicloudHTTPDNS', 'x.x.x'
pod 'EMASLocalProxy', 'x.x.x'
end3.2.2 使用樣本
整合後,在WkWebView初始化時進行如下配置:
#import <EMASLocalProxy/EMASLocalProxy.h>
#import <AlicloudHttpDNS/AlicloudHttpDNS.h>
// 建立 WKWebViewConfiguration
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 配置DNS解析器
[EMASLocalHttpProxy setDNSResolverBlock:^NSArray<NSString *> *(NSString *hostname) {
// 擷取HTTPDNS服務執行個體
HttpDnsService *httpdns = [HttpDnsService sharedInstance];
HttpdnsResult *result = [httpdns resolveHostSyncNonBlocking:hostname byIpType:HttpdnsQueryIPTypeBoth];
if (result && (result.hasIpv4Address || result.hasIpv6Address)) {
NSMutableArray<NSString *> *allIPs = [NSMutableArray array];
if (result.hasIpv4Address) {
[allIPs addObjectsFromArray:result.ips];
}
if (result.hasIpv6Address) {
[allIPs addObjectsFromArray:result.ipv6s];
}
NSLog(@"HTTPDNS解析成功,網域名稱: %@, IP: %@", hostname, allIPs);
return allIPs;
}
NSLog(@"HTTPDNS解析失敗,網域名稱: %@", hostname);
return nil;
}];
// 設定記錄層級
[EMASLocalHttpProxy setLogLevel:EMASLocalHttpProxyLogLevelDebug];
// 配置WebView代理
BOOL proxyConfigured = [EMASLocalHttpProxy installIntoWkWebViewConfiguration:config];
if (proxyConfigured) {
NSLog(@"WebView代理配置成功");
} else {
NSLog(@"WebView代理配置失敗,使用系統網路");
}
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];在上線前,您需要閱讀和理解代碼實現邏輯,並進行充分測試,確保完美相容。
3.3 實現細節
EMASLocalProxy的完整實現基於iOS 17.0+的ProxyConfigurations API和Network.framework,提供高效能的本地代理服務。詳細的技術實現可參考開原始碼:
GitHub源碼地址: https://github.com/aliyun/alicloud-ios-sdk-emascurl/tree/master/EMASLocalProxy
核心技術要點:
使用Network framework建立本地HTTPProxy 伺服器
通過CONNECT隧道處理HTTP請求
實現用戶端與目標伺服器間的透明資料轉寄
整合自訂DNS解析器支援HTTPDNS
提供完善的降級和錯誤處理機制
3.4 降級及最佳化方案
EMASLocalHttpProxy在設計之初即充分考慮了多種異常情境,內建多層防護與自動降級(Fallback)機制,旨在提供高效能本地代理能力的同時,保障系統的高可用性與最終網路請求的可達性,即便在組件故障或外部依賴異常的情況下,也能最大程度減少對使用者體驗的影響。
以下是不同的異常情境及應對:
情境 | 觸發條件 | 降級或保護措施 | 最終效果 |
代理啟動 | 連接埠衝突 | 自動重試隨機連接埠 | 提高啟動成功率 |
啟動阻塞 | 啟動逾時退出 | 避免應用卡死 | |
代理運行 |
| 標記服務為“未運行” | 觸發後續降級策略 |
外部存取嘗試 | 僅監聽 127.0.0.1 | 拒絕區域網路訪問,保障安全 | |
WebView 配置 | 服務未運行 | 使用非持久化 | 回退到系統預設網路 |
系統版本低於iOS17 | 跳過代理配置 | 與系統預設行為保持一致 | |
DNS 解析 | 自訂解析器拋異常 | 捕獲異常,使用原始網域名稱,走localDNS解析 | 避免因解析失敗影響串連 |
網路連接 | 目標伺服器串連失敗 | 返回 | 提供標準化故障反饋 |
通過以上多層設計,HttpdnsLocalHttpProxy 能夠在複雜多變的網路環境中實現可靠運行。其完備的降級機制確保即使部分組件失效,仍能保障請求通路不中斷。
4. 全域攔截NSURLProtocol的方案
本方案是最早在iOS WebView上適配HTTPDNS的可行方案,它接入門檻實際上很高,效果也不好,只不過早年iOS並未提供其他選擇,因此流傳下來。它的原理是,基於NSURLProtocol可攔截iOS系統上基於上層網路程式庫NSURLConnection/NSURLSession發出的網路請求,WkWebView發出的請求同樣包含在內,攔截請求後,再使用HTTPDNS做網域名稱解析和後續處理。步驟如下:
通過以下介面註冊自訂
NSURLProtocol,用於攔截WkWebView上層網路請求,並建立新的網路請求接管資料發送、接收、重新導向等處理邏輯,將結果反饋給原始請求。[NSURLProtocol registerClass:[HttpDnsNSURLProtocolImpl class]];自訂
NSURLProtocol處理過程概述:在
canInitWithRequest中過濾需要做HTTPDNS網域名稱解析的請求。請求攔截後,做HTTPDNS網域名稱解析。
解析完成後,同普通請求一樣,替換URL.host欄位,替換HTTP Header Host域,並接管該請求的資料發送、接收、重新導向等處理。
通過
NSURLProtocol的介面,將請求處理結果反饋到WebView原始請求。
自訂
NSURLProtocol的實現邏輯可參考我們提供的demo中的 HttpDnsNSURLProtocolImpl.m。
由於Apple官方並未公開太多協議細節,上述方案在生產環境需要結合業務情況,自行處理cookie、重新導向等細節問題,才具備可行性。非特殊情況,不建議使用此方案。
5. 方案總結與對比
本文檔介紹了在iOS端WKWebView情境下整合HTTPDNS的兩種主要技術方案:基於iOS 17+的本地代理方案和全域攔截NSURLProtocol的方案。
每種方案都有其特定的適用情境、優缺點和實現複雜度。為協助您快速決策,下表對這兩種方案進行了橫向對比:
維度 / 方案 | 本地代理(ProxyConfiguration)(iOS 17 +) | 全域 NSURLProtocol 攔截 |
官方支援度 | Apple 在 iOS 17 引入的正式 API,完全公開、長期可用 | 使用公開 NSURLProtocol API,但在 WKWebView 內部細節缺乏官方文檔 |
生效版本 | iOS 17 及以上,iOS 17以下版本只是代理不生效,無其他副作用 | iOS 11 及以上 |
協議覆蓋 | HTTP / HTTPS / WebSocket / HTTP2(透明轉寄原始流量) | 僅限 NSURLSession / NSURLConnection 可處理的協議 |
實現複雜度 | 中:需實現本地代理、連接埠管理、雙向轉寄 | 中:需處理請求複寫、線程與緩衝互動 |
對業務代碼侵入 | 低:WKWebView 只需配置代理 | 中:全域註冊 NSURLProtocol,可能影響現有 NSURLSession 邏輯 |
Cookie / 緩衝 / CORS | 代理層透明,不額外處理 | 開發人員需自我維護,容易遺漏邊緣情境 |
維護成本 | 低:依賴官方 API,版本升級風險小 | 中:系統 API 穩定,但需關注WKWebView 內部行為變化 |
失效降級策略 | 支援:代理故障可回退系統網路 | 需自行實現 |
推薦情境 | 主推方案:目標使用者 > iOS 17;對安全與相容要求高 | 輕量改造、快速驗證;對複雜請求相容性要求不高 |
綜合考慮穩定性、開發維護成本和未來趨勢,我們強烈推薦使用基於iOS 17+的本地代理方案。
隨著iOS 17+系統版本的高速普及,該方案能以最低的成本為絕大多數使用者帶來穩定、可靠的HTTPDNS服務,有效解決網域名稱劫持問題,並提升網路效能。其優雅的實現方式和官方支援,確保了方案的長期可行性。對於低於iOS 17的系統版本,採取平滑降級策略,即直接使用系統預設的網路請求,待使用者升級系統後自動享受HTTPDNS帶來的優勢。
其他方案由於其固有的複雜性和不確定性,僅建議在有特殊需求且具備深厚技術儲備的團隊,經過充分評估和測試後謹慎採用。