从答题赚钱APP谈谈接口防抓包

从答题赚钱APP谈谈接口防抓包

这段时间,答题赚钱APP真的是红遍了神州大地:国民老公王思聪的冲顶大会、芝士超人、西瓜视频,甚至连老司机韩路也玩起了这个游戏?。有利益就有动力,毕竟每场奖金都在十万、百万,虽然官方可以在最终答对人数上面掺水稀释每人的奖金,但是的确可能拿到奖金。人类,对这种可预期、强反馈的东西跟吸毒一样……于是,市面上出现了很多所谓的自动AI答题工具。大概可以分为两个流派:

  1. 通过OCR识别题目,然后用搜索引擎搜索答案告诉用户选什么。答案选择策略各异。做得比较简单的就是选搜索结果最多的那个为正确答案。
  2. 直接抓包这些APP下发的题目,然后用搜索引擎搜索答案。

可以看出,主要区别就是如何获取题目的文本。顺便吐槽一句,其实这些工具跟AI有半毛钱关系呀。对于第一种方式,是比较难防的。第二种方式解决办法主要有两种:

  1. 设计之初,使用图片下发题目,而不是直接下发题目文本;
  2. 如果已经走上了文本下发题目这条不归路,那么至少要做到接口防抓包。

这里我们谈一下接口如何防抓包。

为何可以成功抓包?

  1. 接口走HTTP,那么直接是明文传输,也不存在传输层的认证和加密问题,所见即所得。随着大家安全意识的增强,直接这么裸奔的产品越来越少。但是会有人因为各种原因就是不迁移到HTTPS,然后自己实现一个民科版的加密。我们极其不推荐这种做法,主要有以下几个原因:
    1. 大部分工程师都没有密码学背景,设计的算法基本很难完备的考虑数据机密性、完整性和不可抵赖性。
    2. 将应用层与数据传输层进行耦合不仅限制了通用性,如无法进行透明的流量转发,而且会带来非常高的系统维护和迁移成本。
  2. 接口走HTTPS。嗯,数据加密了不是?但是,通过中间人攻击(MitM)也是可以成功抓包的。这背后的基本原理是:在手机上安装一个中间人CA证书(如Charles证书) --> APP信任手机上的证书 --> 中间人可以成功解密流量进行抓包

如何防止抓包?

对于HTTPS API接口,如何防止抓包呢?既然问题出在证书信任问题上,那么解决方法就是在我们的APP中预置证书。在TLS/SSL握手时,用预置在本地的证书中的公钥校验服务器的数字签名,只有签名通过才能成功握手。由于数字签名是使用私钥生成的,而私钥只掌握在我们手上,中间人无法伪造一个有效的签名,因此攻击失败,无法抓包。

同时,为了防止预置证书被替换,在证书存储上,可以将证书进行加密后进行「嵌入存储」,如嵌入在图片中或一段语音中。这涉及到信息隐写的领域,这个话题我们有空了详细说。

预置证书/公钥更新问题

这样做虽然解决了抓包问题,但是也带来了另外一个问题:我们购买的证书都是有有效期的,到期前需要对证书进行更新。主要有两种方式:

  1. 提供预置证书更新接口。在当前证书快过期时,APP请求获取新的预置证书,这过渡时期,两个证书同时有效,直到安全完成证书切换。这种方式有一定的维护成本,且不易测试。
  2. 在APP中只预埋公钥,这样只要私钥不变,即使证书更新也不用更新该公钥。但是,这样不太符合周期性更新私钥的安全审计需求。一个折中的方法是,一次性预置多个公钥,只要任意一个公钥验证通过即可。考虑到我们的证书一般购买周期是3~5年,那么3个公钥,可以使用9~15年,同时,我们在此期间还可以发布新版本废弃老公钥,添加新公钥,这样可以使公钥一直更新下去。

谈谈“五级工程师和职业发展”的思考

再过几个小时,春节长假就结束了。我想,不管过去的一年过的怎样,大部分工程师们对开年的的工作和生活都应该是有所憧憬和计划的,我也不例外。只不过我选择了把前年在吴军老师《硅谷来信》上看到的《五级工程师和职业发展》重温了一下(版权原因,我这里无法提供原文的链接,但这一定阻挡不了聪明、求知若渴的你)。如果你看过原文,我依然觉得你不妨看看这里的思考,因为我所思考的可能更贴近实际的你。

什么是“五级工程师”?

著名前苏联物理学家朗道曾经给出过一个五级物理学家的划分,吴军老师在此基础上,给出了“五级工程师”的划分:

  • 第五级:能独立解决问题,完成工程工作;
  • 第四级:能指导和带领其他人一同完成更有影响力的工作;
  • 第三级:能独立设计和实现产品,并且在市场上获得成功;
  • 第二级:能设计和实现别人不能做出的产品,也就是说他的作用很难取代;
  • 第一级:开创一个产业。

你处在哪一级?

五级工程师的划分非常简洁,但是却有点抽象。我举几个大家熟悉的人物,方便大家进行定位:

  • 云风, 第三级;
  • 阮一峰,第三级;
  • 范凯,第四级;
  • 王垠,第五级;
  • 池建强,在用友度过了第五级和第四级,到锤子科技,以及后来加入极客帮逐步升级到第三级;
  • 冯大辉,在支付宝时为第四级(阿里P8),后来加入丁香园,现在创业无码科技输出产品后到了第三级。如果无码在医疗搜索上能独树一帜,我觉得应该能到2.5级。
  • Jeff Dean, Linus, 丹尼斯.里奇, 肯·汤普逊,第二级;
  • 爱迪生、福特、贝尔、香农、理查德.斯托曼,第一级。
  • 爱因斯坦, 第0级;

需要说明的是,以上只是我自己的一个主观划分,上面的大牛在每个人心中的位置因为了解程度和和主观倾向不同,划分的结果可能有区别。这里只是参照,方便大家自我定位。

尤其要指出的是,我这里并不是要黑王垠。细说起来我还请垠兄吃过饭,应该对他还算了解,只是对于大众来说,他至今(2018.02)还没有向人们展示一个有足够影响力的产品(无论是面向开发者的技术产品还是面向普通用户的应用产品)。近期他把自己的博客删除了,关于他的消息逐渐少了,也许当他回归的那天,他会直接从第五季跃迁到第三级。 王垠博客在这篇博文发表没几天就恢复访问了,他最近发表的博文《真相》道出了他准备认真写书的计划,采取自愿付费的方式。有兴趣的同学可以支持一下他,希望他能带了一点点difference.

严格的说,第五级并不是一个轻而易举就能达到的级别。但是,只要是一个善于思考,手脚轻快的新晋工程师在工作一两年以后,达到是没有问题的。如果你每天做的事情都是一些简单重复性的事情,那么我想其实是不能算为第五级工程师的。

如何打怪升级?

对于工程师来说,确定性的输入和输出是最容易解决的问题。那么,我们知道了这个划分以后,如何来指导自己的职业发展进行打怪升级呢?我觉得需要想清楚以下几件事。

级别之间人与人的能力、能力圈的差距是数量级的

以前跟同事一起饭后散步的时候,我经常说人和人之间的差距是无法想象的,如果一个人内心做不到真正的谦逊,那一定是他没有见过真正优秀的人。对于工程师级别的划分也是一样的,优秀工程师与普通工程师的差距是数量级的,而不是线性的,更不是想象的只差一点点。回到自己身上,抬头看一下上面?列出的代表性工程师,客观评估一下与他们的差距,是否有种路漫漫而修远兮的感觉?但是,我们并不用失望,要知道,对于大航海时代的船长来说,正式知道了自己的位置才支撑着他们战胜了风浪和败血症,最终发现了新大陆。

这个数量级我觉得不用定太大,《The Rise of Developeronomics》提到的“10倍效率工程师”应该是比较合适的。即每个级别相差10倍。

想清楚了这一点,能大大缓解程序员之间天然的鄙视链,内心也变得不那么天生骄傲。你身边一定会有你觉得是“菜鸟”的同事。对于这类同事,说你的工作效率和工作输出是他们的3~5倍,可能你不会反对,但是扪心自问你的工作能力是他们的10倍吗?如果这里你需要掂量一下,那么就默默放下你心中对他们的相对优越感吧,毕竟你们之间还是在同一个级别,你们之间的差距很可能只是时间经验的积累罢了。

此外,级别之间的差距不仅要求的专业能力要有数量级的提升,对于能力圈的大小也需要有数量级的提升。你身边一定有薪酬和工作效率跟刚毕业不久的年轻人差不多的老同事。这类同事工作勤恳,保质保量,人也很nice, 但是每当想考虑晋升机会的时候,总是拿不出像样的亮点帮他一把。这部分人很多是工作能力提升以后,能力圈没有跟上导致的。这里并没有对老同事不敬的意思,我也承认有些老同事是因为性格或自主选择的因素在一个职位上做很长一段时间。

级别之间的数量级差距是挑战也是巨大的机遇。因为这也意味着每提高一级,会筛选掉大约等数量级的人,这也就意味着你具备了竞争更好的职位和薪酬的机会。近几年,很多人都感慨说「IT行业的红利要逐步过去了,我们会不会成为下一代失业的民工?」,也有很多开发者不无担心的说「AI都会写代码了,会不会让程序员失业?」其实,这种担心至少目前来说是多余的。要知道,在人类发展历史上,无论是第一次工业革命还是第二次工业革命,淘汰人的不是机器而是更优秀的人。至于AI,现在只能说是「智能的人工」,依然任重道远。

第五级工程师容易犯的错误

上面说了五级工程师其实不是一个容易达到的级别。一般来说,主程、核心开发人员可以认为是这个级别。对应到医疗体系的话,至少是主治医师才能算第五级。吴军老师在文中举了一个第五级工程师的例子,方便大家自我评估:

这个人在京东公司任职,老板让他做一个工具,找出那些不断帮助女(男)朋友买书的读者。他自己知道在公司内找谁去要数据,如何确认两个人可能是男女朋友,而且经常买书。也知道自己在京东公司的环境里,应该使用什么样的开发工具。以及为了方便客户使用,这个工具应该有什么样的基本功能。

如果你达到了第五级,恭喜你已经登堂入室,可以欢快的向第四级工程师进发啦。但是就我身边的观察,很多达到这一级别向后发展的路上,往往容易走一些弯路:

  1. 逐渐进入舒适区,从脑力劳动者变成体力劳动者。「擅长主动学习和喜欢迎接挑战」说起来容易,其实在长久的工作中是一个特别难坚持的事情。练级之路没有捷径,学习和成长本来就是痛苦的,习惯这种痛苦吧。
  2. 喜欢研究武器,但是却不上场杀敌。我身边C++背景的人尤其容易犯这个错误(此处感觉要被C++开发者喷):喜欢研究因为语言历史和设计问题导致的一些晦涩且trick的用法,自觉高深,但是工作输出上却缺乏善可陈。在公司的整个商业行为中,技术是其中的一个环节,如果你不是那么确定自己要在这个技术方向上发展十年,那么你花一定时间研究这些技术是可以的,但是一定不能忘了公司是有成本和效率要求的。
  3. 容易陷入「技术做了N年,要不要转管理」的怪圈不能自拔。上面提到了,每升一级,需要能力和能力圈的同步提升。因此「转管理」对于不准备丢掉技术的工程师来说本身就是一个伪命题。你的影响力在第五级达到一定程度的时候,即使你没有职位的授权,你推动很多事情都是流畅和自然的。工程师喜欢扁平文化,而且个个骨子里闷骚、桀骜不驯,如果不能服众的话,转不转又有什么意义呢?喜欢看热闹的同学可以围观一下v2ex上的隔壁组的小兵集体情愿 要炒了 team leader.
  4. 喜欢用跳巢来涨薪酬。准确讲,这种行为并没有对错之分,只是一种个人选择。但是,我希望你是因为自己能力全方位提升以后,公司暂时没有适合你的职位和项目供你晋升,而不是仅仅作为一种手段。

第四级工程师容易面临的瓶颈

如果你成功完成了第五级的修炼来到了第四级,那么我觉得你至少从薪酬上已经超越了80%的IT从业者。这个级别的典型的工程师有:巨头里的小组负责人、高级工程师,中小互联网公司里的技术总监、CTO、架构师、DBA等。对应到医疗体系的话,至少需要是医院的科室主任。

这个级别是我们日常工作中经常打交道,同时心里默默认为是聪明人的最多的群体。这个群体聪明、勤奋、好学,是其负责的具体工作的佼佼者。很多人,发展到了这个阶段也就是其职业生涯的最终阶段了。除去自主选择停留在这个等级的那部分人,更多的人是卡在了对整个商业行为的理解,或者说是认知升级没有跟上。

很多工程师,脱离了公司或者组织,是不知道如何赚钱的。如果希望继续升级,一定要建立对整个商业行为完整的认知。具体到操作层面,可以在公司内部孵化项目或者产品,然后推向市场。整个过程中,你自然会学会如何争取资源、利用资源,如何在修海湾大桥还是修浮桥之间决断,如何做获取种子用户、如何营销、如何做市场放大推广,如何调整模式验证模型,最终实现变现。最终变现的规模不需要达到一个亿的小目标,公司项目或产品能到100w流水就够了(如果你在巨头工作,你当然可以花半天时间就刷到100w,但是聪明的你一定知道我不是这个意思……)。如果公司暂时不能提供资源进行项目孵化,那么可以尝试独立开发者做side project(但是不应该占用工作时间). 个人项目变现规模我觉得10w就够了。这个数字并不难做到,如果你感兴趣的话,可以随便看看INDIE HACKERS 上面开发者的经验之谈。当然,这个过程不会非常顺利,大部分时候,你可能最终是学会了「如何cancel项目」,但是,谁TM care呢?少年,勇敢站起来继续lu…

如何成为第三级工程师

很遗憾,鄙人也还在仰望这个级别,更多是思考这个层级人的特质,见贤思齐。如果你觉得自己做到了这个级别,欢迎发表您的高见。

这个层级的典型人物有巨头的部门leader, 产品leader(微信张小龙应该算第2.5级),中小公司的CEO。也就是我们大部分时候泛指的换联网那部分「财务自由」的人。对应到医疗系统,应该是院长这个级别。一路上,接触了不少这类人,他们身上也的确有一些特质非常吸引人:

  1. 敏感,且往往是个不错的产品经理。
  2. 喜欢并擅长深入思考,具有良好的思维体力,并且将思考作为日常的马拉松。
  3. 迫切,近乎疯狂的要结果。
  4. 谈情怀,也谈使命感,但是执行上非常务实。

复利思维+正态分布

不仅是作为一名工程师,其他各方面的发展和成长都免不了挫折。但是一定记住复利的魔力:如果我们选定了做一名优秀的工程师,在做计划和选择的时候争取做到自己的每一步都是在自己之前积累的前一步上的。否则,在原地周围折腾是难以发生质变的。时代发展太快,可能很多人心中都缺乏安全感,但是试想你手里如果握着一个几年以后可以增长数十倍的筹码,心里也就不再慌张了。

另一方面,中国的国情之一是人口基数大。天朝的工程师群体虽然占人口比例不算大,但是基数已经非常大了(千万级)。改变不了规则就尝试去争取自己的位置。只要你超过了平均水平之后,越往前,惯性越大,竞争的人越少,看到的机会越多。所以,不要抱怨房价一直上涨了,房子毕竟是要卖给能够支付得起售价的人,如果我们当前买不起房,很可能只是我们当前的位置拖了社会的后腿?

成为稀缺

任何时候,稀缺的人才都不愁机遇。最近也在思考一个工程师的核心竞争力和不可替代性是什么。看到了刘未鹏的一篇分享,挺有感触,摘录如下:

个人的核心竞争力是他独特的个性知识经验组合。这种组合1)绝无仅有;2)在实践中有价值;3)具有可持续发展性。

具体到工程师来说:

  1. 专业领域技能;
  2. 跨领域的技能;
  3. 学习能力;
  4. 性格要素。

小结

我所说的,必然不可能都对,取走你所需要的。新的一年,祝大家开工大吉,升级顺利!

Golang多级内存池设计与实现

Golang多级内存池设计与实现

上个月,牙膏厂intel因为MeltdownSpectre两个bug需要给CPU固件和系统打了补丁。我们生产环境使用的是阿里云,打完补丁后,几台IO密集型的机器性能下降明显,从流量和cpu load估计,性能影响在50%左右,不是说好的最多下降30%麽?

在跑的业务是go写的,使用go pprof对程序profiling了一下,无意中发现,目前的系统gc和malloc偏高。其中ioutil.ReadAll占用了可观的CPU时间。

ioutil.ReadAll为什么慢?

这个函数的签名原型是func ReadAll(r io.Reader) ([]byte, error). 团队的小伙伴非常喜欢用这个函数,其中一个原因是这个函数可以将r中的数据一次性读完返回,不需要关心内存如何分配、如果分配的内存不够了,如何进行内存扩张等。作为一个util函数,这样设计是完全没问题的。但是,IO密集场景下,这个函数的开销就是你需要关心的了。这个函数实际调用realAll读取数据:

其中,capacity是常量值512. realAll函数在调用buf.ReadFrom进行数据读取:

看到这里,原因就非常清楚了:如果要读取的数据大小超过了初始buf大小(默认初始大小为512 bytes), 则会重新分配内存,并拷贝内容到新的buffer中。如果要读取的数据非常大,则会重复多次上述操作。那么优化的问题就转化为如何降低内存重分配和拷贝。

多级内存池的设计和实现

  1. 内存池被按照大小被分为多级。如上图所示,(0, 1024]使用level 0, (1024, 2048]使用level 1. 内存池分级有两个好处:
    1. 可以灵活的规划不同级别内存池的总大小和item数量,适应不同业务。
    2. 实现层面上,可以将一把内存池大锁拆分成多个小锁,减少锁争抢。
  2. 当已分配的内存池耗尽需要扩张时,一次性申请一大块内存,提高扩张效率。如level 0所示。
  3. 代码实现gmmpool,bench结果显示性能提高约19倍:

小结

对于频繁进行内存分配和释放的场景,使用内存池可以显著降低golang运行时的开销。同时也要注意,内存池的内存交给了用户管理,你需要小心检查是否存在内存泄露问题。如果你对性能要求没有这么苛刻,只是想复用一些小对象,那么我们推荐你使用标准库的sync.Pool.

另外,开头提到的阿里云性能问题,即使使用了内存池优化,结果还是非常悲剧。最后阿里云帮我们更换了没有打牙膏厂补丁的机器解决。是不是非常惊喜??