tencent cloud

HTTPS (SNI) Scenario
Last updated: 2025-09-05 17:52:26
HTTPS (SNI) Scenario
Last updated: 2025-09-05 17:52:26

Principles

Server Name Indication (SNI) is an SSL/TLS extension to address the use of multiple domain names and certificates on a server. How it works is as follows:
Send the domain name (Hostname) of the site to access before connecting to the server to establish an SSL connection.
The server returns a suitable cert based on this domain name.
During the process, when the client uses HTTPDNS resolution for the domain name, the host in the request URL will be replaced with the IP obtained from HTTPDNS resolution. This causes the server to receive the parsed IP as the domain name, making it unable to find a matching certificate. As a result, the server can only return the default certificate or do not return one, leading to an SSL/TLS handshake error.
Since iOS overlay network libraries NSURLConnection/NSURLSession do not provide an API to configure the SNI field, NSURLProtocol can be considered for use to intercept network requests, and use CFHTTPMessageRef to create an NSInputStream instance for Socket Communication, set its kCFStreamSSLPeerName value.

Solution Description

Note:
This documentation provides a reference solution for HTTPDNS integration in SNI scenarios. The example code is not official code for online production environments. Before integration, we recommend that you fully evaluate the content of this documentation to ensure the solution's robustness meets your production standards.
If you need a reference example, you can refer to the source code of MSDKDnsHttpMessageTools and modify or reuse it based on business needs.
HTTPDNS iOS SDK provides MSDKDnsHttpMessageTools. MSDKDnsHttpMessageTools is a Protocol encapsulated by HTTPDNS iOS SDK based on NSURLProtocol. MSDKDnsHttpMessageTools inherits NSURLProtocol and can automatically intercept requests in NSURLSession. MSDKDnsHttpMessageTools calls the WGGetHostByName method, automatically replaces the IP in the URL and sets the HOST header. With MSDKDnsHttpMessageTools, you no longer need to perform domain name replacement. MSDKDnsHttpMessageTools addresses the limited functionality and poor scalability of the CFNetwork library used in custom NSURLProtocol.

Sample Code

Complete example code is available in Demo's SNIViewController.m.
// Register NSURLProtocol to intercept requests
[NSURLProtocol registerClass:[MSDKDnsHttpMessageTools class]];

// URLs that require SNI, such as https://www.qq.com
NSString *originalUrl = @"your url";
NSURL *url = [NSURL URLWithString:originalUrl];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

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

// NSURLSession example
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 example
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];

Usage Instructions

Call the following APIs to set the domain names to block or no interception required:
#pragma mark - SNI scenario, call only once, do not call multiple times
/**
Set the domain name list to intercept in the SNI scenario
Recommend using this API setting to only intercept domain names in the SNI scenario and avoid blocking domain names in other scenes

@param hijackDomainArray Domain name list to intercept
*/
- (void) WGSetHijackDomainArray:(NSArray *)hijackDomainArray;

/**
Set the non-intercepted domain list in the SNI scenario

@param noHijackDomainArray Non-intercepted domain list
*/
- (void) WGSetNoHijackDomainArray:(NSArray *)noHijackDomainArray;
If a domain name list is set up for interception, only HTTPS requests from the listed domains will be intercepted and handled. No action is taken for other origins.
If a non-intercepted domain list is set up, HTTPS requests from the listed domains will not be intercepted and handled.
Note:
Recommend using WGSetHijackDomainArray to block domains in SNI scenarios only and avoid blocking domains in other scenarios.
Was this page helpful?
You can also Contact Sales or Submit a Ticket for help.
Yes
No

Feedback