Telegram DC 之都市传说

Telegram 号称有 5 个数据中心(DC, Data Center),在 Telegram 代码与文档中被称作 DC 1~5。其中 DC1 与 DC3 位于美国的迈阿密(Miami, USA);DC2 与 DC4 位于荷兰的阿姆斯特丹(Amsterdam, NL);DC5 位于新加坡(Singapore)。

Telegram 的运行状态

每个帐号都会在注册时关联一个 DC,此后不随用户更改手机号或地理位置迁移。用户也不能自由选用 DC——如果连接到了错误的 DC,服务端会返回错误信息,要求客户端连接到帐号所关联的正确 DC 上。

从日常宕机的 DC5 说起

在 5 个 DC 中,DC5 在 Telegram 中文圈格外知名——并不是因为它默默无闻服务了大量的中文用户,而是因为它经常宕机。

当 DC5 宕机时,身处 DC5 的用户无法使用 Telegram,此时的 Telegram 圈内的话题往往会变成 「DC5 怎么又挂啦」。DC5 用户只能等待自己不断「重连中」的客户端恢复后,再与其他 DC 的群友们一起批判 DC5。

DC2 与 DC3 之谜

为了满足群友们的好奇心,有人写了个 bot(机器人),可以查询用户所处的 DC。于是群友们开始查起了自己的 DC:

  • 用 +86 手机号注册的用户发现自己在 DC5(新加坡),即将体验下一次宕机。
  • 用 +1 手机号注册的用户则会在 DC1(美国迈阿密),可以兼顾连接速度与稳定性。
  • 用欧洲手机号注册的用户会发现自己在 DC4(荷兰阿姆斯特丹),成为了中文圈中最稀有的存在。

咦?等等… Telegram 不是号称有 5 个 DC 吗?那 DC2 与 DC3 呢?

通过搜索 bot 的消息,用户位于 DC1 的有 360 条,DC4 有 50 条,DC5 有 390 条。DC2 与 DC3 有 0 条。

通过搜索 bot 消息的「大数据查询」,我们发现似乎真的没有来自 DC2 与 DC3 的用户。

于是,有人推测 DC2 与 DC3 皆无用户,也有人分析后推测 DC2 与 DC3 分别是 DC1 与 DC4 的附属 DC,会在其上级 DC 繁忙时接受用户注册。

真的是这样吗?

Telegram DC 的分配规则(2022-05)

TL;DR:

  • DC1、DC2、DC4、DC5 是根据用户注册时所填写的手机号的国家代码分配的,这 4 个 DC 随时接受新用户注册,且均有大量存量用户。
  • DC3 曾经有用户,但在 2020 年左右,DC3 的存量用户可能已被转移至 DC1。DC3 目前可能已无用户,且不再接受新用户注册。

也就是说,DC2 实际上关联着大量用户,且像其他 DC 一样,只要用户注册时,手机号的国家代码落在 DC2 负责的范围内(如 +49 德国),该用户就一定会进入 DC2。而 DC3 虽然仍在正常运行,但可能已无关联用户。

既然有大量用户位于 DC2 ,为何上文的 bot 从未发现过来自 DC2 的用户呢?

这是因为 bot 获取 DC 的方式出了问题。

我到底在哪个 DC?

目前常用的 DC 获取方法有 3 种,下文将注册一个 DC2 的新帐号,实际尝试一下这 3 种方法。

方法 1(登录法)

我们使用会被分配到 DC2 的手机号,通过 Telegram MTProto 协议(这也是官方客户端使用的协议)连接 DC1,调用 auth.sendCode 接口,尝试发送验证码,注册一个账号。

此时服务端会返回 PHONE_MIGRATE_2 错误,提示客户端应当要连接 DC2(如果连接 DC2 后进行同样操作,便会直接发送验证码)。

这样,我们就知道这个帐号是一个 DC2 的帐号。这种方法对于已注册的帐号同样有效,但是这种方法需要知道用户的手机号,难以用来查询群友的 DC。

方法 2(头像/文件法)

在刚才的 DC2 帐号注册完成后(下文称之为新号),我们利用会显示用户 DC 的第三方客户端(Plus Messenger),登录自己的另一个账号,去查看新号的 DC。然而,客户端此时并未能显示 DC,需要替新号上传头像后才显示新号在 DC2。

这是因为第三方客户端是在下载用户头像时,通过 MTProto 协议 userProfilePhoto 结构体中的 dc_id 字段,来获知用户所在的 DC。

这种方法是通过用户上传的文件所在的 DC,来判断用户所在的 DC。

如果是用新号登录第三方客户端去查看自己的 DC,则可能是通过方法 1 判断出的 DC,因为客户端知道自己在连接哪个服务器。

方法 3(Web CDN 法)

最后我们通过上文提到的 bot 查询这个新号的 DC。

bot 说,该帐号所在的数据中心为 DC4(阿姆斯特丹,荷兰)

咦?这个新号不是位于 DC2 吗,为什么 bot 会说是 DC4 呢?

其实它是通过 Telegram Web CDN 来获取用户的 DC 的。我们打开 https://t.me/dctest** 查看源码,会发现新号的头像域名是以 cdn4 开头的,导致被 bot 判断为了 DC4。

由于 DC2 与 DC3 会「借用」同地点的 DC4 与 DC1 域名来提供 Web CDN 服务,因此 bot 无法找到任何 DC2 用户——他们都被判断成了 DC4 用户。

还有另一种 bot,要求用户给 bot 发送一个图片/文件来判断其 DC。这类似方法 2,可以较为准确的判断用户 DC。

DC3 的消失

通过方法 2 正确获取用户 DC 后,我们可以发现在全球范围内(尤其是海外群组内),DC2 的用户并不算少,但 DC3 用户却屈指可数。多方查找后,我们发现了两名位于 DC3 的用户:@urie**@flowinglig**

然而,如果进一步分析,就会发现他们可能并不是真的在 DC3。例如,调用 photos.GetUserPhotos 查看头像列表,可以看到 @urie** 上传过 7 张头像,其中只有两张位于 DC3,新上传的头像都已在 DC1。

同样的,查看两位用户发言历史中的图片,也只有寥寥几张老图片是存于 DC3 的,新图片都是存在 DC1。而查看其它 DC 的用户,则发现他们发送的图片都存在各自所在的 DC 中。

此外,@urie** 也在 2021 年发送过文件给 DC 识别机器人(文件法)进行测试,返回的结果同样是 DC1。

遗憾的是,由于无法获知他们的手机号,所以并不能通过方法 1(登录法)准确测试,这里只能通过方法 2(头像/文件法)推测他们从 DC3 被转移到了 DC1。

为了进一步证实 DC3 已经不再接受新用户,我们生成了万余个全球各个地区的号码,通过方法 1(登录法)测试 Telegram 的 DC 分配规则,结果如下:

在测试过程中,我们尽可能让每个号码都连接到错误的 DC 上——这是为了通过返回的 PHONE_MIGRATE_X 错误了解号码对应的实际 DC,也是为了避免产生大量垃圾短信,造成骚扰及 Pavel Durov 因短信费破产。

在完成测试后,我们剔除了确定位于 DC4 的号码,再将剩余号码连接至 DC4 再次判断,以确保不会遗漏被分配至 DC3 的号码。

结合以上分析,我们可以认为 DC3 确实已不再接受新用户,而老用户也可能已经全部被转移至 DC1 了。

尽管我们没能找到消失的 DC3,但如果你想要成为指定 DC 的用户,回避 DC5 的宕机风险,或是测试一下测试机器人是否靠谱,现在只需参考上一张图,使用特定国家代码的号码注册即可。


由于 Telegram 服务端和部分运作机制并不开源,本文许多结论是通过推测得出。如有发现文中的错误,或有其他线索,欢迎评论提出。

本文撰写过程中参考了以下项目及内容,在此表示感谢:

Coxxs

本文(https://dev.moe/2564)由 Coxxs 原创,转载请注明原文链接。

Telegram DC 之都市传说》有8个想法

  1. DC 和 IP 还有一定关联,UK 号码用 RU 的 IP 注册就会在 DC2

  2. 文中用头像和图片来佐证 DC3 上的用户可能已被迁移是有瑕疵的。Telegram 的媒体文件所在 DC 和用户所在 DC 是高度解藕的。最简单的验证方式就是不带来源转发消息,这样一定不改变图片所在 DC。另一个验证方式是让 Telegram 从网上下载一张图片 (https://core.telegram.org/constructor/inputMediaPhotoExternal) 然后发送出去(这对机器人和普通用户应该都是有效的,只不过大部分客户端没有暴露这个方法),这样的图片一定在 DC4。

    进一步来说,Telegram 的文件上传与媒体发送也是解藕的。简单地说,文件上传 (https://core.telegram.org/method/upload.saveFilePart) 后是没有实体的,只是一个引用 (https://core.telegram.org/constructor/inputFile) ,既不可能什么都不做就再次下载下来,也不会知道它在哪个 DC;只有将它作为头像 (https://core.telegram.org/method/photos.uploadProfilePhoto) 或包装 (https://core.telegram.org/constructor/inputMediaUploadedPhoto) 以后绑定到对话 (https://core.telegram.org/method/messages.uploadMedia) 或进行其它操作,它才最终实体化 (https://core.telegram.org/constructor/photo) ,才有机会下载它和知道它所在的 DC。服务端不要求用户只能发送位于自己 DC 上的媒体,也没有证据表明 DC 接受用户上传并实体化媒体以后返回位于另一个 DC 的媒体对象会破坏任何客户端的任何功能性。因此实际上无法验证这些用户的头像或发送的图片是否是 DC3 隐式地转发给 DC1 储存后返回的。最终导致无法证明存量 DC3 用户是否真被迁移至 DC1。

    1. 感谢补充与详细讲解。我们所检查的媒体大多为「无来源转发」功能推出前,用户主动发送的(而不是转发/服务器自动拉取)。另外,文中也只是通过种种现象推测,确实未断言 DC3 用户一定是被转移到 DC1 了(事实上我们甚至无法断言他们曾经是在 DC3 的)。

  3. 所以tg里的消息所在DC是与发送者绑定的是吗?试验了一下创建一个群,群主是DC1,管理员是DC5,群主和管理员分别更改群头像后,群的DC跟随上传头像的人所在DC变化。

    1. 而且这样来看,一个群虽然显示的是DC1,如果DC5宕机,里面的DC5群员发送的消息仍然是看不到的吧

      1. 图片是仅储存在上传者发送的 DC 中,但消息应该不是这样。实践中如果 DC5 宕机,DC5 用户在超级群曾经发送的消息依然可以加载,而图片不行。(普通的小群就不确定了,普通群在架构上更类似多人私聊,而超级群类似频道)

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注