tencent cloud

移动解析 HTTPDNS

产品简介
产品介绍
应用场景
产品优势
产品限制
购买指南
计费说明
欠费说明
快速入门
开通移动解析 HTTPDNS
接入移动解析 HTTPDNS
操作指南
添加域名
解析量统计说明
解析监控
API 文档
配置信息说明
HTTP 请求方式查询
AES、DES 加密解密说明
API 接入实践教程
SDK 文档
SDK 快速接入
IOS SDK 文档
Android SDK 文档
访问管理及协作
访问管理概述
访问管理策略示例
常见问题
HTTPDNS 政策
隐私协议
数据处理和安全协议

HTTPS(SNI)场景

PDF
聚焦模式
字号
最后更新时间: 2025-09-05 17:52:26

原理

SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的 SSL/TLS 扩展。工作原理如下:
在连接到服务器建立 SSL 连接之前先发送要访问站点的域名(Hostname)。
服务器根据这个域名返回一个合适的证书。
上述过程中,当客户端使用 HTTPDNS 解析域名时,请求 URL 中的 host 会被替换成 HTTPDNS 解析出来的 IP,导致服务器获取到的域名为解析后的 IP,无法找到匹配的证书,只能返回默认的证书或者不返回,所以会出现 SSL/TLS 握手不成功的错误。
由于 iOS 上层网络库 NSURLConnection/NSURLSession 没有提供接口进行 SNI 字段的配置,因此可以考虑使用 NSURLProtocol 拦截网络请求,然后使用 CFHTTPMessageRef 创建 NSInputStream 实例进行 Socket 通信,并设置其 kCFStreamSSLPeerName 的值。

方案描述

注意:
本文档提出了 SNI 场景下 HTTPDNS 集成的参考方案,示例代码非线上生产环境正式代码。在接入之前,我们建议您充分评估本文档内容,以确保方案的健壮性符合您的生产标准。
如果需要参考示例,您可以参考 MSDKDnsHttpMessageTools 的 源码,可根据业务需求进行修改或复用。
HTTPDNS iOS SDK 提供了 MSDKDnsHttpMessageTools。MSDKDnsHttpMessageTools 是 HTTPDNS iOS SDK 基于 NSURLProtocol 封装的 Protocol。MSDKDnsHttpMessageTools 继承了 NSURLProtocol,可以自动拦截 NSURLSession 中的请求。MSDKDnsHttpMessageTools 中调用了WGGetHostByName 方法,并自动将 IP 进行 URL 替换和 HOST 头设置,使用 MSDKDnsHttpMessageTools 您不用再进行域名替换。MSDKDnsHttpMessageTools 解决了自定义 NSURLProtocol 使用的 CFNetwork 库功能受限,扩展性差的问题。

代码示例

完整的示例代码在 Demo 的 SNIViewController.m 中。
// 注册拦截请求的 NSURLProtocol
[NSURLProtocol registerClass:[MSDKDnsHttpMessageTools class]];

// 需要设置 SNI 的 URL,比如 https://www.qq.com
NSString *originalUrl = @"your url";
NSURL *url = [NSURL URLWithString:originalUrl];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

// NSURLConnection 例子
self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[self.connection start];

// NSURLSession 例子
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSArray *protocolArray = @[ [MSDKDnsHttpMessageTools class] ];
configuration.protocolClasses = protocolArray;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
self.task = [session dataTaskWithRequest:request];
[self.task resume];

// AFNetworking 例子
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSArray *protocolArray = @[[MSDKDnsHttpMessageTools class]];
config.protocolClasses = protocolArray;
AFHTTPSessionManager* sessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config];
sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSURLSessionDataTask* task = [sessionManager dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
    NSLog(@"update upload progress %@", uploadProgress.description);
} downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
    NSLog(@"update download progress %@", downloadProgress.description);
} completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
    NSLog(@"request complete ==== response: %@ ===== error: %@", [NSString stringWithFormat:@"%@", responseObject], error);
}];
[task resume];

使用说明

需调用以下接口设置需要拦截域名或无需拦截的域名:
#pragma mark - SNI 场景,仅调用一次即可,请勿多次调用
/**
SNI 场景下设置需要拦截的域名列表
建议使用该接口设置,仅拦截 SNI 场景下的域名,避免拦截其它场景下的域名

@param hijackDomainArray 需要拦截的域名列表
*/
- (void) WGSetHijackDomainArray:(NSArray *)hijackDomainArray;

/**
SNI 场景下设置不需要拦截的域名列表

@param noHijackDomainArray 不需要拦截的域名列表
*/
- (void) WGSetNoHijackDomainArray:(NSArray *)noHijackDomainArray;
如设置了需要拦截的域名列表,则仅会拦截处理该域名列表中的 HTTPS 请求,其他域名不做处理。
如设置了不需要拦截的域名列表,则不会拦截处理该域名列表中的 HTTPS 请求。
注意:
建议使用 WGSetHijackDomainArray 仅拦截 SNI 场景下的域名,避免拦截其他场景下的域名。

帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈