前段时间因为公司的一款手机APP产品经常遭到流量劫持,严重影响用户体验,因此对互联网流量劫持的原因以及可行方案进行了一些研究和测试,趁着清明三天小长假躺床上养病,梳理一下。全文都是po主根据之前一段时间的研究结合自己的理解一个一个字敲出来的,参考的一些文章,最后也列出,可以直接链接进去。由于po主水平有限,文章肯定有很多错误,希望大家不吝赐教。
一、劫持的方式分析
互联网的流量劫持大致分两种,第一种是DNS劫持,第二种是链路劫持。对于这两种劫持的原因有很多,比如用户电脑中毒了,DNS被篡改了,比如家用路由器被攻破了等等。但这种个人极端原因毕竟是少数,真正的幕后大佬(此处应该有广东话配音)其实是运X商(此处配有BB音),这其实已经是互联网行业公开的秘密,各大互联网公司早已经和各大运营商展开了一场旷日持久的撕胯大战,po主公司由于是金融行业,刚涉足互联网不久,还处于摸石头过河阶段,却也是感受到了我国互联网环境的水深。对此po主只有一句话,大家都是要被颠覆的行业,难兄难弟何必相爱相杀呢? 好了,废话不多说了,这是一个严肃的技术文档!!!
1、DNS劫持
首先我们要搞明白运营商为什么要劫持用户DNS呢? 用户跟你什么仇什么怨?
劫持原因基本分两类,第一类是为了跳转广告,第二类是本地缓存,总结一下就是为了——钱!
跳转广告比较好理解,我明明访问的是淘宝,怎么跳转成了一个不知名小网购网站,还和淘宝长的挺像。本来po是要以身试法,截个被劫持的图下来展示下的,结果访问各大网站1个小时,也没有一次被劫持,真心为电信点赞! 跳转广告这种方式由于过于芳草天,用户也不是傻子,运营商用起来也是比较谨慎,所以第二类本地缓存才是罪恶之源。
由于各运营商带宽资源、网间结算费用、IDC机房资源分布等存在较大差异,因此为了保证网内用户的访问质量,同时减少跨网结算,运营商在网内搭建了内容缓存服务器,通过把域名强行指向内容缓存服务器的IP地址,就实现了把本地本网流量完全留在了本地的目的。但是由于运营商对这些内容缓存服务器的使用的技术手段参差不齐,运维管理也不是很及时。通常会引起两个问题,一是当这些运营商的内容缓存服务器出现故障后,用户将无法访问到需要的资源,二是当源站已经有内容更新了,而这些运营商的内容缓存服务器并未及时更新,导致用户访问到旧资源,或者无法访问到资源。
其实运营商的DNS劫持的原理很简单,就是当用户向local DNS去请求某个域名的真实ip时,运营商的local DNS服务器回复了一个假网站或内容缓存服务器的ip,最终导致用户访问出现异常。当然一些劫持行为一旦被发现,运营商一般都会声称DNS服务器被黑,当然也可能声称临时工干的。DNS劫持由于其实现简单,无论是出于有意或无意的,目前被广泛的应用在互联网环境中。根据腾讯内部的统计,腾讯全国每日的DNS解析异常量达到80万条,并且这还只是一个抽样监测的结果。这对于企业的影响是非常恶劣,尤其在移动互联网时代,用户体验就是核心竞争力,因此DNS劫持的攻防之战也是一个互联网公司必须重视的课题。
2、链路劫持
比起DNS劫持的简单粗暴,链路劫持的技术含量更高,也更难被发现。最常见的就是页面蒙层,页面广告,页面替换等(这里的页面替换不同于DNS劫持,即使更换了local DNS依然会被劫持,所以更难察觉)。当然链路劫持还常常被黑客利用进行钓鱼或DDOS攻击等(近期比较有名的就是某邪恶组织利用百度联盟广告被恶意植入JS去DDOS攻击GitHub)。我们这里就不多谈个别极端情况,具体的黑客行为可以参考这篇文章《详解流量劫持的形成原因》
链路劫持的原理就是运营商(也可能是黑客)在用户访问网站的时候进行窃听,获取用户访问的目的ip后,然后以这个ip为source-ip冒充网站给用户响应,通常响应中会插入一段JS代码,这段代码可能会让用户去get一些非真实网站资源,最终可能造成真实页面被插入广告,被蒙层,甚至整页面被替换,严重影响用户体验以及企业形象。由于链路劫持可能通常发生在last-mile,而last-mile被运营商牢牢控住,所以这对监测以及解决问题带来了巨大的挑战。
二、可选的解决方案
针对于DNS劫持和链路劫持,业界有比较多的解决方案,各有利弊,适合不同的场景,总体上来说可以分两大类,一是被动监测型,二是主动防御型,下面就分别介绍一下。
1、被动监测型
被动监测型主要是通过采集用户访问站点的网络参数的方式来判断是否遭到劫持,比如通过采集用户访问站点的ip地址来和我们真实站点以及CDN节点的ip地址进行比对,判断是否遭到DNS劫持,或者通过采集用户访问的URL和真实站点的URL进行比对,判断是否遭到链路劫持。在PC时代对于被动监测型一般就是真机模拟这一种方式,但是在随着移动互联网的快速发展,针对于移动APP出现了一种插入SDK来监测的方式,这两种方式采用的技术手段完全不同,也各有利弊。
1)真机模拟型
由第三方监测厂商提供全国范围内的监测服务,通过真实的PC或手机模拟用户的真实访问来收集相关 的性能参数,然后由厂商对数据进行分析,最终为客户呈现性能指标或者提供告警服务。
优点:1、落地容易、实现简单;
2、不用修改任何APP的代码,和原程序完成无耦合。
缺点:1、手机真机的模拟,由于手机成本以及移动流量的原因,数量比较有限,采样数据的覆盖度较低。
2)插入SDK型
主要用于移动APP,通过在移动APP中插入SDK的方式,收集用户访问站点的性能参数,并将其统一发送至数据分析平台,最终呈现出性能指标以及相关告警服务。目前市场上有多家APM厂商提供类似的服务,实现方式一般分为SaaS以及私有云两种,对于一般小企业考虑到成本问题会选择SaaS模式,相关性能数据统一发送到APM厂商的公有云上,厂商加以分析,最终呈现的结果客户可以通过web方式查看。而对比注重安全的大企业,无法接受数据被上传到第三方的云端,部分APM厂商也会提供相应的私有云解决方案。
优点:1、数据来自真实用户,具体更高的真实性和完整性。
缺点:1、SaaS解决方案安全问题
2、私有云解决方案成本高,部署复杂
目前被动监测的方式多为购买第三方厂商的监测服务,在发现某一地区的劫持率超过阀值后会向企业告警,企业依据厂商提供的证据向运营商投诉,但是往往运营商的处理效率非常低,因此要从根本上解决问题,需要采取一些主动防御的解决方案。
2、主动防御型
主动防御型就是主动出击从根本上杜绝劫持的可能,对于DNS劫持的解决思路目前po主了解的主要有两种,第一种是绕过运营商的local DNS,使用公共的DNS,另一种是直接通过ip来访问,抛弃了域名访问的模式。而对于链路劫持,业内目前还没有什么太好的主动防御模式,https应该算一种,但是https也会带来诸多其他问题。下面分别介绍下几种思路。
1)绕过运营商localDNS,使用公共的DNS
让用户不使用运营商的local DNS改用114DNS,114DNS是国内最大的中立缓存DNS。推动用户自己手工去改DNS显然是不可行的,用户10个有9个都不知道DNS是啥。那如何去让用户不使用运营商的local DNS呢?po主在腾讯的一个工程师的博客里面看到有这么一段话:“如何在用户侧构造域名请求:对于PC端的客户端来说,构造一个标准的DNS请求包并不算什么难事。但在移动端要向一个指定的LocalDNS上发送标准的DNS请求包,而且要兼容各种iOS和android的版本的话,技术上是可行的,只是兼容的成本会很高。”po主认为这种方式暂且不谈技术上是否可行,最大的问题应该是无法确保公共DNS的稳定性。一旦公共的DNS遭到攻击,将会导致全国性的故障,所以一定需要一个冗余的方案,就是当公共DNS挂了后,可以去向运营商的local dns去请求。
2)抛弃域名访问方式,直接进行通过IP访问
这种解决思路,po主了解的有两种方式,第一种是httpdns,这种应该是目前DNS防劫持的主流方式,但是网上相关的介绍非常少,从腾讯员工的博客以及阿里朋友给的内部资料上看,现在腾讯和阿里都在用这种方式。另一种是网宿的MAA解决方案。两者的原理大同小异,都是为移动APP而量身定制的。
httpdns的原理大致就是在移动客户端中加入一个域名解析的模块,客户端通过http的方式向企业的流量调度服务器请求ip,此时流量调度服务器会回根据用户所在位置给用户一个最优的ip。客户端在获取ip后直接用此ip来访问所需站点资源。
这种方式看着确实很完美,但是对于一般的企业来说想要实现是一件极具挑战的事情。
1、客户端需要进行一定的开发来满足客户端的httpdns的请求;
2、针对这个流量调度服务器需要自己开发一套所有节点的IP地址库以及测速系统,才可以保证将用户引导的访问最快的IDC节点上,并且对于使用了CDN加速的域名来说,这个IP地址库是不可控的。
3、如何保证高可用性以及不同运营商的用户访问到同一个HttpDNS的服务IP,用户的访问延迟?腾讯的做法是:HttpDNS通过接入了腾讯公网交换平台的BGP Anycast网络,与全国多个主流运营商建立了BGP互联,保证了这些运营商的用户能够快速地访问到HttpDNS服务;另外HttpDNS在多个数据中心进行了部署,任意一个节点发生故障时均能无缝切换到备份节点,保证用户解析正常。
所以说httpdns是一个好的解决方案,但是用起来并不容易,而其投入产出比也只有在一些巨型的互联网公司身上才能体现出来。
再来说说网宿的MAA的解决方案,po主觉得和httpdns比较类似,前提是这个域名要使用网宿的CDN加速。网宿的MAA方案其实就是帮一般企业来解决上面httpdns的三点难点。
1、客户端插入网宿研发的SDK,向其鉴权服务器请求ip;
2、网宿的鉴权服务器类似于httpdns中的流量调度服务器,因为CDN厂商本来就要负责调度CDN节点的资源,所以这点对他们来说很容易;
3、如何保证高可用性以及不同运营商的用户访问到鉴权的服务器,用户的访问延迟?这点网宿的资料里面没有提到,po主个人猜测问题应该不大,因为对于一个CDN加速的域名来说,用户本来就是要去网宿的鉴权的服务器的,而对于一个提供CDN服务的厂商来说,鉴权的服务器的高可用肯定是要做好的。
(以上绝对非软文,po主觉得是个很好的解决思路,表示要向网宿征收广告费啊!!!)
但是网宿的这个解决方案同样存在问题:
1、插入SDK的方式很多大企业可能无法接受
2、只能用于网宿加速的域名,其他厂商的CDN节点的ip信息网宿不可控,这样可能会被一个厂商绑架。
3)https
注意https是解决链路劫持的方案,并无法解决DNS劫持的问题。https的优点太多了,什么保密性、完整性、可用性,我就不多说了,去网上一搜一大堆,我这里就只谈谈如何防御链路劫持。
1、https是加密协议,我们随便抓个http包,发现http包里面的所有东西都是明文的,这样就会被监听,而https协议是加密的。
2、但是光加密还不够,因为只是application data被加密了,网络层的信息都没有被加密,邪恶势力依然可以用数据包的目的ip作为源ip响应用户。https还有另一大特点是要验证数字证书,为了确保客户端访问的网站是经过CA验证的可信任的网站。所以这就几乎彻底杜绝了链路劫持的可能。
但是https也不是如此完美,虽然https解决了诸多安全问题,但是对性能也有着比较大的影响。一是用户要从http跳转到https,并且要多几次TLS的握手,这会消耗一定的时间;二是服务器的压力也会增加。除此之外如果使用全站的https,所有页面里面的嵌入资源都要改成https,APP的程序也要进行相应的修改,CDN的所有节点也必须都支持https并且导入证书。所以全站https并不是一件容易的事情,国外的Google、Facebook、Twitter早已支持全站https,但目前国内大多数公司都没有采用全站https的方式,微信算是一个,前段时间百度表示已经支持全站的https了,前段时间我试了一下,百度主站在pc端和移动端都已经可以自动跳转到https了,但是近期发现移动端又恢复成http了,可能是考虑访问体验问题。由此可见全站https应该是未来互联网的趋势。
三、选取何种解决方案
(以下仅代表个人观点)
1、主动防御型的解决方案总体上看虽然可以从根本上解决劫持问题,但是成本高,研发周期长,适合超大的互联网公司,但未必适合所有企业。
2、被动监测型中,真机监测显然不是未来主流发展方向,并且覆盖范围小是硬伤,但是安全无副作用。
SaaS方式的插SDK具有一定的安全风险,在传统行业尤其是金融行业中很难被接受。
私有云方式的插SDK成本比较高,部署相对复杂。
那么问题来了,又便宜又安全又好用的东西,你告诉我一个我去批发来卖。
3、能否自研制SDK。这个问题要问开发,我个人理解应该是可以。但是抓取了海量的数据要自己去分析并不是一件容易的事情,需要花费很多的人力物力,毕竟这种第三方监测厂商百来号人就是靠这个吃饭。厂商卖的不是一个简单的SDK,卖的是服务。说到底还是一个投入产出比的问题,是自己花精力去搞但未必成功,还是买一个现成的商业解决方案。
4、被动监测型除了监测劫持问题外,还有很多其他功能。比如CDN的服务质量评估,比如用户访问的网络性能分析,甚至可以追踪到移动应用的崩溃原因以及代码级别的执行时间开销。这对于提高用户体验,减轻运维压力都是及其重要的。
最后总结下,如果说一个APP的功能是前锋的话,性能就是后卫,前锋虽然身价高,但赢球还要看防守。功夫再高,也怕菜刀,更何况菜刀在流氓手里。