折腾了两天百度网盘限速,我大概搞明白 120 KiB/s 是怎么来的了

栖白 2026-09-03 10:55 1

前几天在某音符软件刷到了一个视频,是用Openspeedy的变速功能实现网盘下载加速。

在简单了解了一下这个加速软件后,我很好奇为何这个游戏变速器能实际影响网盘的下载速度。是否是百度网盘在用户端限制了用户一段时间内能获取的字节数?而时间加速骗过了这个计时器,让实际传输的数据变多了。

逆向这块我基础很弱,过程中大量使用GPT来协助整理,于是写了这个帖子记录一下这次的成果,希望能有所帮助。


以下均为个人观点,欢迎指正!

本次主要分析的是 Windows 客户端 kernel.dll 3.0.20.234

先说一下我目前理解的限速框架


下载策略                  //大概是拿到一些下载行为用到的控制参数

sl = 120 //实际下载策略里发现的字段,猜测可能是Speed Limit?

客户端换算
120 × 1024

122880 B/s

多个限速来源进行仲裁 //目前观察到4种,而限速逻辑存在一定的优先级区分

得到最终生效的限速值

Token Bucket(令牌桶) //类似一个额度池,定期补充,每次下载数据都会消耗

按经过的时间补充下载额度

下载数据消耗额度

没有额度就等待

先说说这个下载策略,点击下载按钮以后,客户端不是随便找个服务器就开始传文件,而是需要拿到相应的信息,比如:

-去哪个地址下载

-与此次下载相关的控制参数

-速度相关参数

客户端拿到这些信息之后,建立下载任务,才真正开始传输数据。

而sl这个字段,就是其中控制速度的参数(暂且这么认为)

而进一步下追之后,这个值会进入限速的相关逻辑,被转化成

120 × 1024 = 122880 B/s也就是:120 KiB/s

于是这个值进入了客户端的限速系统。

注意,这个数值不是当前实际下载速度,而更类似一个基准,下载速度在其周围浮动。


而我们为什么要说下载策略,而不是直接说这个sl参数呢?

是因为我们发现客户端不只是听sl这一个值,还有其他来源。

例如(此处列举2种):locatedownload → 返回 sl 等下载相关参数

CMS配置 → 也可以提供整体速度限制相关参数


这些来源之间,通过一定的仲裁策略/优先级进行协调

可以理解成:


locatedownload :      //此处抽象简单化了
“我这里限 120 KiB/s”

CMS :
“整体下载这里也有一个限制”

客户端比较这些来源决定最后哪个限制值生效


那么最后的实际限速值是怎么拿到的呢?

先解释一个关键点:

locatedownloadCMS、P2P SDK 等限速来源,其参数起作用,并不是按类似“谁最后到就听谁的”这种策略,客户端内部有一套set_sl的仲裁逻辑,会同时记录:

-限速值

-这个值是谁设置的

-当前有没有更高优先级的来源已经生效


我们用百度原始kernel.dll跑了一遍,可以抽象成这样的过程:


初始 / reset

CDN = 524288 B/s
TOTAL = 524288 B/s

locatedownload 到来
sl = 120

120 × 1024 = 122880 B/s

CDN = 122880 B/s ← locatedownload
TOTAL = 122880 B/s ← locatedownload

随后 CMS 配置到来

CDN = 122880 B/s ← locatedownload 保持
TOTAL = 122880 B/s ← CMS 接管

也就是说,同一个 122880 B/s,实际上可以有不同来源,在当时的一次真实长任务下载中, CDN 这一层的 120 KiB/s 来自 locatedownload,而 TOTAL(整体下载)这一层最终由 CMS 接管。


所以最后的实际限速值受多个来源影响。


另外一个支撑这套理论的证据是,我们在客户端里找到的CMS原始配置其实是

total_limit_speed = 81920 B/s也就是大约80 KiB/s

但最终的total却是122880 B/s

所以说,客户端内部其实做了一个兼容判断


CMS 原始候选 = 81920

当前 locatedownload CDN = 122880

locatedownload 当前有效

CMS 候选比当前 CDN 更低

把 CMS TOTAL 候选提高到 122880

后来在历史日志中,还看到了一次当前 CDN = 204800 B/s

CMS 原始值仍然为 81920 B/s

按照同一套逻辑,最后得出的total就是204800 B/s


所以说这里可以得到一个结论:

120 KiB/s 不是写死在这套仲裁逻辑里的。相同的 CMS 原始输入,在当前下载状态不同的时候,可以计算出 120 KiB/s,也可以计算出 200 KiB/s


而有了这个120 KiB/s的限速值,就一定是它把下载速度卡住了吗?

暂时还不能

因为这里只是证明,客户端最终配置出了一个 122880 B/s 的限制。

但是客户端内部还有其他限制:

-CDN 限制 //内容分发网络的速度上限

-TOTAL 整体限制 //整个下载系统总体最多能放多少数据

-task 级限制 //针对某一个具体下载任务的速度限制

-NetGrid 等对象里的限制 //某个下载任务背后实际负责组织网络连接,数据传输的一层执行对象

一个限速值即使存在,它可能并未被真正使用


整个客户端

├─ TOTAL
│ 控制总体下载速度

├─ CDN
│ 控制 CDN 下载路径

└─ 某个具体任务

├─ task 级限制

└─ NetGrid / peer 执行层限制

其实类似不同的闸门,取了其中最紧的一个。最紧的一层决定瓶颈。


所以后面我没有继续只盯着配置值,而是启动真实下载任务,观察哪个限速器的“额度”真的在被不断消耗。也就是前面的Token Bucket(令牌桶)


对于令牌桶,我们主要关注三个东西


rate
每秒应该补多少下载额度

token
现在还剩多少下载额度

timestamp
上一次补额度时的时间

可以理解为


时间过去

按照 rate 补 token

下载数据

消耗 token

token 不够

等待继续补

如果某一个限速器确实在卡我们的下载速度,那么他对应的令牌桶,应该出于一种不断被消耗,不断被补充,而消耗的速度大于被补充的速度,导致token长期接近耗尽的一种状态。


反之,如果一个限速器下载速度写的很小,但是他的tokentimestamp实际并没有变化的话,至少这次下载没有从这里取额度。


在一次真实下载任务中,客户端显示的速度长期处于122764 \~ 126223 B/s范围。

与此同时,我们看到TOTALrate = 122880 B/s

更重要的是它的token,在连续采样之后,我们得到


480 / 482 次 
token < 16 KiB

也就是在下载过程的绝大多数时间,它剩下的下载额度都很少,是一个十分典型的卡住吞吐的状态。


与此同时,我们也观察了其他限速器,此中的一个task 级限制,约为 500 MiB/s

额度一直很充足,显然不是它卡住了我们的下载速度。

还有一个task / NetGrid CDN = 16 KiB/s

那么为何下载速度不是16 KiB/s呢?

因为他的


token 没变
timestamp 没变

说明这次下载,并未消耗他的额度。

真正表现了瓶颈特征的,是122880 B/s


为了进一步证明,total限速器不是一个待在内存里的无关对象,我们还获取了暂停下载任务时的数据。当任务运行时


TOTAL token 在变化
TOTAL timestamp 在变化
文件进度在增长

暂停时


TOTAL rate 仍然 = 122880 B/s

但是:

token 冻结
timestamp 冻结
文件进度停止
网络读取也停止

甚至捕获到,冻结时token = 18 bytes


所以说明,total限速器的活动和真实下载生命周期是同步的。


接下来就进入了Openspeedy的作用层了,也就是令牌桶是按什么时间补充额度的

核心就一个公式

新增 token ≈ rate × elapsed_time

比如


rate = 122880 B/s

程序认为过去了 1 秒

大约补 122880 bytes

程序认为过去了 0.5 秒

大约补 61440 bytes

而这个elapsed_time 是从哪里来的呢!


我们继续追百度原始 kernel.dll 的令牌桶补充逻辑,最后追到了 Windows 的 FILETIME 时间接口。也就是说,这个限速器不是单纯“每隔固定 1 秒发一次额度”,而是会读取时间,算出“距离上次过去了多久”,再据此补 token。


上一次时间
timestamp_old

读取当前时间
timestamp_now

elapsed = now - old

新增 token ≈ rate × elapsed

更新 timestamp

Openspeedy影响的,就是限速器对于时间的感知。


到这里,也只是在理论上说明了此套机制可行,我们还做了更进一步的实验。


首先,我们加载百度原来的签名 kernel.dll,让他自己的限速器工作,保持rate不变,只改变了它感知时间的速度,结果:


0.25x → 29.79 KiB/s
0.50x → 59.56 KiB/s
1.00x → 119.13 KiB/s
2.00x → 239.25 KiB/s
5.00x → 598.13 KiB/s

5个点做线性拟合,基本就是一条直线。


这里的“改变时间倍率”并不是在实验代码里直接修改 elapsed_time。我们在自己的测试程序中加载了 OpenSpeedy 官方的 speedpatch64.dll,通过它提供的倍率控制让整个进程看到的 FILETIME 时间变快或变慢。

与此同时,我们另外用一条不受本次 FILETIME 虚拟化影响的时间NtQuerySystemTime作为现实时间对照,因此可以确认百度限速器实际感知到的是 0.5x、2x、5x,而不是手工把计算结果乘了一个系数。


不过这还不够,完全可以质疑是在实验程序里调用限速函数,我们需要证明,这个数字能被传入实际的数据传输与文件写入。


之前的测试相当于拆一个水龙头阀门,而接下来,我们要把这个阀门装上真正的水管,看看水流是否真的经过这个阀门了。


我们接入了真实数据传输


本地 TCP sender

百度原始 TOTAL 限速器

recv() 接收数据

写入文件

FlushFileBuffers()

只有令牌桶允许,才能接受之后的数据

最终结果仍然是


无时间修改  → 119.14 KiB/s

0.5x → 59.57 KiB/s
1x → 119.13 KiB/s
2x → 239.20 KiB/s
5x → 599.53 KiB/s

到这里,时间倍率影响的已经不只是“令牌桶函数算出来的数字”,而是实际经过 socket 接收并写进文件的数据吞吐。


现在已经能证明:只要改变这个进程对时间的感知,百度原始限速器控制下的下载速度也会变化。


但前面的实验还有一个区别:speedpatch64.dll 是我们的测试程序自己加载进去的,而平时使用 OpenSpeedy 时,并不是目标程序主动加载它,而是 OpenSpeedy 从外部把时间补丁注入目标进程。


所以最后我们又补了一层验证:直接使用OpenSpeedy官方的Bridge流程,对我们自己的测试程序进行注入。 并没有修改真实运行中的百度网盘进程。


OpenSpeedy 官方 Bridge

将 speedpatch64.dll 加载进测试程序

改变测试程序看到的时间

百度原始 kernel.dll

TOTAL 令牌桶

TCP recv()

写入文件

得到的结果:


0.5x → 59.57 KiB/s
1x → 119.15 KiB/s
2x → 239.23 KiB/s
5x → 599.65 KiB/s

也就是说,从OpenSpeedy的实际外部注入链,到百度原始限速代码,再到真正的文件接收和写入,是能完整跑通的。


目前的证据支持:


sl=120会进入客户端限速逻辑,并换算成122880 B/s

真实普通长文件下载中,真正表现出瓶颈特征的是TOTAL = 122880 B/s

TOTAL 令牌桶按经过时间补充额度,改变进程感知的时间后,百度原始限速代码控制下的实际数据吞吐会近似按倍率变化


这里要声明一点,我们没有对真实在线的 baidunetdiskhost.exe 注入 OpenSpeedy ,所以不能真实完整证明,百度下载一定按某种倍率提升。真实百度进程部分始终只做了只读观察。


另外,这套结论主要对应我们观察到的普通长文件路径。客户端还存在小文件特殊路径,例如 fsl=0 时会跳过一个特定的全局 token consume,因此不能拿 120 KiB/s 这一条规则解释所有下载场景。


写完有点头昏脑胀的,如果有些地方描述不清或者有逻辑错误,欢迎各位佬指正,也请包涵。 ^-^

最新回复 (19)
  • 烧冻鸡翅 09-03 10:58
    1

    始皇严选,严肃学习ing

  • MartinMa 09-03 11:00
    2

    所以有办法突破限速吗,从百度盘通过插件获取api下载链接,然后使用第三方下载软件,有没有办法做到?

  • hanhanye 09-03 11:07
    4

    你可以把文章喂给AI,组织一遍再自己看 ^-^

  • marki 09-03 11:07
    5

    长文总结一下,太长有点头晕… 另外哈基米3.8flash怎么还在ab

  • 沧浪同学 09-03 11:09
    6

    这个不是一两年前就修复了吗

    还是说今年新的科研成果

  • miku tc 09-03 11:10
    7

    所以按照这个逻辑在本地就可以直接解除百度网盘的限速 ^-^

  • yamika 09-03 11:12
    8

    最近也在各个视频平台又刷到了,可以用**Openspeedy**直接加速下载速度,感觉原理还是一样的

  • luwei 09-03 11:14
    9

    我记得通过加速解除限速已经被修复了,所以综合来说目前通过加速解除限速只是解决限速的其中一环 要突破限速还要解决其它的限速源

  • 栖白 楼主 09-03 11:15
    10

    SorrySorry,以后写完先放几天,到时候再自己重新看一遍能不能易于理解

  • 拉香蕉的奥德彪 09-03 11:16
    11

    ^-^上一个这么干的人不知道现在出来没有

  • MrQ 09-03 11:18
    12

    加速的方法早就有了,后续他们加了更多限制,可能老版本还能用这个方法。


    另外度盘已经算良心了,充会员就给速度,迅雷现在白金VIP 网盘取回都限速 4m/s

  • 网好卡卡卡卡卡卡罗特 09-03 11:18
    13

    10年前我就想问一个问题了 就百度云这吃相 为啥刷不到骂他的帖子啥的呢?

    (虽然我也妥协了都冲年费会员充到svip7了 ^-^)

  • xlxzhc 09-03 11:18
    14



  • vfx 09-03 11:18
    15

    以前变速齿轮也可以加速下载,但肯定是BUG被修复了啊.知道原理没啥用,破解不了的.唯有充值才能变强.

  • Caphhh 09-03 11:23
    16

    折腾这个收益《《 成本,限制远不止这一处,上游一改全报废


    研究消耗的 token 还不如拿来冲年费会员/买临时账号

  • buste 09-03 11:26
    17

    还是蓝绿破解器好使吧 用了几年了没出过问题 官方还给我送了几个礼品鼓励我继续用 ^-^

  • microsoft2333 09-03 11:27
    18

    我寻思着 百度网盘他们不做服务器端的限速吗

  • 一梦浮生 09-03 11:30
    19

    临时用baidu的时候 用过几次这个软件,效果还是可以的.

  • kt8tqbhvk 09-03 11:33
    20

    会员好像不限速的,折腾这些没有意义的内容,浪费的时间远远比买个会员更贵。

* 帖子来源Linux.do
返回