全部產品
Search
文件中心

HTTPDNS:iOS端WebView情境使用HTTPDNS

更新時間:Dec 18, 2025

重要

本文檔只針對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網域名稱解析,然後將請求轉寄到真實伺服器。

image

相比傳統技術方案,本地代理方案具有以下顯著優勢:

  1. 穩定性:基於iOS 17+官方API,無需依賴私人API或混淆技術,穩定性和相容性最佳。

  2. 適用性:對WebView完全透明,無需處理cookie、重新導向、CORS等複雜細節。支援HTTP/HTTPS/WebSocket等所有協議,覆蓋面更廣。

  3. 安全性:本地代理獨立在App沙箱內,並未向外界暴露,也無可利用的操作空間;

  4. 高效能:純本地實現,所有網路資料只多了一次記憶體級拷貝,對於用戶端來說是可以忽略不計的消耗;

  5. 易維護:實現邏輯清晰,維護成本相對較低。

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'
end

3.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)機制,旨在提供高效能本地代理能力的同時,保障系統的高可用性與最終網路請求的可達性,即便在組件故障或外部依賴異常的情況下,也能最大程度減少對使用者體驗的影響。

以下是不同的異常情境及應對:

情境

觸發條件

降級或保護措施

最終效果

代理啟動

連接埠衝突

自動重試隨機連接埠

提高啟動成功率

啟動阻塞

啟動逾時退出

避免應用卡死

代理運行

nw_listener 崩潰

標記服務為“未運行”

觸發後續降級策略

外部存取嘗試

僅監聽 127.0.0.1

拒絕區域網路訪問,保障安全

WebView 配置

服務未運行

使用非持久化 WKWebsiteDataStore

回退到系統預設網路

系統版本低於iOS17

跳過代理配置

與系統預設行為保持一致

DNS 解析

自訂解析器拋異常

捕獲異常,使用原始網域名稱,走localDNS解析

避免因解析失敗影響串連

網路連接

目標伺服器串連失敗

返回 502 Bad Gateway 響應

提供標準化故障反饋

通過以上多層設計,HttpdnsLocalHttpProxy 能夠在複雜多變的網路環境中實現可靠運行。其完備的降級機制確保即使部分組件失效,仍能保障請求通路不中斷。

4. 全域攔截NSURLProtocol的方案

本方案是最早在iOS WebView上適配HTTPDNS的可行方案,它接入門檻實際上很高,效果也不好,只不過早年iOS並未提供其他選擇,因此流傳下來。它的原理是,基於NSURLProtocol可攔截iOS系統上基於上層網路程式庫NSURLConnection/NSURLSession發出的網路請求,WkWebView發出的請求同樣包含在內,攔截請求後,再使用HTTPDNS做網域名稱解析和後續處理。步驟如下:

  1. 通過以下介面註冊自訂NSURLProtocol,用於攔截WkWebView上層網路請求,並建立新的網路請求接管資料發送、接收、重新導向等處理邏輯,將結果反饋給原始請求。

    [NSURLProtocol registerClass:[HttpDnsNSURLProtocolImpl class]];
  2. 自訂NSURLProtocol處理過程概述:

    • canInitWithRequest中過濾需要做HTTPDNS網域名稱解析的請求。

    • 請求攔截後,做HTTPDNS網域名稱解析。

    • 解析完成後,同普通請求一樣,替換URL.host欄位,替換HTTP Header Host域,並接管該請求的資料發送、接收、重新導向等處理。

    • 通過NSURLProtocol的介面,將請求處理結果反饋到WebView原始請求。

  3. 自訂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帶來的優勢。

其他方案由於其固有的複雜性和不確定性,僅建議在有特殊需求且具備深厚技術儲備的團隊,經過充分評估和測試後謹慎採用。