2013年7月19日星期五

50 年前的黑客黑什么?

19 世纪 60 年代,个人电脑还没有出现,两位 Steve 还没有把苹果电脑发明出来,那当时的黑客黑什么呢?黑电话网络。其中最著名的例子应该是两位 Steve 发明的蓝盒子了——只要用它来拨号,就能免费拨打长途。那到底蓝盒子的原理是什么?如果你好奇心足够重,就应该去看一本叫做《Exploding the Phone》的书。

这本书先介绍了一下 AT&T 的简史。在贝尔发面电话之前,垄断美国的网络是西联电报。当时电报存在一个技术难题,就是一条线路只能走一个信道。由于想要发电报的人越来越多,而扩建线路的成本并不低,所以西联电报尝试研究信道复用技术。当时研究信道复用的人很多,大家都认为谁先研究出来了就可以高价卖给西联电报,贝尔也是竞争者之一。不过贝尔更爱声学,所以他想要通过线路来传播声音。在他看来,如果线路能传播和声,那就相当于能够复用了——不同频率的声音相当于不同的信道。最终贝尔发明了电话,西联电报认为这是玩具拒绝购买,贝尔只好创立自己的公司来建立电话网络。

最初的电话是点对点的,也就是两家公司需要经常联系的话就铺设一条电话线路连接这两家公司。很快贝尔就意识到这限制了电话网络的扩张,所以引入了交换局的概念——多个家庭接入一个交换局,然后任何人拿起电话都可以跟交换局的接线员说要接给谁,接线员就可以帮他接通电话。随后交换局发展到可以通过干线和其它交换局连接起来,于是大家可以跟接线员说「请帮忙接某某区第几局谁谁谁」,接线员就会接干线到某某区第几局,然后跟该局的接线员谁接谁谁谁。

在搞掂美国东部几个大城市的电话网络后,贝尔意识到电话专利还有 10 年就要过期了,过期后就会出现非常多的竞争对手,所以贝尔尝试利用这 10 年来建立美国的长途电话网络,随后以此来跟竞争对手的本地电话网络竞争。事实证明这个策略是正确的,电话专利过期后每个城市都有若干电话公司成立,贝尔的做法就是打压这些电话公司——要么你被我并购,要么你跟我合作,否则我不让你接入长途网络。最终 AT&T 形成了,并且成为了一个受司法部认可的垄断企业。

这时候电话网络已经演变出电话号码来,但仅用于同一交换局内。如果你要打一个长途电话?你还是要跟接线员说「请帮忙接某某市某某区第几局号码多少多少」,然后她帮你接到某某市某某区第几局,再让那个局的接线员完成拨号。北美的电话号码格式都是 +1 (XXX) YYY-ZZZZ,其中 ZZZZ 段就是同一个交换局下面的电话号码了。后来,交换局也变成了号码,于是就有了 YYY 段,但长途电话还是要找接线员。

让长途电话也变成号码,这是 AT&T 的迫切需求,同时也是技术难题。迫切需求,是因为 AT&T 雇佣的接线员越来越多,按照网络扩张速度来看,AT&T 估计要雇佣一百万的接线员才能覆盖整个美国,而美国根本不可能提供那么多的人力资源来做接线员。技术难题,是因为无法为任意两个城市建立直接连接的长途干线,所以需要接线员来手动路由。有时候接线员不知道该怎么路由了,还需要接转入局接线员,因为她们是接线员的接线员,专业接转出局接线员无法路由的电话。

最终 AT&T 成功通过机器加打孔金属片解决了这个问题。所有的路由信息都记录在打孔金属片上,机器能够智能地选择下一跳交换局,在本交换局到下一跳交换局干线全部被占用的时候还能智能地选择另一个下一跳交换局。不过这里还有一个小小的问题:过去目的地电话号码都是接线员之间口述传递的,直到最后一跳的交换局才拨打本地号码,现在通过什么方式来传达目的地号码呢?既然接线员能够口述电话号码,AT&T 的工程师想,那让交换机和交换机通过音频线路来传递电话号码也可以吧。于是一个史无前例的网络漏洞就诞生了。

这本书每一章都是一个独立的故事,讲述一个人或者一小群人如何发现 AT&T 的这个网络漏洞然后加以利用。尽管随着科技的发展,这个漏洞和利用方式都在变化,但不同时期都有人发现了这个漏洞。在接线员消失以前,有人找到转入局号码并且拨进去假装上一跳接线员要求转接,因为计费发生在第一条接线员那里,所以转入局接线员总会无偿转接。在接线员消失后,有盲人发现对着电话吹口哨就能拨打免费电话。再后来,晶体管的出现使得蓝盒子成为可能。

简单来说,这个漏洞是这样子的:计费永远只发生在第一跳的交换机,如果你在第一跳交换机拨打一个免费电话,整个会话它都不会进行计费。美国的目录服务(相当于中国的 114)是免费的,包括长途拨打其它城市的目录服务也是免费的,所以你可以拨打一个长途目录服务来开始一个不计费的会话。接下来你需要对着电话发出一个 2600 Hz 的声音,这个声音是两台交换机之间用来表示干线闲的声音。你第一跳的交换机听到这个声音后会无视它,因为你是电话不是交换机。但第二跳的交换机就会以为干线闲,那对它来说意味着第一跳的交换机把电话挂断了。接着你终止 2600 Hz 的声音,第二跳交换机就会以为第一跳交换机再次连接同一条干线,并且有一个新的长途电话需要接通。这时候你就可以通过音频指令向第二跳交换机进行拨号了,无论你拨什么号码它都会为你接通,而且计费责任不在它身上。第一跳交换机会把整个过程看做你原先那个免费长途电话,因此也不产生计费。

在 50 年前,AT&T 不能像 Facebook 一样发个 hotfix 就立即对所有服务器生效,AT&T 也不能像 Microsoft 一样发个 hotfix 然后等着用户下载生效。面对这个漏洞,AT&T 的工程师估计需要几亿到几十亿美元的成本来更换所有的交换机。至于更换交换机后能否保证不再有漏洞,那肯定是不保证的。所以,在那 10 年的时间里,AT&T 想方设法制止别人利用这个漏洞,但同时又要尽量避免见报,因为见报了就会有更多人仿效。

在这期间,黑客使用各种手段来探索电话网络的秘密。他们找到了电话网络中的回路,也就是 IP 网络 localhost 的始祖——你拨打电话给回路号码,它会录音一段时间,然后它会自动回拨并播放录音。回路的作用跟 ping localhost 相似,就是测试一对线路是否联通。他们找到了免费的电话会议入口——某些无效号码会把所有来电都接到一跟线路上,然后播放号码无效的录音,只要你大声说话所有人都能听见。他们甚至还找到了从民用电话网络劫持交换机介入军用电话网络的方法。

最终,晶体管使得程控交换机成为可能,这个漏洞才被堵住了。(中国基本上没有部署过机电交换机,直接从接线员时代进入程控交换机时代,所以这个漏洞几乎不曾存在过。)晶体管同时使得个人电脑成为了可能,原本热爱探索电话网络的黑客找到了新的探索方向,例如两位 Steve 就发明了苹果电脑。最终黑电话网络的 10 年结束了。至于那 10 年里都发生过什么传奇故事,大家可以去看那本书慢慢了解,我就不剧透更多了。

2013年7月9日星期二

赴美工作常识(Part 2 - 申请)

在《Part 1 - 签证》的评论中有人提到,说我还没说如何申请职位就说签证的事情了。一方面,签证的周期决定了你申请职位的时间,错过关键时间点的话就可能错过重要的机会。另一方面,传统意义上的「申请」其实不是我的强项,而我个人的做法可能对大多数人来说是不容易实践的。

首先需要说明的是,我在找工作时有两件事情是绝对不做的:

  1. 大量投简历给众多公司
  2. 为面试做任何应试准备

我找工作基本上靠内部推荐,所以我是不会投简历给众多公司的。这不仅仅是因为内部推荐会使得公司更重视,还因为我需要了解一家公司是否适合我。一家公司如果没办法吸引到我身边跟我志同道合的好友,那么它对我的吸引力也相对有限。(我选择豌豆荚的时候就是因为我认识里面不少人,并且这些都是我信任的人。)通过认识的人,我可以了解到这家公司的文化以及前景,这对我来说是非常重要的。

对于面试,我从来不尝试通过应试的方式来准备。我觉得我懂什么由我的兴趣来决定,没兴趣的事情我没必要通过机械训练来假装懂,有兴趣的事情我会研究清楚你喜欢跟我讨论什么都可以。这使得我能通过的面试都是我真正喜欢并且胜任的工作。当然,这不意味着面试前不能巩固一下自己已经掌握的知识,因为有些自己很感兴趣的事情一段时间不接触也会生疏,如果你拿我两年前的技术文章来问我很可能我也说不清楚细节。

把前提条件说清楚了,我们就可以进入正题了。

名声

听说过 Google PageRank 的人都应该知道,PageRank 的核心思想是把链接当做投票(或是论文中的引用),你的页面被其它页面链接的次数越多,那些页面自身的 PageRank 越高,你的页面的 PageRank 也就越高。同时,在做关键字匹配的时候链接的文字比你页面内容的文字更重要,如果有一个 PageRank 很高的页面链接到你的页面且链接文字是某关键字,就算你的页面内容完全不包含这个关键字也能用这个关键字搜索到你的页面。简单来说,你说你是谁并不重要,重要的是别人说你是谁。

基于同样的道理,其实你在简历上说你做过什么并不重要,至少没有你想象中的重要,真正重要的是在别人怎样说你。(简历的问题后面再说。)所以最简单的方式是去 Stack Overflow 上面回答问题,和去 GitHub 上面参加开源项目。

Stack Overflow 的门槛相对低一些,只要你敢于用英文和别人交流就行。问题并不比各种中文技术问答论坛要难,可能对于大部分人来说难度在于理解问题和用英文说清楚自己的答案。对我来说,通常看 10 个问题只有 1 个是可以回答的——有几个是问题质量太差而不值得回答的,有几个是不懂所以无法回答的,有几个是已经有很好的答案不需要重复回答的。如果你阅读问题的速度太低,建议还是先通过阅读技术书籍来提高,否则挑选问题的速度会很低。在挑选到合适的问题后,你就可以答题了。Chinglish 不重要,但写完一定要检查一遍避免犯低级错误。

GitHub 的话,要对一个项目作出贡献先要对它有相当的了解,所以门槛不低。我曾经见过有英文文章推荐一种很好的切入方法:找一个你感兴趣的知名开源项目,然后寻找它缺乏单元测试的地方,尝试帮它写单元测试。这会驱使你去研究待测代码,因为如果你不知道这些功能的边界在哪里,你是没办法写单元测试的。写好单元测试就发 pull request,一般对方是不会拒绝的,因为这绝对是纯粹的贡献,不会跟项目主导者所设想的项目发展方向有任何冲突。如果代码本身就写得完全不可测?那你就可以动手重构代码,让它变得可测,这同样会驱使你去研究代码。

简历

我偶尔会收到陌生人的简历,一部分是让我帮忙推荐给公司的,另一部分则是让我对简历提出修改建议的。我发现大多数人的简历都会包含过多的信息,结果就是重点不突出。

要写好简历,首先要理解别人是怎么读简历的。如果现在有 100 份简历放在你面前,要你挑 10 份还可以的,以及 1 份特别出众的,你会怎么读?可以很肯定的是,你不会把这当做考纲中的必考内容一页一页仔细读。你会先抽样一部分粗略看一遍,以便确定这些简历的基准线在哪里,然后才能确定那 10 份的期望是多高,那 1 份的期望又是多高。接着你以那 10 份的期望为筛选标准来看这 100 份简历,达不到期望的直接扔掉。有可能你最后剩下 15 份,你会再看第二遍并且扔掉 5 份;也有可能你最后剩下 8 份,这时候你凭记忆把接近这 8 份的另外 3 份找回来,再扔掉 1 份。最后,你从这 10 份里面挑明显好的 1 份出来。

可以说,这 100 份简历里面有 8 份是毫不犹豫能够留下的,有 85 份是毫不犹豫可以扔掉的,剩下的 7 份才是需要仔细阅读对比的。如果你的目标是成为那少部分人——直接通过的那少部分,而不是让人纠结的那少部分,那你就应该分析清楚自己的优势在哪里,并且只提能够证明这些优势的重点。多余的信息没必要提,提了只会降低信噪比。

为了适应人的阅读习惯,必须注意一下排版,引导读者的视线从上往下看,并且突出关键字。入门的话,读一下《The Non-Designer’s Design Book(写给大家看的设计书)》就足够了。前端工程师可能经常接触到网格式布局,其实道理书中也说得很清楚,就算你不理解的话你按照这种方式去设计简历也会发现可读性更高。

最后,现在主流放英文简历的地方应该是 LinkedIn。很多美国公司都会购买 LinkedIn 的服务来搜索简历和联系潜在的候选人,所以就算你已经有了很好的个人网站最好还是在 LinkedIn 保存一份简历副本。

在上述一切准备就绪之后,就可以接触公司了。找人内部推荐,或者在公司网站上传简历,其实都可以。值得提醒的是,如果你有计划要找人内部推荐,就先别自行上传简历,否则推荐可能被视为重复上传,最后系统有可能不承认这是推荐。

关于申请我能想到的就那么多了。前期工作做得足够好的话,可以省掉后期临急抱佛脚的麻烦。不要等到想换工作的时候才想办法证明自己的价值,要时刻保证自己的价值以便在想换工作的时候就能换工作。