「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」
前言
上一篇文章iOS之Charles抓包原理(上),我们大概描写了Charles是如何实现中间人攻击的。那这一篇,我们就来聊聊如何防止Charles捉包。
数字证书原理
CA机构拥有非对称加密的私钥和公钥。CA机构对证书明文数据T进行hash。- 对
hash后的值用私钥加密,得到数字签名。 - 明文和数字签名共同组成了数字证书
数字证书使用流程
- 服务端向浏览器发送数字证书(里面包含公钥,域名,明文数据等信息)
- 用
CA证书的公钥对数字签名进行解密,得到一个值,可以认为是S‘。 - 获取到明文数据
T,进行hash,hash后的值为h’。 - 这时候
S‘和h’的内容是一样的,才代表证书是可信的,没有被篡改的。
想一下,如果明文数据T被修改了,那hash后的值,和数字签名解密后的值就不一样了,就代表证书是不可信的,数据被篡改了。
要是CA颁发的证书,那我们就通过AFNetworking请求就好,但是大多数用的都不是正规的证书,那我们要如何做呢?
解决思路
方案一:connectionProxyDictionary
我们使用NSURLSession来发起网络请求,里面有一个NSURLSessionConfiguration的配置,这个配置有一个属性叫 connectionProxyDictionary。
官方给的注释是: 一般这个属性用来配置一些 需要走特定代理的连接,配置上特定的ip端口之类的,但是如果在初始化 NSURLSession 的时候将 connectionProxyDictionary 设置为空,当手机开启了代理服务,用这个session 发起的网络请求并不会去走这个代理,而且默认的不走代理直接发起网络请求。
所以我们可以定义一个宏,需要再放开,来判断是否可以代理调试。这就可以做到在线上不能捉包,内部打的包可以捉包。
configuration.connectionProxyDictionary = @{};
方案二:AFN + SSL Pinning
AFN有封装类似校验证书的功能,即SSL证书绑定。通过SSL证书绑定来验证服务器身份。
-
首先我们APP导入
cer证书,这个数字证书是可以问服务端获取的。 -
然后我们设置
SSL Pinning安全策略,校验模式可以设置为PublicKey,或者Certificate,具体选择可看下面的AFSecurityPolicy。 -
利用
cer证书,就能来有效地验证服务端的证书。配置好后,再设置代理,伪装的证书就无法通过验证了,就无法捉包了。
代码如下:
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
AFSecurityPolicy
typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
// 证书是信任机构签发的就会通过
AFSSLPinningModeNone,
// 验证服务端证书的公钥是否一致,一致就验证通过
AFSSLPinningModePublicKey,
// 验证全部信息,如证书的公钥,域名,有效期等信息,全部一致就验证通过
AFSSLPinningModeCertificate,
};
-
allowInvalidCertificates:允许非权威机构颁发的证书,一般设置为YES -
validatesDomainName: 验证域名是否一致
后记
上诉2种解决方案都可以使用,从而实现防止Charles捉包。如果有不同看法,欢迎留言。
参考链接: