iOS(Objective-C)设置备用DNS解决域名解析失败方案咨询
iOS端自定义DNS配置解决方案(Objective-C实现)
iOS系统没有对外暴露类似安卓端全局修改Java VM DNS属性的公共API,普通第三方应用无法直接全局覆盖系统DNS配置,你可以根据自身网络请求的实现层级选择对应方案:
方案1:针对NSURLSession/UIWebView/WKWebView的请求,自定义NSURLProtocol拦截解析
这是最常用的应用层实现方案,可以在拦截到域名请求时,手动将域名替换为指定DNS服务器解析得到的IP,同时修改请求Host头:
// 自定义DNS解析工具方法 - (NSString *)resolveHost:(NSString *)host withDnsServer:(NSString *)dnsServer { // 示例为固定host映射,实际可集成DNS查询逻辑,向指定DNS服务器请求A记录 NSDictionary *hostMap = @{@"your-custom-host.com": @"192.168.1.1"}; return hostMap[host] ?: host; } // NSURLProtocol拦截请求时的处理逻辑 - (void)startLoading { NSMutableURLRequest *mutableRequest = [self.request mutableCopy]; NSString *originalHost = mutableRequest.URL.host; NSString *resolvedIp = [self resolveHost:originalHost withDnsServer:@"8.8.8.8"]; // 替换域名为解析后的IP NSURLComponents *components = [NSURLComponents componentsWithURL:mutableRequest.URL resolvingAgainstBaseURL:NO]; components.host = resolvedIp; mutableRequest.URL = components.URL; // 手动设置Host头保证服务端正常识别 [mutableRequest setValue:originalHost forHTTPHeaderField:@"Host"]; // 发送修改后的请求 NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; self.dataTask = [session dataTaskWithRequest:mutableRequest]; [self.dataTask resume]; }
使用前需要提前将自定义的NSURLProtocol注册到NSURLSessionConfiguration中。
方案2:针对Socket层的原生网络请求,指定DNS服务器查询
如果你的应用直接使用BSD Socket或者CFNetwork框架做网络通信,可以在解析域名时手动指定DNS服务器地址,绕过系统默认DNS配置:
#include <resolv.h> #include <netdb.h> - (NSArray *)queryIpFromHost:(NSString *)host dnsServer:(NSString *)dnsServer { res_state res = malloc(sizeof(struct __res_state)); res_ninit(res); // 手动设置指定的DNS服务器 in_addr_t dnsAddr = inet_addr([dnsServer UTF8String]); res->nsaddr_list[0].sin_addr.s_addr = dnsAddr; res->nsaddr_list[0].sin_family = AF_INET; res->nsaddr_list[0].sin_port = htons(53); res->nscount = 1; u_char answer[1024]; int len = res_nquery(res, [host UTF8String], ns_c_in, ns_t_a, answer, sizeof(answer)); // 后续解析answer报文获取IP列表,此处省略解析逻辑 res_nclose(res); free(res); // 返回解析得到的IP数组 return @[]; }
注意事项
- 上述方案仅对当前应用自身的网络请求生效,无法影响系统其他应用的DNS配置
- 如果需要全局生效当前应用所有网络请求,建议在网络库底层统一做域名解析替换,避免逐个修改业务请求逻辑
内容的提问来源于stack exchange,提问作者Douglas Ianitsky
相关产品推荐
相关产品推荐

