startup 的安全问题

安全这个问题好像离绝大多数的 startup 比较遥远,好像谈到安全只有 BAT 这类规模的才会重视。
绝大多数的 startup 起家都是短糙快,怎么好搞怎么搞,怎么方便怎么搞,怎么省事怎么搞。再加上「绝大多数的创业公司都喜欢宣称自己是「平均年龄25 的年轻团队。」,正面理解起来是有活力的团队,反面理解起来,其实代表的是「招不到人,只能忽悠年轻人,组建的一只没经验靠人力时间堆砌的弱逼团队」」,其整体的安全性可想而知。
这或许在初期并没有什么问题,因为本来知道你的人就不多嘛,cracker 们也没兴趣花时间在只有几千几百用户的上团体上。
但是如果你很幸运,成为了那百分之几甚至千分之几的存活下来的,那就是另外一回事了,你们的产品会在短期内被很多的用户知道,得到了不少用户的认可,用户数量逐渐变多,接下来可能要经过一段爆发性的增长,一方面来说是好事,但是,另外一方面,对公司整体的技术也是一个非常大的挑战,再加上很多都是没什么经验的工程师,真的就是摸着石头过河了,在这期间,会经历若干次的宕机服务不可用事故,为了尽快的 available,不得不牺牲很多方面,正所谓 tradeoff,比如牺牲了安全。
然后名气慢慢大了,积累的用户数量在圈子里面也数一数二了,白帽子也好黑帽子也罢,都对其产生了很大的兴趣,随便扫扫,就发现了不少有价值的信息,至于什么信息大家自己补脑吧。
好在有类似 wooyun 这样的平台,突然有一天 startup 在 wooyun 上收到了一封「弱口令」(关于弱密码的危害,请看这里)的漏洞提交,至此,公司开始对安全有了一定的认识,发现原来弱口令还是导致直接渗透到内网,于是上上下下一顿整改,但这毕竟只是冰山一角,前几年为了方便留下的祸患太多了,接下来,不停的收到若口令、权限绕过、设计缺陷等等各种各样的漏洞报告。虽然大多数人都很重视这类问题,积极的配合整改,但总会有那么些人不以为然,认为这些事情不值一提,根据 2/8 原则,80% 的漏洞都是由 20% 的人造成的,直到某一天,发现公司的用户信息、代码被拖库了,傻眼了。
上面可能是很多 startup 都要经历的过程:为了方便随便上线,携带敏感信息的配置文件不加任何处理,无任何限制的开放对内服务的访问权限,弱密码,以上还仅仅是技术层面的因素,如果遇到叼炸天的工程师自以为是等人为非技术因素,后期需要改进沟通的更是难上加难。
出几次事故也未必是坏事,最起码让我们明白,不好好对待这个问题,迟早是要出大事的,用户信息泄漏了导致公司陷入危机的不在少数,那些处在风华正茂认为老子(或许有老娘这么一说)天下第一无人能敌写代码如行云流水天马行空 bug free 的也是会出些非常低级的错误的。很多东西,尤其是安全,仅仅是从技术层面加以控制是完全不够的,更多的是需要从行政手段上加以干预,有奖有惩,才能从根源控制。当然,上面说的这些尤其是最后一点在一个仅仅发展了两三年,连基本的工程师制度惩处措施都没有,没有强大的执行力或者说是重视此问题的有话语权工程师的干预下,是不可能做到的。

最近半个月的工作[14P]

5 月发生的事,6 月补充完,9 月发出来 ;-)


5 月 13 日周二
开始我们另外一个核心 IDC 最后一次常规性 10G 升级,下面的一部分我们后来把他总结成了《5 月故障总结(post-mortem)》
回家睡了会儿,3:00 am 起床,4:00am 开始连续干了 6h
回公司休息了 1h,塞了点巧克力复活
中午去水立方进行了常规的 1h 训练
回来面(对了,我们目前招高级应用运维工程师 PE,有兴趣的给我简历,邮箱是 w 在 umeng 点 com)了一个候选人,结果在我问到第二个问题的时候就怂了,第一个问题是常规性的自我介绍,第二个问题也是我最喜欢问的问题之一,最近半个月在做什么
由于 uplink 依然在老的网络环境中,我们老的 3750X 到新的 Nexus 中间的 8G port channel 链路中的一条物理链路由于 LB 的算法不科学,导致其打满丢包的状态,当机立断,直接让 NE 更改了 LB 的算法,效果明显

5 月 14 日周三
由于 uplink 这个不稳定因素的存在,开会讨论最后一次也是最重要的升级以及收尾工作,由原本的周四凌晨升级提前到了周三凌晨进行
10G 的最后一次也是最重要的升级,应为涉及到切换我们的 uplink,迁移我们的 GW 以及我们两地双机房中间的互联链路迁移
晚上去和颐休息了 3h,凌晨 3 点干到早上 7 点,期间除了 uplink 切换成功之外,其他的均已失败回滚告终,回酒店休息了 3h
中午回公司继续,讨论了凌晨出现的一些问题以及解决方案,其中我们两地双机房互联链路不通的问题最后发现是 HSRP 的问题
凌晨 GW 迁移失败之后,我跟我们 ne, director 回公司模拟了一下当时出现问题的场景,想了几种可能的原因,不过都被实际的模拟结果所否定,唯一的可能性就是服务器会自动的更新 arp 表,找到新的 GW 地址
下班之前,上面遇到的所有问题都已经找到了问题的根源,想到了对策,唯独 GW 的问题,这个对我们整个生产环境的影响绝对是毁灭性的,一旦 GW 迁移失败,我们所有跨 VLAN 的访问都将失败,由于当时时间太紧迫,根本没有时间让我去 debug 就回滚了,我也就无法得知当时真正的现象以及后续的细节
临走之前,我们 director 问我要不要他过去帮忙,我当时是拍着胸脯说的「相信我,你回家休息吧」,虽然我当时有 95% 的把握确认了上面提到的迁移失败的原因以及 80% 左右的把握让我在非常短的时间内 debug 找到问题并且修复,其后者是最具有挑战性的

现在看到的我们的还是 1G 的上联,等你看到这篇博客的时候,应该已经升级到了 10G 的上联了

5 月 15 日周四
这次升级提前预留了充足的时间,从 3:30 – 6:00,我觉得 3h 的时间足够我 debug 一个中等难度的线上问题了
跟昨晚一样,先是回酒店休息了一下,凌晨 2 点开足马力一直干到了早上 8 点多,GW 的问题也在我们开始的第一步被我很快的发现了问题的原因并且修复,两地双机房互联 HSRP 的问题也后续被我们 ne 一举解决,「基本完美」收官,为什么这么说?因为后续的几天出现了若干的问题,好在都不是我们核心的 Nexus 引起的
回酒店休息到 11 点,打车回家准备继续休息,结果在车上就收到报警说我们的一台前端的 ngx 挂了,当时电话跟我们工程师沟通了下,看现象不大像是新升级的网络造成的,回家又花了 1h 时间救了把火,最后查明原因发现确实跟网络没有关系,只不过在这个敏感的时间点上,出现任何的问题,正常人都会不由得往网络上面倾斜
下午先赶到公司跟我们 director 沟通了进展的,然后赶到清华,在那儿度过了下午剩余的时间,干嘛的了?我花了 3h 的时间去拜拜 RMS 大神,花了 1h 的时间跑到教室外面的走廊插上了 3G 网卡排查了一起路由问题
RMS 大神确实蛮有意思的,下面这三段视频是我当时在现场拍的,虽然 RMS 说不要把这些视频照片传到 youtube, instgram 上,但我还是本着共享的精神跟大家分享了:

  1. Windows is malware
  2. Dancing during class break
  3. St. iGNUcius avatar

下午在会场收到反馈说,我们某个 storm cluster 的处理性能出现了问题,时间点跟我们升级网络的时间几乎吻合,但是从我们内网的各项监控指标来看,数值得到了前所未有的好转,pkg loss 由原来的 8% 直接变为了 0,latency 也由原来高峰时期动辄 4, 5ms 直接下降到了 0.2ms 以下,直觉告诉我几乎不可能是核心网络引起的,但是,没有更有力的数据来证明这些
看码农们在邮件里面以 「猜测」、「推脱」的姿态开始了问题的 debug 之后,我直接以「明天人齐了一起讨论下吧。」结束了这场闹剧
听完演讲之后本想回公司报个销就回去休息的,结果的结果,碰巧我们一个核心业务线上出现了很严重的性能问题,伴着麦当劳雪碧继续搞到了接近凌晨,没找到的问题原因,但是紧急扩容了一些机器,情况有所好转

两个出口的 ngx 都挂了


两个出口的流量一个跌没了一个直接爆了

Continue reading

ops 的 technical support

Technical support 是一项非常有挑战性的工程。做 ops 的多少要遇到一些这类的问题,对外你是客户,厂商给你提供技术支持;对内,你需要服务客户,给很多分不清 ip 是什么如何做 bind 的码农们提供技术支持敦促其改进。
每次客户的系统出问题,你屁颠屁颠的跑到现场去花了几天几夜帮他修复了一个非常棘手的问题,自然值得骄傲,但是如果有比这个更好的方式,为何不试试看,很高兴的看到,有很多的公司已经在这方面做的很完善。
首先说说我们的老合作伙伴,RedHat,一般系统出了问题,我们会先排查,不到万不得已不会去开 case,我觉得这是对大家的尊重。开 case,自然要讲清问题发生的背景,现象,可能的原因等等问题,尤其是前两者,这需要你话费很大的时间以比较精炼准确的语言去描述,这样对方的 technical support 才能尽快的领悟到问题所在,尤其是一个涉及多个层次的复杂的系统问题。人跟动物最重要的区别就是人类会使用工具,好的工程师能写出大大解放客户双手,同时提高自己获取背景信息的好工具,sosreport 就是一个明显的体现。
其实原理一点都不复杂,就是一个 python 脚本,把当前的系统做了一个 snapshot,将重要的基本配置信息全部打包到了 sosreport-HOSTNAME.CASENUM-DATE.tar.xz 这个文件里面了,解压开来无非就是一些系统的信息文件:
# ll /tmp/HOSTNAME-2014052115241400657060/
total 44
drwxr-xr-x  3 root root 4096 May 21 15:24 boot/
drwxr-xr-x 36 root root 4096 May 21 15:24 etc/
drwxr-xr-x  3 root root 4096 May 21 15:24 lib/
drwxr-xr-x  7 root root 4096 May 21 15:24 proc/
drwxr-xr-x  2 root root 4096 May 21 15:24 root/
drwxr-xr-x 30 root root 4096 May 21 15:24 sos_commands/
drwxr-xr-x  2 root root 4096 May 21 15:24 sos_logs/
drwxr-xr-x  2 root root 4096 May 21 15:24 sos_reports/
drwxr-xr-x  4 root root 4096 May 21 15:24 sys/
drwxr-xr-x  5 root root 4096 May 21 15:24 var/
lrwxrwxrwx  1 root root   37 May 21 22:51 chkconfig -> sos_commands/startup/chkconfig_–list
lrwxrwxrwx  1 root root   25 May 21 22:51 date -> sos_commands/general/date
lrwxrwxrwx  1 root root   27 May 21 22:51 df -> sos_commands/filesys/df_-al
lrwxrwxrwx  1 root root   31 May 21 22:51 dmidecode -> sos_commands/hardware/dmidecode
lrwxrwxrwx  1 root root   24 May 21 22:51 free -> sos_commands/memory/free
lrwxrwxrwx  1 root root   29 May 21 22:51 hostname -> sos_commands/general/hostname
lrwxrwxrwx  1 root root   35 May 21 22:51 ifconfig -> sos_commands/networking/ifconfig_-a
lrwxrwxrwx  1 root root   81 May 21 22:51 installed-rpms -> sos_commands/rpm/rpm_-qa_–qf_NAME_-_VERSION_-_RELEASE_._ARCH_INSTALLTIME_date_–
lrwxrwxrwx  1 root root   48 May 21 22:51 java -> sos_commands/general/alternatives_–display_java
lrwxrwxrwx  1 root root   35 May 21 22:51 lsb-release -> sos_commands/lsbrelease/lsb_release
lrwxrwxrwx  1 root root   25 May 21 22:51 lsmod -> sos_commands/kernel/lsmod
lrwxrwxrwx  1 root root   36 May 21 22:51 lsof -> sos_commands/process/lsof_-b_M_-n_-l
lrwxrwxrwx  1 root root   27 May 21 22:51 lspci -> sos_commands/hardware/lspci
lrwxrwxrwx  1 root root   29 May 21 22:51 mount -> sos_commands/filesys/mount_-l
lrwxrwxrwx  1 root root   38 May 21 22:51 netstat -> sos_commands/networking/netstat_-neopa
lrwxrwxrwx  1 root root   30 May 21 22:51 ps -> sos_commands/process/ps_auxwww
lrwxrwxrwx  1 root root   27 May 21 22:51 pstree -> sos_commands/process/pstree
lrwxrwxrwx  1 root root   32 May 21 22:51 route -> sos_commands/networking/route_-n
lrwxrwxrwx  1 root root   22 May 21 22:51 sar21 -> sos_commands/sar/sar21
lrwxrwxrwx  1 root root   29 May 21 22:51 sestatus -> sos_commands/selinux/sestatus
lrwxrwxrwx  1 root root   28 May 21 22:51 uname -> sos_commands/kernel/uname_-a
lrwxrwxrwx  1 root root   27 May 21 22:51 uptime -> sos_commands/general/uptime
lrwxrwxrwx  1 root root   39 May 21 22:51 vgdisplay -> sos_commands/devicemapper/vgdisplay_-vv

这些信息对问题的诊断是至关重要的,正所谓一图胜千言,很多时候,一条命令胜过几千个单词的描述。

在这方面做的很优秀的的还包括 github,这个跟 RedHat 比,基本就是以黑盒子,我也没必要花经历去 hack 他,出了问题,很简单,直进到管理后台,把 "Download diagnostics info" & "Download support bundle" 的信息发送给他们就好了。

上面提到的两家公司的做法非常值得我们学习,比如可以用在对内的 technical support 上,依葫芦画瓢,执行一下 sosreport 是不是能很快的知道当前系统的整体状况,这比一群码农围着你,尤其遇到那种遇到问题完全失控的,你一言我一语的解释不清要高效的多。
technical support 是项很有挑战,需要具备综合能力,能站在高处俯视系统的工作;除此之外,还能提高与码农们沟通的能力,要知道大部分的码农都是不善于表达自己,很多时候,是无法把自己遇到的问题给表述清楚的,能把他们「哄」开心了,也算是一项不大不小的成就了。总之,多接些这样的活儿,虽然很费时间,尤其遇到一些非常 tricky 的问题,但是对提高自己的综合能力非常有帮助。

5 月故障总结(post-mortem)

14 年 5 月,友盟的几个核心产品由于各种因素的影响,对外表现了一些不稳定的现象,我作为最主要的当事人之一,有不可逃避的责任,为了给开发者一个交代,我总结了这么一篇 post-mortem。目前对外发布的版本出于迎合普通工程师的口味,我们的运营阉割了部分内容,除此之外,我们还做了一个给纯小白用户看的时间轴图片,更加的简介明了,说是《友盟万兆网络升级日记》并不能概括这段事件发生的事情。下面这个是我写的一个未经删改的 post-mortem,透露的内容还是很多的,同时技术性也更强。该版本基本的思路是参照 github, cloudflare 的 postmortem 套路。


上个月(2014 年 5 月)的 13 日至 27 日,包括我们统计分析、在线参数在内的服务出现了间断性不稳定的情况,给热爱我们产品与服务的开发者带了很大的不便,为此我们深表歉意与自责。

未经缜密计划安排的停机维护时间对我们来说在任何时间段都是不被允许的,作为一名全程参与整个事件的工程师,我非常乐意给我们的开发者解释一下造成我们这一段时间服务不稳定的原因,为此我们做了什么以避免今后类似的事件再次发生。

背景

2011 年 7 月我们开始在全国最好的数据中心之一部署上架了我们的第一台服务器以及交换机,当时的网络架构还是简单的 2960G trunk 模式。

转眼,到了 2012 年第三季度,我们这套简易的方案在处理内部流量时出现了比较吃力的问题,于是我们在 2012 年年底完成了我们三层网络架构的升级,有兴趣的可以看看我们工程师当时总结该次升级的博客(1, 2, 3, 4)。

在接下来的一年多时间里面,我们的业务出现了爆发性的增长,带宽也由最初的几十兆飙升了目前的数 G,在 2013 年年底,我们决定对我们部署着统计分析等服务的核心数据中心再一次进行升级,这一次,我们将由原先的 3750X 三层堆叠架构升级到 Cisco 最新最强大的万兆 Nexus 752 架构以支持更高的吞吐、更低的延时以及更好的服务器网卡冗余。

2014 年年初到 3 月底的这段期间,我们的工程师马不停蹄的进行着大量的前期准备调研工作,包括我们目前线网的梳理确认、综合布线、网络设备的上架调试、新老网的设备互联以最大程度的减小停机时间。

进入 4 月以来,我们又紧锣密鼓的讨论制定了各种潜在风险以及应对措施,回滚计划、网络以及业务连通性监控确认等方案。最终决定,一共分为 4 次常规性的迁移,将数百台服务器由老网迁移到新网,1 次互联网入口/出口流量以及网关的迁移,前后历时一个月。

4 月 03 日晚上 08:00,我们的内网由于延时过高,导致了我们实时处理的时间过长,触发了 Storm 的 timeout 机制,最终导致了我们的实时处理延迟了 10 小时,这也是第一次向我们的开发者发出由于网络原因造成数据延时的通知。为了加快进度,我们决定将原先定于 5 月初的第一次升级提前到 4 月末进行。

4 月 24 日凌晨,我们进行了第一批服务器的迁移,在我们开发默契配合下,完美的完成了此次迁移。在后续的观察中,我们发现新老网(3750X – Nexus 7000)之间的 4G 链路带宽利用率可能会比较高,于是我们紧急调度了我们供应商的资源,在 4 月 28 日将这条关键的链路扩容到了 8G 以提高更大的带宽。

4 月 29 日、5 月 8 日,我们又分批顺利地完成了第二次、第三次服务器的迁移。

Continue reading

1000 天的日日夜夜

11 年的 7 月 10 号来到这里,一周之后的晚上,跟我们 CTO 以及另外一个 TL 一起开始了我们第一个正式 IDC  的「破土动工」,机器是不会说谎的,下图是我们第一台交换机的信息。

May 22 2014 是我们第一台线上机器跑到 1000d 的日子,这是目前我们仅有的三台跑着 CentOS 5.6 2.6.18-238.el5xen 的机器;另外,也是三台仅有的跑着 xen 的机器,当年曾经穷的把 LVS 放在这上面跑。如果不是 208.5d 的 bug,估计同一时段会有很多的机器跑到 1000d,现在同时期上的那批机器不少都跑到了 600、700d。

三年时间发生了很多事,很多有趣的事,不少悲伤的事,没有永远的朋友也没有永远的敌人,只有共同的利益。

机器与人

机器跟人是两个不同的物种,目前,我的工作 60% 跟前者打交道,剩下的 40% 会跟「五光十色」的程序员、产品、运营、市场等打交道(总算不要跟销售打交道了)。
总的来说,机器比人好管理好沟通的多,因为机器没有欲望,你让他怎么做他就怎么做。当然如果你对他不熟悉不了解就想强上,一般情况下受伤是你自己,所以如果不想出现一些悲剧性的后果甚至是灾难性的,因此最好需要花时间去熟悉,然后再驾驭。
不管是机器还是人,最终都是服务以及被服务的关系,比如 A 机器提供 API 给 B 机器调用,这个可以看成是一个 client/server 的模型,如果 A 机器出问题了,对于 B 机器这个独立的个体来说,最坏的情况是 crash 了,更普遍的情况可能会是 stderr 或者打 log,你可以通过调查这些蛛丝马迹发现 A 「不爽」的原因。

人就不一样了,第一人有欲望(除非你信佛教),第二众口难调,举三个亲自经历很有代表的例子:
1. 公司每天中午的饭菜,我从 11 年吃到现在,吃了三年吃腻了,有时闻到油的味道就不想入口,当然有不少跟我同等感受的同事;但是观察下来你会发现,还有一部分同事看上去吃的蛮香的,并且跟他们讨论下来,他们也觉得饭菜还不错。这个是一个典型的众口难调的例子,期望不一样,结论也不一样,这不是期望越高失望越大么。至于什么出去玩,你想去 A 地我想去 B 地的问题那就更多了。

2. 上面说的是日常生活方面的,下面说两个技术层面的,虽然跟我们的 production operations 关系不大,但是原理是相似的。

2.1. 11 年我刚去友盟的那会儿,兼职接手了当时新办公室内部网络部署的摊子,没钱没人,只能让着我们的行政小姑娘帮忙打打杂,花了半个多月的时间搞定,信心满满的给第二天要搬到新地盘办公的员工发邮件告知。后来总结起来发现这事面向的是普通观众,大部分人都是不懂 tcp/ip 的,包括众多的分不清 gateway 为何物的程序员,而我当时写的又比较的专业,设想的情况太美好不切实际,比如竟然想到通过静态 IP 而非 DHCP 的方式让每个人去访问网络,所以当时的反馈并不是很好,收到了各种各样有理的无理的回复以及善良的建议,接下来又忙活了接近了 1m,才终于解决了这个问题。后期又总结了下出现这个问题的原因:
* 技术层面也就是网络的实现部署太过理想化,所以面对的大众即使是工程师的环境,也应该使用 DHCP 而非 staic IP
* 其次,对我们的客户的信息的传递上,普通客户就应该使用普通朴素的语言,最好能 step by step 的截图告知怎么操作
* 另外一点就是在出现问题之前没有综合的考虑可能出现问题的各种情况,不然等真出现问题再考虑就有点晚了
* 非主观因素就是,你面对的是一大波的客户,那就更面临着被骂的风险,这个做运营的因该很有体会,尤其是专门维护公司 twitter、weibo 账户的同学,应该是经常能搜到客户的不满以及发泄的,所以,这事最终的结论就是自己先把份内的工作做好,先满足大部分人的要求,在时间精力允许的情况下,再去满足那一小部分人的欲望以及口味

2.2. 第二个是关于我们内部的代码托管平台 github enterprise 维护的事,这事也是我前几个月接手。然后做了两件事,第一个是把我们的 instance 升级到了最新的版本,这个完全没有影响,第二件事是出于安全的考虑,将原来的公网可访问变成了只有通过 proxy 才可以访问内网的方式。这事从技术实现上来说同样不大,换下端口改下 IP 就好了。我索性快刀斩乱麻,加上前期准备花了不到 3h 的时间搞定了所有技术层面的事情。比较麻烦的是在告知我们的客户,也就是所有的友盟员工发生了这件事的大致经过以及结果以及最重要的,对他们的影响。吸取了之前的教训,再加上处理多了这类事情之后自然就轻车熟了。所以在使用了很通俗的语言描述了访问方式变化之后,排除一些垃圾回复(完全 OT 的,自己机器原因无法访问的)得到的反馈还是很正面的。

总之,跟人打交道是门学问,尤其是服务一些吃力不讨好的对象更是如此,要解决这个问题,无外乎这几条路径:
* 尽量少动,专业术语叫少变更,不到万不得已,不要手贱去惹事,实在要做,做之前问下自己,真的要做吗?
* 准备好事后处理的艺术,正如我 2.2. 例举的那个案例一样
* 做完之后正确的区分合理不合理的反馈以及建议,对于不合理的甚至是扯蛋的反馈,有时间有心情就回复周知一下,没时间直接 mute 就好,你很难满足所有人的胃口
* 交给别人做,把自己从火坑里面解放出来,迎接下一个火坑的到来

总的来说,跟机器打交道很简单,跟人打交道相比要复杂的多,有的时候后者或许比前者重要的多。