iOS 防止抓包(SSL Pinning)

1、判断是否有网络代理(不推荐)

当进行网络请求的时候,客户端判断当前是否设置了代理,如果设置了代理,不允许进行访问,附带判断是否设置代理的代码:

+ (BOOL)getProxyStatus {
    NSDictionary *proxySettings = NSMakeCollectable([(NSDictionary *)CFNetworkCopySystemProxySettings() autorelease]);
    NSArray *proxies = NSMakeCollectable([(NSArray *)CFNetworkCopyProxiesForURL((CFURLRef)[NSURL URLWithString:@"http://www.baidu.com"], (CFDictionaryRef)proxySettings) autorelease]);
    NSDictionary *settings = [proxies objectAtIndex:0];
    
    NSLog(@"host=%@", [settings objectForKey:(NSString *)kCFProxyHostNameKey]);
    NSLog(@"port=%@", [settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
    NSLog(@"type=%@", [settings objectForKey:(NSString *)kCFProxyTypeKey]);
    
    if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"])
    {
        //没有设置代理
        return NO;
    }
    else
    {
        //设置代理了
        return YES;
    }
}

结果:


没有代理:
[20383:1874008] type=kCFProxyTypeNone
(lldb) po proxies
<__NSArrayM 0x1c064e5e0>(
{
kCFProxyTypeKey = kCFProxyTypeNone;
}
)


设置了代理
[20391:1874714] type=kCFProxyTypeHTTP
(lldb) po proxies
<__NSArrayM 0x1c005f8c0>(
{
kCFProxyHostNameKey = “127.0.0.1”;
kCFProxyPortNumberKey = 1380;
kCFProxyTypeKey = kCFProxyTypeHTTP;
}
)


2、SSL Pinning(AFN+SSL Pinning)推荐

SSL Pinning,即SSL证书绑定。通过SSL证书绑定来验证服务器身份,防止应用被抓包。
1、取到证书
客户端需要证书(Certification file), .cer格式的文件。可以跟服务器端索取。
如果他们给个.pem文件,要使用命令行转换

    openssl x509 -inform PEM -in name.pem -outform DER -out name.cer

如果给了个.crt文件,请这样转换:

    openssl x509 -in name.crt -out name.cer -outform der

如果啥都不给你,你只能自己动手了:

openssl s_client -connect www.website.com:443 /dev/null | openssl x509 -outform DER > myWebsite.cer**

2、把证书加进项目中
把生成的.cer证书文件直接拖到你项目的相关文件夹中,记得勾选Copy items if neede和Add to targets。
3、参数名意思
AFSecurityPolicy
SSLPinningMode

AFSecurityPolicy是AFNetworking中网络通信安全策略模块。它提供三种SSL Pinning Mode

/**
 ## SSL Pinning Modes

 The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes.

 enum {
 AFSSLPinningModeNone,
 AFSSLPinningModePublicKey,
 AFSSLPinningModeCertificate,
 }

 `AFSSLPinningModeNone`
 Do not used pinned certificates to validate servers.

 `AFSSLPinningModePublicKey`
 Validate host certificates against public keys of pinned certificates.

 `AFSSLPinningModeCertificate`
 Validate host certificates against pinned certificates.
*/

AFSSLPinningModeNone:完全信任服务器证书;
AFSSLPinningModePublicKey:只比对服务器证书和本地证书的Public Key是否一致,如果一致则信任服务器证书;
AFSSLPinningModeCertificate:比对服务器证书和本地证书的所有内容,完全一致则信任服务器证书;
选择那种模式呢?
AFSSLPinningModeCertificate:最安全的比对模式。但是也比较麻烦,因为证书是打包在APP中,如果服务器证书改变或者到期,旧版本无法使用了,我们就需要用户更新APP来使用最新的证书。
AFSSLPinningModePublicKey:只比对证书的Public Key,只要Public Key没有改变,证书的其他变动都不会影响使用。
如果你不能保证你的用户总是使用你的APP的最新版本,所以我们使用AFSSLPinningModePublicKey

allowInvalidCertificates

/**
 Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`.
 */
@property (nonatomic, assign) BOOL allowInvalidCertificates;

是否信任非法证书,默认是NO。
validatesDomainName

/**
 Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`.
 */
@property (nonatomic, assign) BOOL validatesDomainName;

是否校验证书中DomainName字段,它可能是IP,域名如*.google.com,默认为YES,严格保证安全性。

4、使用AFSecurityPolicy设置SLL Pinning

+ (AFHTTPSessionManager *)manager
{
    static AFHTTPSessionManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        manager =  [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config];

        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey withPinnedCertificates:[AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]]];
        manager.securityPolicy = securityPolicy;
    });
    return manager;
}

扩展
Android 防止抓包
1、单个接口访问不带代理的

 URL url = new URL(urlStr);  
   urlConnection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); 

2、OkHttp框架

    OkHttpClient client = new OkHttpClient().newBuilder().proxy(Proxy.NO_PROXY).build(); 

更多:
https://www.cnblogs.com/zhanggui/p/5754977.html
https://www.jianshu.com/p/23545f8d36d2

你可能感兴趣的:(iOS基础)