最近想实现一个旧项目https的防抓包功能,重新学习并且配置了下https相关通信知识,参考了不少文章,有些文章比较旧不全或者有误,走了不少弯路和坑,所以整理出来方便自己巩固以及供大家参考,指出不足或者有误之处互相学习。
本文的服务端环境:
1 | Debian 9.8 |
原创文章,欢迎转载,转载请注明:ifish.site
作者:JaydenZhou
一、需要的前置知识点
本文需要的前置知识点,这也是我刚接触时候绕得很晕的问题,自己前后端流程走一遍后,就清晰多了。
1 | 网络相关的知识点: |
https的通信,是从非对称加密(RSA)到对称加密(AES)的一个过程,其中数字证书扮演着重要作用。 借助文章:https://juejin.im/post/5c9cbf1df265da60f6731f0a 里面所讲,
1 | 数字证书 = 公钥 + 签名 + 申请者和颁发者的信息 |
类比于我们的身份证(数字证书) = 证件号(公钥) + 公安盖章(签名) + 个人姓名/发证公安局(申请者和颁发者的信息)。
私钥一般以.key结尾,用它才能跟对应的数字证书(公钥)互相解密。
二、单向/双向认证的应用场景在哪里呢?
单向认证: 这里有个简单的理解,凡是你可以直接访问的网站(比如我的域名: https://ifish.site ); 直接请求的https的api等,都是单向认证,因为它只需要client端能够解密出server端的数字证书(分CA和自签发的),操作系统或者浏览器一般都内置了一堆相关CA的证书,所以可以直接访问;若是自签发的,浏览器会提示该证书不受信任。适用场景是站点访问,非高机密数据传输。
双向认证: 顾名思义,就是在单向基础上,添加上了服务端要校验客户端的公钥,客户端要自己保存着自己的私钥来加密,客户端发过来的请求要用该私钥来加密后,才能跟服务器进行完整通信。适用场景:企业间对应机密api接口的数据传输。
三、证书的生成
配置好Linux环境后,首先我们要生成对应的证书,两种方法如下:
1 | 方法一:用CA签的证书(有收费 or 免费),这样浏览器就不会显示不信任提示,前提是要有合法的境内实名域名,然后比如在阿里云服务器管理后台界面进行证书的申请。 |
方法一按照对应服务商的提示来操作就行,这里讲下openssl来生成的方法,先抛出一个我自己现在也疑惑的问题:
为何要生成root根CA证书,然后再发布二级server和client证书? 是为了一个根证书可以直接管理多个二级证书?
本文为了简化演示https单向/双向认证,只需要生成对应的 server 和 client 相关证书就行,避免文件太多导致像我这样的新手造成的困惑和配置出错。
1.生成服务端key:
1 | openssl genrsa -out server-key.key 1024 |
2.生成服务端证书请求文件(这步很关键,弹出信息填写提示时候,“Common Name”一定要填写你自己的域名,其他的可以直接回车):
1 | openssl req -new -out server-req.csr -key server-key.key |
比如我的域名是 ifish.site
3.生成服务端证书cer:
1 | openssl x509 -req -in server-req.csr -out server-cert.cer -signkey server-key.key -CAcreateserial -days 3650 |
4.生成客户端key(同上面方法一样):
1 | openssl genrsa -out client-key.key 1024 |
5.生成服务端证书请求文件(Common Name最好一致):
1 | openssl req -new -out client-req.csr -key client-key.key |
6.生成客户端证书cer:
1 | openssl x509 -req -in client-req.csr -out client-cert.cer -signkey client-key.key -CAcreateserial -days 3650 |
7.生成客户端带密码的p12证书(这步很重要,双向认证的话,浏览器访问时候要导入该证书才行;Android请求的时候也需要把它转成bks来请求双向认证):
1 | openssl pkcs12 -export -clcerts -in client-cert.cer -inkey client-key.key -out client.p12 |
四、nginx配置
1.将生成的证书,为了方便管理,建议放到nginx相同目录下,比如我是放到“/usr/local/nginx/conf/ssl_cust” 里面;
2.打开对应的 conf 里面要https访问的域名,如果之前有配过443端口,那么只需要指定下对应的证书即可,其中
1 | 单向认证是: |
1 | 双向认证是: |
3.若完全没有配过https的话,可以参考我的配置:
1 | server |
4.保存关闭后,执行以下命令让nginx重启生效:
1 | sudo nginx -s reload |
5.如此我们配置就生效了,可以用浏览器来验证下,如果只是单向认证,直接浏览器输入域名来访问即可,会有不安全提示;
若是双向认证,直接访问会出现 400 Bad Requst, 需要我们手动添加证书,这里是Chrome下的截图,我们需要添加之前我们生成的 client.p12 文件。
五、Android代码请求
终于到Android请求的代码写法了,为了简化Demo的独立访问,这里引入了 xUtils库 (https://github.com/wyouflf/xUtils3 ),当然你也可以自己手写或者用比如Retrofit、OkHttp等网络库。
单向认证的写法:
其实单向认证,用xUtils的话可以不需要设置setSslSocketFactory内容,因为库代码DefaultParamsBuilder.java里面判断了如果没有设置自定义ssl,那么就直接用操作系统自带的进行返回,从而来访问https。
我们这里为了演示下具体代码,所以自定义一个ssl的构造出来,操作如下:
把服务端server-cert.cer证书放到 assets 目录下,然后创建一个 SSLHelper.java 的辅助类:
1 | public static SSLSocketFactory getSSLSingleFactory(Context context) { |
对应的Activity请求里的代码是:
1 | RequestParams params = new RequestParams("https://ifish.site"); |
双向认证的写法:
双向认证要求的是客户端也需要持有一份自己的私钥key、服务端要有一份客户端的公钥证书。但是由于Android系统限制,我们需要把client.p12转成client.bks格式,才能被访问到。介绍一个转化工具,叫做“Portecle”,亲测可用的下载和使用链接如下:https://blog.csdn.net/zhangyong125/article/details/50402183,也可以自己去官网免费下载,如果是Linux系统, 可以用 java -jar protecle.jar 来运行,然后按照上文链接的使用方法,把对应的 client.p12转成client.bks格式。
对应的 SSLHelper.java添加一个双向认证方法:
1 | public static SSLSocketFactory getSSLDoubleFactory(Context context) { |
然后Activity里面,params.setSslSocketFactory(SSLHelper.getSSLSingleFactory(this)); 换成 params.setSslSocketFactory(SSLHelper.getSSLDoubleFactory(this)); 即可。
六、总结
疑难点:
1.涉及的知识点比较多,很多不是Android本身的东西;
2.https单向/双向原理不太好理解,可以看该文https://juejin.im/post/5c9cbf1df265da60f6731f0a;
3.仅验证单双向认证来说,没必要生成根CA证书,部分文章生成太多证书会导致配置上容易乱。
调试验证技巧:
原Android网络请求框架庞大,对应的域名是生产环境的域名,绝对不能随便动后台的生产环境配置。因此需要自己的一台服务器,自己搭建一个简单的后台Demo https请求,以及Android的Demo网络请求app,从而方便Debug。
参考:
https://www.zhihu.com/question/29620953 – SSL中,公钥、私钥、证书的后缀名都是些啥?
https://juejin.im/post/5c9cbf1df265da60f6731f0a – 扯一扯HTTPS单向认证、双向认证、抓包原理、反抓包策略
https://zhuanlan.zhihu.com/p/60392573 – 为了抓包某app,我折腾了10天,原来他是用SSL Pinning防抓包的
https://www.cnblogs.com/yelao/p/9486882.html – Nginx https 双向认证
https://blog.csdn.net/jsc702325/article/details/76724010 – Android 用自签名证书实现https请求
https://www.cnblogs.com/guogangj/p/4118605.html – 那些证书相关的玩意儿(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12等)
https://blog.csdn.net/zhangyong125/article/details/50402183 – P12证书转BKS证书