Background
The recent app seems to have reported an exception that DNS could not resolve to try to resolve this issue. There is very little information gathered, even AFN the original author has decided that this may be an unsolved problem, see: https://github.com/AFNetworking/AFNetworking/ issues/2954, but in the end the StackOverflow on the slightest hint, successfully found and pooled into a usable solution. Rejoicing, share with June!
Problem description
The DNS hijacking problem can be resolved by directly accessing the website via IP. DNS hijacking, which can be simulated by modifying the computer's host file. If it is an HTTP request, use the IP address to directly access the interface, with the header in the host field with the original domain name information can be, if the HTTPS request, It's going to be a lot of trouble. Overriding TLS Chain Validation Correctly
there is a way in curl to -resolve
use the specified IP to access the HTTPS Web site, the Integrated Curl Library in iOS should also be possible, but the changes are too large, not verified, for the server IP is constantly changing circumstances, may need to use the Httpdns service, see: Https://www.dnspod.cn/httpdns.
Solution Discussion 1. The most straightforward way is to allow invalid SSL certificates, which are not recommended for production environments; 2. A method that requires partial rewriting of the AFN source code.
Add nsapptransportsecurity type dictionary in info.plist, add Nsallowsarbitraryloads type Boolean under Nsapptransportsecurity, The value is set to Yes. These are used to solve iOS9, allowing HTTP requests to access the network, of course, more than that. For specific reasons interested in Google.
To add a new attribute to the Afurlconnectionoperation class:
/** 可信任的域名,用于支持通过ip访问此域名下的https链接. Trusted domain, this domain for support via IP access HTTPS links. */@property(nonatomic, strong) NSMutableArray * trustHostnames;
- Proxy method implemented for Afurlconnectionoperation:-(void) connection: (Nsurlconnection *) connection
Willsendrequestforauthenticationchallenge: (Nsurlauthenticationchallenge *) challenge Add related logic code to add a trusted domain name:
- (void) Connection: (nsurlconnection*) Connectionwillsendrequestforauthenticationchallenge: (Nsurlauthenticationchallenge *) challenge{if( Self. Authenticationchallenge) { Self. Authenticationchallenge(connection, challenge);return; }if([Challenge. Protectionspace. AuthenticationmethodIsequaltostring:nsurlauthenticationmethodservertrust]) {Sectrustref servertrust = Challenge. Protectionspace. Servertrust;/* Add a trusted domain name to support: Access specific HTTPS servers directly using IP. ADD trusted domain name to support:direct use of IP access specific HTTPS server.*/ for(NSString* Trusthostname in [ SelfTrusthostnames]) {servertrust = Afchangehostfortrust (Servertrust, trusthostname); } ....
- Refer to Apple's official documentation for customized functions for adding trusted domain names: afchangehostfortrust
Static inline Sectrustref afchangehostfortrust (Sectrustref trust, NSString * trusthostname) {if(! Trusthostname | | [Trusthostname isequaltostring:@""]) {returnTrust } cfmutablearrayref newtrustpolicies = Cfarraycreatemutable ( Kcfallocatordefault,0, &kcftypearraycallbacks); Secpolicyref Sslpolicy = Secpolicycreatessl (true, (Cfstringref) trusthostname); Cfarrayappendvalue (Newtrustpolicies, Sslpolicy);#ifdef mac_backwards_compatibility/* This technique worksinchOS X (V10. 5 andLater) */sectrustsetpolicies (trust, newtrustpolicies); Cfrelease (oldtrustpolicies);returnTrust#else/* This technique worksinchIos2 andLater,orOS X V10. 7 andLater */cfmutablearrayref certificates = cfarraycreatemutable ( Kcfallocatordefault,0, &kcftypearraycallbacks); /* Copy theCertificates from theOriginal Trust Object */CfindexCount= Sectrustgetcertificatecount (trust); Cfindex i=0; for(i =0; I <Count; i++) {SeccertificaterefItem= Sectrustgetcertificateatindex (trust, I); Cfarrayappendvalue (Certificates,Item); }/* Create a new Trust object */Sectrustref newtrust = NULL;if(Sectrustcreatewithcertificates (certificates, newtrustpolicies, &newtrust)! = errsecsuccess) {/* Probably a good spot to LogSomething. */returnNULL; }returnNewtrust;#endif}
- Using the AOP method, override the Trusthostnames property of Afurlconnectionoperation:
/* 使用AOP方式,指定可信任的域名, 以支持:直接使用ip访问特定https服务器.*/ [AFURLConnectionOperation aspect_hookSelector:@selector(trustHostnames) withOptions:AspectPositionInstead usingBlock: ^(id<AspectInfo> info){ NSArray * trustHostnames = @[@"www.example.com"]; NSInvocation *invocation = info.originalInvocation; [invocation setReturnValue:&trustHostnames]; }error:NULL];
Here is an IOS AOP library, an unfamiliar point here: http://www.ios122.com/2015/08/aspects/.
Afnetworking The original author can not solve the problem: How to use IP direct access to HTTPS Web site?