iOS防DNS汙染方案調研—HTTPS(非SNI)業務場景
1. 背景說明
本文主要介紹 HTTPS(含SNI) 業務場景下在 iOS 端實現 “IP直連” 的通用解決方案。
1.1 HTTPS
傳送 HTTPS 請求首先要進行 SSL/TLS 握手,握手過程大致如下:
- 客戶端發起握手請求,攜帶隨機數、支援演算法列表等引數。
- 服務端收到請求,選擇合適的演算法,下發公鑰證照和隨機數。
- 客戶端對服務端證照進行校驗,併傳送隨機數資訊,該資訊使用公鑰加密。
- 服務端通過私鑰獲取隨機數資訊。
- 雙方根據以上互動的資訊生成session ticket,用作該連線後續資料傳輸的加密金鑰。
上述過程中,和“IP直連”有關的是第3步,客戶端需要驗證服務端下發的證照,驗證過程有以下兩個要點:
- 客戶端用本地儲存的根證照解開證照鏈,確認服務端下發的證照是由可信任的機構頒發的。
- 客戶端需要檢查證照的 domain 域和擴充套件域,看是否包含本次請求的 host。
如果上述兩點都校驗通過,就證明當前的服務端是可信任的,否則就是不可信任,應當中斷當前連線。
當客戶端使用“IP直連”解析域名時,請求URL中的host會被替換成解析出來的IP,所以在證照驗證的第2步,會出現domain不匹配的情況,導致SSL/TLS握手不成功。
1.2 SNI
SNI(Server Name Indication)是為了解決一個伺服器使用多個域名和證照的SSL/TLS擴充套件。它的工作原理如下:
- 在連線到伺服器建立SSL連結之前先傳送要訪問站點的域名(Hostname)。
- 伺服器根據這個域名返回一個合適的證照。
目前,大多數作業系統和瀏覽器都已經很好地支援SNI擴充套件,OpenSSL 0.9.8也已經內建這一功能。
上述過程中,當客戶端使用“IP直連”時,請求URL中的host會被替換成解析出來的IP,導致伺服器獲取到的域名為解析後的IP,無法找到匹配的證照,只能返回預設的證照或者不返回,所以會出現SSL/TLS握手不成功的錯誤。
比如當你需要通過 HTTPS 訪問 CDN 資源時,CDN 的站點往往服務了很多的域名,所以需要通過SNI指定具體的域名證照進行通訊。
2. HTTPS場景(非SNI)解決方案
針對“domain不匹配”問題,可以採用如下方案解決:hook 證照校驗過程中第2步,將IP直接替換成原來的域名,再執行證照驗證。該方案與使用“自定義證照”進行 HTTPS 請求的校驗方案一樣。
【注意】基於該方案發起網路請求,若報出SSL校驗錯誤
,比如 iOS 系統報錯kCFStreamErrorDomainSSL, -9813; The certificate for this server is invalid
,Android系統報錯System.err: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
,請檢查應用場景是否為SNI(單IP多HTTPS域名)。
下面分別列出 iOS 平臺的示例程式碼。
iOS示例
此示例針對NSURLSession/NSURLConnection介面。
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
forDomain:(NSString *)domain
{
/*
* 建立證照校驗策略
*/
NSMutableArray *policies = [NSMutableArray array];
if (domain) {
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
} else {
[policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
}
/*
* 繫結校驗策略到服務端的證照上
*/
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
/*
* 評估當前serverTrust是否可信任,
* 官方建議在result = kSecTrustResultUnspecified 或 kSecTrustResultProceed
* 的情況下serverTrust可以被驗證通過,https://developer.apple.com/library/ios/technotes/tn2232/_index.html
* 關於SecTrustResultType的詳細資訊請參考SecTrust.h
*/
SecTrustResultType result;
SecTrustEvaluate(serverTrust, &result);
return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
}
/*
* NSURLConnection
*/
- (void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if (!challenge) {
return;
}
/*
* URL裡面的host在使用“IP直連”的情況下被設定成了IP,此處從HTTP Header中獲取真實域名
*/
NSString* host = [[self.request allHTTPHeaderFields] objectForKey:@"host"];
if (!host) {
host = self.request.URL.host;
}
/*
* 判斷challenge的身份驗證方法是否是NSURLAuthenticationMethodServerTrust(HTTPS模式下會進行該身份驗證流程),
* 在沒有配置身份驗證方法的情況下進行預設的網路請求流程。
*/
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
if ([self evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) {
/*
* 驗證完以後,需要構造一個NSURLCredential傳送給發起方
*/
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
/*
* 驗證失敗,進入預設處理流程
*/
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
} else {
/*
* 對於其他驗證方法直接進行處理流程
*/
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/*
* NSURLSession
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler
{
if (!challenge) {
return;
}
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
NSURLCredential *credential = nil;
/*
* 獲取原始域名資訊。
*/
NSString* host = [[self.request allHTTPHeaderFields] objectForKey:@"host"];
if (!host) {
host = self.request.URL.host;
}
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([self evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) {
disposition = NSURLSessionAuthChallengeUseCredential;
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
// 對於其他的challenges直接使用預設的驗證方案
completionHandler(disposition,credential);
}
需要修改HOST的場景總結
那麼什麼時候需要修改Host?
答案是所有情況都需要設定 HOST:做網路請求時,採用 IP 直連的方案會遇到 HOST 欄位被改為 IP 的問題,所以都需要手動地配置 HOST 欄位。
場景 | HTTP | HTTPS(非SNI) | HTTPS(SNI) |
---|---|---|---|
如何設定 | 改Host | 改Host,在移動端我們自己校驗,直接返回YES | 改HOST,而且需要做SNI適配。 |
雖然 IP 直接連的方案,導致的結果是 HOST 欄位被改為了IP,所以需要手動修改HOST。但是服務端唯一的根據是SNI欄位。下面就介紹下針對 SNI 場景的方案:
3. HTTPS(SNI)場景方案
3.1 iOS SNI場景
SNI(單IP多HTTPS證照)場景下,iOS上層網路庫NSURLConnection/NSURLSession
沒有提供介面進行SNI欄位
的配置,因此需要Socket層級的底層網路庫例如CFNetwork
,來實現IP直連網路請求
適配方案。而基於CFNetwork的解決方案需要開發者考慮資料的收發、重定向、解碼、快取等問題(CFNetwork是非常底層的網路實現),希望開發者合理評估該場景的使用風險。
可參考:
具體的實現方案可以參考: 《防 DNS 汙染方案調研—– SNI 場景》
相關文章
- iOS防DNS汙染方案調研—WebView業務場景iOSDNSWebView
- iOS防DNS汙染方案調研—302等URL重定向業務場景iOSDNS
- DNS劫持 DNS汙染 介紹、dns 劫持 汙染DNS
- DNS劫持和DNS汙染DNS
- DNS劫持與DNS汙染是什麼意思、dns劫持和汙染DNS
- 調研------典型使用者及場景
- 如何防止DNS汙染?DNS
- dns汙染與dns劫持,瞭解dns汙染與dns劫持,網站安全不可疏忽DNS網站
- iOS自動化測試調研方案iOS
- 基於工控場景的DNS隧道檢測方案DNS
- iOS Out-Of-Memory 原理闡述及方案調研iOS
- 網站安全:dns汙染與dns劫持網站DNS
- 11、DNS隧道技術調研DNS
- 業務流程場景
- dns汙染是誰幹的,什麼是dns汙染,它和DNS劫持有什麼區別DNS
- 大話業務場景與解決方案-做任務
- 怎麼判斷dns汙染,怎麼判斷dns汙染,具體判斷方法DNS
- 【技術向】基於工控場景的DNS隧道攻擊方案DNS
- 元件化方案調研元件化
- 域名被牆、dns劫持汙染、都有什麼方法、防止域名被牆dns劫持汙染方法DNS
- 使用 CoreDNS 來應對 DNS 汙染DNS
- 資料庫技術方案與業務場景的深入融合資料庫
- 業務系統表格調研指令碼指令碼
- 高併發業務場景下的秒殺解決方案 (初探)
- 業務建模:CQRS應用場景
- rsync+inotify實現實時同步(小業務場景解決方案)
- 如何根據不同業務場景調節 HPA 擴縮容靈敏度
- iOS多執行緒調研iOS執行緒
- 所謂DNS汙染和劫持是什麼?DNS
- HTTPS 原理剖析與專案場景HTTP
- 基於業務場景下的圖片/檔案上傳方案總結
- 高CPU業務場景下的任務分發方案Gearman搭建一覽
- 前端圖片合併方案調研前端
- 求助,jmeter 壓測 ,業務場景測試JMeter
- 什麼業務場景適合使用Redis?Redis
- 不同業務場景使用不同的map
- 業務場景---Token無感重新整理
- 智慧安防的主要應用場景和資料採集標註解決方案 | 景聯文科技