Karsa Wang 's Blog

记录一些问题,也许对其他人也有所助益


SSL Pin 研究和原理以及在iOS调试的坑

最近碰到个在 ReactNative 里面使用 SSL pin 的坑,困扰了我许久,解决后记录下。 什么是 SSL,安全性怎么保障 https 我们很熟悉,iOS 是默认强制使用的,https 本质是运行在 ssl 加密通道上的 http,核心是 ssl 加密。ssl 加密是通过服务端下发共用证书,协商好加密方案后建立的加密通道。 安全性是通过系统内置的知名 CA 的根证书,与建立 SSL 通道时候,服务端下发的证书链进行比对,来保障。这里默认 CA 是可以信任的,那么 CA 签发的证书就是可信的。CA 下发的证书可以跟 CA 的根证书形成证书链条,用以进行证书有效性确认。安全性得以保障。 SSL pin 是什么,用在什么场景 ssl 加密通道是非对称加密通道,服务端下发了公钥,客户端进行加密,服务端拿私钥进行解密,本质上是信任了 CA 签发的证书,也就是服务端作为主导。 但 CA 有时候也不靠谱,万一证书签发错误,或者泄漏给别人了,咋办?SSL pin 这时候就是用来进行额外的保障。 SSL pin 通过在客户端内置公钥证书,和服务端下发的证书做比对,在系统比对的基础上,增加一层自己比对的过程。自己比对的时候,就可以在 CA 证书之外,有自签名证书作为额外一层保障。这时候,即使对方拿到了 CA 签发的正确证书,我们自己签发的证书也可以保障服务的安全性。 iOS 中 SSL pin 怎么用 iOS 中用 NSURLSession 的时候,指定一个实现了URLSession:didReceiveChallenge:completionHandler方法的 delegate,就可以在回调方法里,进行自定义的证书比对过程。 整个过程相对比较麻烦,所以现在大家用的比较多的是通过一个开源库TrustKit进行比对。 TrustKit 通过配置域名和与之对应的公钥证书签名,(这里后续的描述是有问题的,看后续更新中“Public Key Pinning 是怎么实现的”这段)在 SSL 通道建立的时候,获取到证书链,比对证书链中每个证书,一旦有比对成功的,就算是成功,如果所有的都比对失败,就算是 SSL pin 失败了。SSL pin 失败,会打断 ssl 通道的建立,所以后续 ssl 通道上的 http 请求也不会发生。

Read more...

环境配置害死人,快用docker拯救你

关于环境配置这个问题,其实这个问题折腾过很多次了,但每次都踩坑,可谓是坑坑不一样,一坑更比一坑深。 记录这个也不是刚发现,而是为了打自己脸,每次一碰到问题,就无脑冲,折腾了一万年的时候,发现还是这个方法香。但这个方法是自己用过无数次的啊。 最早用docker的时候,你肯定想不到,其实不是为了不服服务,而是为了使用不同的环境,最开始是因为python,后来是因为node。聪明的你肯定会问,为啥不用python和node的版本管理工具,比如nvm之类的。我只能说,第一当时的我确实年轻,只是一门心思解决问题,而不是去找解决问题的工具,所以折腾的很累,收效却甚微。第二,即使在折腾,也怕把主机环境折腾坏,毕竟对主机运行的服务对环境的依赖不清楚。第二个原因,即使到现在,不断的去了解系统运行服务,其实还是不能避免。 但有了docker就完全不一样了,我就是运行个应用程序而已,管你host上什么环境,我用全新的环境,在本机运行这个程序不香么?多出来的时间干啥不好,为啥一定要跟没有做好的系统或者没有做好的安装程序较劲?即使最终成功了,真的有什么收获么? 况且,docker提供的不仅仅是一个干净高度可定制的环境,他还是有dockerhub,不好配置安装但又不得不用的工具很多这里都有,你就说香不香吧。

加密通道搭建独立开发者的开发环境

作为独立开发者或者说小型开发团队,不大可能像大型团队一样在运维方面走比较安全但同时相对复杂的运维流程,但同时又需要一个相对灵活稳定且具有一定安全性的方式,来跟服务器服务进行联通。这时候,加密通道在这个场景下可能是比较好的解决方案。 我自己用的是qtunnel, 它是很多年前的代码了,并且已经很多年不更新,但不影响它至今仍然对我很有吸引力。 具体的使用方式就不赘述了,他的核心价值是在非安全链接上对流量进行加密,readme里面的例子是redis,这也是我一直在使用的模式。不仅仅是redis,任何tcp协议的服务他都可以支持,包括但不限于 mysql 这类数据库服务,nacos 这类服务发现和数据配置服务。事实上,我的开发电脑和服务器之间就是完全通过qtunnel搭建起来的开发环境。 为什么使用qtunnel?我是个比较懒惰的开发者,在发现qtunnel之前,没有常规的流程其实就是进行日志调试,或者实在没得选的时候,冒险开放一下服务的端口调试,使用之后立即关上。这样确实是有风险的,并且不久之后我就尝到了风险的滋味。有一次调试后,因为一些事情,我忘记调整防火墙,然后那是个周末前的工作日,在下个周一到来之前,在我还在外面美美的拍照的时候,收到了数据库锁定的勒索消息。在那之后,我就基本上把所有的敏感服务端口都关掉了,同时开始寻找解决方案。 qtunnel可以解决这个问题,除此之外,他是用go开发的,因为我用go语言,所以go语言开发的开源方案是我的首选。在看到他后,说实话我被他简洁的代码和开发模式吸引了。他的代码结构非常简单,代码量也少,这意味着即使作者不再维护代码,如果我要使用,修改的代价也很小。 在他停止维护的几年后,go推出了mod的管理模式,替代之前使用gopath管理库的方式,我仅仅是初始化了一下mod,修改几处简单的引用就能重新编译,对比ios,前端代码,这简直就是在天堂。

hugo目前的部署

虽然不想说,但这次部署的方式确实有点难受的。 之前博客部署在DO的vps上,但这台机器资源比较有限,经常会碰到运行一段时间后因为OOM被系统干掉的情况。 然后想说部署在aliyun的机器上,但问题是域名解析过来,需要进行个人备案,我不太想这么操作,避免后续某个时间这个域名不用的时候,备案还在我的名下。 我还有另外一台机器,也不需要备案,资源也算充裕,但问题是那上面运行的服务后续可能会膨胀,如果不膨胀,大概率是要删除的,又不稳定。 嗯,背景就是上面讲的这样。于是一个很诡异的逻辑诞生了: 在aliyun的机器上部署hugo运行服务,开放端口;博客域名解析到DO的vps上,流量通过nginx转发到阿里云的机器上。

Hugo端口和路径配置

其实是第二次折腾hugo了,但还是踩了一些坑,浪费了挺多时间。 版本问题 linux下特别是ubuntu下,apt安装的hugo版本比较旧,记得使用github的release里面,安装最新的版本。 子页面路径上带有端口号的问题 默认情况下,对子页面的引用会是 {baseURL:port/pagePath}的形式,如果hugo服务是通过nigix反向代理到80端口的,我们通常不想让port出现在这里,这时候需要使用 --appendPort=false 这个参数来避免这个问题。 没有特别理解这个参数的默认值为啥是true,或者说为啥不是直接删除这个参数,完全信赖baseURL。

1 of 1