国内部分网盘技术通俗外部分析!

Written on April 12, 2014 View on GitHub

为什么要分析各大网盘?大型网盘的需求很云存储十分相近,思路有些可以互通。

云存储是?

这里的云存储只是指云计算平台中的常见服务:对象存储。但是并且跟Amazon S3和Azure Storage Service不一样的是,这里的对象存储暂时不考虑修改的情况,也就是只有“添、删、查”操作。

为什么只有国内网盘

国外的连上稍微有点困难。。。。

该分析是外部分析,没有任何内部资料。只是利用其网络请求、客户端数据包的分析得出的结论,有些算法参考了网络上的其他资料。 研究的时候没有笔记,写的时候靠记忆,应该有部分记岔了。另外我想象力比较丰富,文章的好多猜测都是基于“如果是我,我会怎么设计”出来的,水平有限,猜错也不要稀奇。

网盘实现原理的猜测

网盘和云存储不一样的是,网盘最终是提供一个(一般是HTTP)对外存取接口,网盘的文件一般只存不改,并且对实时性要求不高,因此网盘只用做好很好的分散存储和发布就可以了,配合精简逻辑的备份、HTTP服务、没有漏洞的验证逻辑,一个简单的小型网盘系统就完成了。 从各个网盘的接口来看,至少在HTTP的对外接口上,并没有看出采用复杂分布式技术的任何迹象,大多数网盘的下载接口,似乎是采取如下结构。

统一的WEB接口
=> 验证后302指向静态服务器
=> 验证后提供访问

在上述过程中,验证后指向的静态服务器地址具有明显的分散存储特性:如文件AABBCCDD.zip通常地址为http://s1.blahblah.blah/AA/BB/AABBCCDD.zip。 在传统web服务上,目录采用这种分文件夹的方式,通常是为了减少单文件夹下的文件数量,以减少文件系统的压力(当目录下文件特别多时,通常需要消耗的IO和CPU在文件系统的索引上),而此结构在常见的KV分布式存储里几乎没有意义。文件的URL写成这样,基本说明了文件在服务器上也是这么存的。(通常这些服务器上IO压力很大,如果做URLRewrite可能会成为性能瓶颈)

从系统需求的角度,这样的结构使用相当少的CPU,因为在访问文件时候,只是对一台服务器进行必须的IO操作,没有额外的开销。 当然还有一种可能,由于存储的成本越来越低,也许给出的静态服务器地址只是一个缓存文件地址。后端仍然使用专用的分布式结构来保证数据安全和正确性,也就是这样的过程:

访问文件
=> 访问到的API服务器看自己服务器上有没有这个文件,有则直接返回文件
=> 没有则实时连接中心存储服务器,在做Proxy的同时,存下该文件到API服务器上。

以上猜测没有任何证据,不过同样一个文件,访问同一个迅雷API服务器,经常一个500KB/s,一个100KB/s。而那个100KB/s的文件,过一段时间就可以用500KB/s访问了。

HASH的使用

HASH的作用不用多说,但是一般HASH算法使用后都有一定的碰撞可能,因此一般厂商会使用多个HASH联合的方式。 下面列出的除了网盘之外,还有一些是下载工具和虚拟网络的数据。

协议&HASHMD5SHA1CRC32自定义HASH样本片HASH
迅雷 Y Y
百度网盘 Y Y Y
115网盘 Y Y
ED2K Y
华为网盘 Y Y
腾讯微云 Y Y
联想网盘 Y
快播 Y
Kademlia Y Y

迅雷GCID:

迅雷的自定义HASH,迅雷内部对文件的唯一标识,是对文件分片后多次SHA1生成,并且根据文件大小有不同的分片方式。BT文件里有分片SHA1数据,两者采用相近的分片方式,通常可以从BT文件里提取GCID。(网上能找到GCID的相关实现,但是根据我大约4千个文件的采样发现,网上的算法是错误的,不能说太多不然会被喝茶)

迅雷CID:

迅雷的自定义样本片HASH,文件样本片(前中后三片)多次SHA1,极易碰撞,早期迅雷版本经常下载错误可能跟此有关。

ED2K:

文件分片多次MD4,无法解决碰撞问题,下载文件是否正确取决于能否连上有正确文件的客户端,但因为MD4相对没有严重漏洞,几乎没有攻击可能性。

华为网盘:

使用ID为MD5+文件大小HEX,不能直接通过ID下载文件,碰撞问题的解决应该隐藏在了服务端。

百度网盘MD5:

当系统认为上传的文件有损坏时,采用的MD5是系统认为正确文件的MD5,服务器可能使用了差异存储。没有证据,通过6万个文件采样得出此结论。

百度网盘样本片HASH:

前256K的MD5。

Kademlia:

这里的Kademlia包括eMule的Kad网络和BT的DHT网络。

结论:

MD5:虽然MD5有比较严重的碰撞漏洞,但是各大厂商还是热衷于使用MD5。从技术的角度,刻意的MD5碰撞攻击很容易被识别,另外MD5的速度普遍高于其他常用HASH算法。 SHA1:SHA1没有已知的碰撞漏洞,速度接近MD5,使用比较广泛。 为什么不使用SHA256之类更安全的算法:我猜因为CPU计算比较贵吧。。。 下载工具多采用分片多次HASH,而网盘多采用单次HASH。 经常被人问起:为什么没人用AES或者RSA?那是加密,这里说的是HASH!另外存储服务器上是不可能用这些加密算法的,因为太耗CPU了,除非在客户端加密好了上传。

验证的实现

迅雷:

登录后得到一个访问ID(通常长度为64或者80字节),该ID能够跨服务器访问服务,大概48小时后失效,一个用户有唯一的访问ID。后台的实现可能是有请求时,访问迅雷验证服务器验证,验证成功后做本地缓存,时效48小时。 这个过程跟KeyStone验证非常相似,但是默认长度短很多。

百度:

有类似的访问ID,但是一个用户可以拥有多个不同的访问ID,同时有效,并且有效时间远大于48小时,事实上两个月前我采样的访问ID现在还有效。从验证的过程和行为表现来看,该访问ID很有可能是具有自我验证的功能(类似软件的序列号),也就是百度服务器只是验证一下该访问ID是否正确,而不需要去连接内部的验证服务器。 这种方法听上去好像不安全,不过我认为很有效,能够大大减少验证压力。给所有人做验证的成本,可能远高于让个别人滥用资源的成本。另外百度登录时的验证算法并非固定的,需要去获取服务器认可的验证算法,该验证算法的参数很有可能隐藏在该访问ID里。百度只需要定期更换指定的验证算法就可以了。

网盘的服务

网盘通常需要提供一些额外服务,比如图片预览、视频在线预览等工具。

迅雷:

内部使用GCID作为文件的唯一识别。可以通过GCID访问其截图、转码视频等信息。 比如如果一个文件是视频或者图片的话,我可以利用GCID直接生成该文件的截图或者缩略图的地址。

百度:

大部分服务采用MD5作为唯一标识,部分文件MD5表现异常,很有可能是为了避免碰撞或者是识别出文件错误。 部分服务采用MD5+长度为4的未知字段作为唯一识别。该字段极有可能用于属性掩码或者用于处理MD5碰撞。

腾讯:

大部分服务采用SHA1作为唯一标识。对于较大的东西,通常存有一个SHA1列表。 SHA1有跟MD5相近的速度,无可用攻击算法,这里采用SHA1应该是非常合适的。

115网盘:

每个文件拥有一个多个唯一ID和全局ID。访问不同服务时使用不同字段,一般是SHA1以及pickcode(一串小写+数字的识别号,可能是base36什么的),pickcode全局唯一。 如可以通过SHA1生成视频文件和照片的缩略图,可以通过pickcode取得视频转码信息、下载地址。 离线下载、秒传

协议&HASHBT文件ED2K其他
迅雷 Y Y GCID、CID
百度网盘 Y Y MD5+样本片MD5+CRC32
115网盘 Y
腾讯微云 MD5+SHA1

各个网盘的离线下载服务和秒传服务都在不断升级,但是一般都支持使用部分HASH识别文件的方式,如MD5、SHA1、ED2K。也就是对这些网盘厂商来说,这些HASH足以识别一个唯一文件。

服务器上很有可能还存有分片HASH,当部分HASH不一致而部分HASH一致时,通常是文件个别字段损坏所致,服务器可以只存下差异部分,该思路可以借鉴到云存储上。

其他

迅雷客户端的传统下载过程

用户提交下载URL,迅雷的利用URL到服务器查询GCID、CID、文件大小。如果这个URL是静态的URL或者是ED2K这种可靠URL,通常能够返回正确的数据。 如果是HTTP地址或者FTP地址,迅雷客户端会尝试访问服务器,取得文件大小等信息。较大的文件会尝试利用分片下载,先计算出CID进行匹配。 若匹配均通过,客户端会发送GCID到迅雷服务器,服务器返回Peer列表。 然后就是著名的P2SP下载了。

百度网盘的后端实现猜测

曾几何时好像在哪看到说百度网盘是基于百度云存储实现的。不认识百度网盘的开发人员,但从百度网盘的API来看,拥有分片上传、组合文件等功能,那么百度网盘的这个传言很有可能是真的。网盘里的每个文件,很有可能是分片存在服务器上的。 而百度网盘的MD5数值也是几个网盘里唯一一个可能会出现异常的。那么很有可能是分片存储的时候,发现该文件有大量文件片跟别人相同,从而认为这两个文件其实是一个文件,但是个别字节有误。(这在多媒体文件里是经常出现的) 因此可以大胆推测:百度网盘里的文件,是分片存在对象存储上的。网盘里的每个文件,其实是一个分片索引。(猜错了也别找我。。。)

Kademlia

非常著名的对等P2P网络。每个Peer拥有一个全局UUID,并且利用UUID决定Peer在网络中的位置。网络的结构是二叉树,所有人都在叶子上,每根枝都可以看成是一个子网。查找的过程,特别像哈夫曼编码树。 Peer之间通常需要通过一个ID来识别P2P文件,eMule的Kad网络使用的是ED2K的Hash,而BitTorrent的DHT使用的是btih,也就是BT文件的SHA1值。

WordPress

发现WordPress默认的twentytwelve样式在中文下很有问题,Open Sans字体在编辑器里也表现得非常异常。