在Python中发布非官方的MTProto代理,协议功能

图片

最近,Telegram开发人员发布了运行在MTProto协议上的代理服务器的源代码。 有关其组装将Docker容器重新包装功能的文章已发布在中心上 。 用C编写的官方代理服务器对代码量感到惊讶-大约23000行。 同时,有时甚至更早一些,出现了一些替代实现,但没有一个支持发布其频道的可能性。

在本文中,我想首先讨论用于与外部服务器进行通信的代理服务器的协议的鲜为人知的功能,其次,要讨论我们自己的开发-用Python实现的代理服务器,该服务器刚刚发布,并且可以供所有人使用免费的MIT许可证。

代理服务器与外部服务器交互的功能


  1. 官方代理服务器不会直接与电报服务器进行交互,而是为此至少使用至少一个代理层。 我们将它们称为“ 中间代理” ,其列表位于core.telegram.org/getProxyConfigcore.telegram.org/getProxyConfigV6 。 官方代理服务器尚不支持IPv6连接。
  2. 为了加密代理服务器和中间代理之间的数据,使用了从两个节点的IP地址获得的密钥。 因此,用于连接到中间代理的代理服务器必须知道其外部ip地址,否则一侧和另一侧的加密密钥将不同。 另外,可在core.telegram.org/getProxySecret上获得的两个节点的端口号和共享机密参与密钥的形成。 电报开发人员建议每天更新一次此机密。
  3. 将代理服务器连接到中间代理服务器时,第一个代理服务器会转移其时间。 如果时间相差几分钟以上,则第二面将关闭连接。
  4. 从客户端向中间代理发送消息时,该消息将包装在对MTProto协议的RPC调用中。 在每个此类RPC调用中,代理都会添加几个参数:两个节点的ip和端口,一个随机连接标识符以及用于在应用程序中显示广告渠道的代理服务器标签。 这些附加参数占用大约96个字节。 由于此功能,当直接工作而不是通过中间代理时,将无法显示广告渠道。
  5. 电报服务器“相信”从代理服务器接收到的有关IP客户端的信息。 这些地址可以在会话信息中看到(绘制矩形):
    图片

  6. 代理服务器和中间代理之间的一个TCP连接发送来自不同用户的消息。 在请求和响应中,有一个参数“随机连接标识符”,这对于使数据到达正确的客户端是必需的。
  7. 代理服务器无法解密客户端数据,但是可以将常规消息与传输的文件区分开。 另外,他知道每个消息的大小。

Fuf,希望不要对技术细节感到厌倦。 现在应该清楚为什么在许多替代代理中没有广告支持-它们直接绕过中间代理将消息直接发送到电报服务器。 事实证明要容易得多。 本文的第二部分描述了通过中间代理工作的代理服务器的第一个非官方实现。 目前,在公共领域中,您可以找到三种这样的实现:在Erlang上的官方实现和这一实现。

Python代理实现


最初,编写代理服务器是为了了解协议的功能,并且是另一个项目的开发-异步袜子代理,然后编写,以“触摸” Python异步/等待。

逐渐地,该项目开始吸引了被问题,错误报告和功能请求所淹没的用户。 经过改进,该项目进入Beta测试和稳定阶段,该阶段持续了大约一周的时间,涉及五台不同配置的服务器。

在我谈论正式代理服务器尚不具备,但是替代代理具有的功能(并保持沉默,而不是正式代理具有的功能)之前,我将谈论许多人在提到Python一词时首先想到的事情。 。

性能表现


为了进行性能测试,在最低配置的云中使用了虚拟机:1个CPU,1024MB RAM。

在综合测试中,代理服务器能够传输大约240兆位/秒或3000条消息/秒。 在C中使用事件循环的替代实现(称为uvloop)时,以及在使用PyPy解释器时,性能数据也有所不同(所有测量均为每秒):
图片

在对真实用户进行测试时,事实证明,这样的服务器足以舒适地为4,000个用户或8,000个使用PyPy的用户提供服务,一个令人惊讶的是,无论该测试服务器如何在俄语频道中进行广告宣传,仍然有89%的用户来自伊朗(也许对于其他国家/地区,同时服务的用户数量会有所不同)。 看起来像这样:

图片

我问了其他服务器的几个管理员-他们的情况是一样的。 也许是由于这样的事实,在俄罗斯,电报在没有代理服务器的情况下运作良好。 在伊朗,测试服务器在创建后几个小时就被封锁了。

图片

服务器负载为2,000个用户。 很明显可以看到为伊朗公民封锁服务器的时刻。

因此,CPU性能不是测试节点上的瓶颈。 如果有10,000个客户端,内存可能会用完。

没有同时使用多个CPU内核(您好,GIL)。

官方代理服务器还没有的功能


使用IPv6协议。
没有其他配置的代理服务器可以使用IPv6进行传出连接。 俄罗斯目前尚未阻止IPv6连接。

无中间代理的工作模式
如果不需要频道广告,则代理将自动绕过中间代理自动直接连接到电报服务器。 它更快,更可靠。

此外,当使用相同的密钥加密从电报服务器到代理以及从代理到客户端的消息时,将实现可选的“ 快速模式 ”。 因此,代理不需要重新加密消息-它按原样发送消息。 这不应影响安全。 在任何情况下,代理管理员都无权访问用户消息。

每天一次自动更新中间代理列表和秘密。
用于更新中间代理列表的官方代理服务器建议每天重启一次Docker容器,这会重置所有连接。 例如,如果服务器在该国家/地区被封锁,则可能无法建立新的连接。 Python版本会定期访问该网站并更新列表。

多平台
支持任何运行Python的平台。 事实证明,即使在iPad上也可以运行它,但是,外部传入连接已被设备阻止。 Windows被单独支持,令我惊讶的是,有多少人在此操作系统下启动代理。 尽管在Windows下,如果您使用虚拟化技术或docker,则可以运行正式客户端。

无需docker即可轻松运行的能力。
如果(突然)有些人不喜欢docker,可以在没有它的情况下启动代理。 您需要在配置文件中至少指定两个参数:port和secret,还可以设置可选的广告标记,然后运行命令:python3 mtprotoproxy.py。 但是,在这种情况下,您将不得不考虑在OS中自动运行,例如,为systemd编写单元文件。 您还需要安装pycrypto或pycryptodome,如果没有,它将无法正常运行,但是速度非常慢。

对于docker,可以使用docker-compose up --build命令来重建容器。

计划于下一个版本发布的功能


限制下载大文件的速度。
下载大文件时,可以在TCP级别上“询问”中间代理服务器或Telegram服务器以更慢地发送数据。 现在,这可以通过设置较小的接收缓冲区值来完成,这还可以节省服务器内存。

流消息。
现在,所有已知的使用中间代理的代理服务器都首先从客户端读取消息,然后才进行传输。 一条消息的大小可以达到1MB。 需要一个存储器来存储它,并且传输延迟会稍微增加。 您可以传输数据流。 这会使代码复杂化,但在最坏的情况下将减少内存消耗。

更改数据包的长度可绕过数据包的长度绕过过滤器
我没有设法进入发行版。

安装和启动


  1. git clone -b稳定github.com/alexbers/mtprotoproxy.git; cd mtprotoproxy
  2. (可选,建议)在config.py中指定PORTUSERSAD_TAG
  3. docker-compose up --build -d(或python3 mtprotoproxy.py,因此没有docker)
  4. (可选,显示形式为tg的链接://) docker-compose logs

图片

支持频道广告的MTProto代理的其他实现:


致谢
seriyps-帮助测试真实用户
shifttstas-有关docker技巧
forst (github)-关于IPv6工作的想法和实施
p1ratrulezzz (github)-有关该项目的技巧和文章
freekzy (github)-用于带有句柄泄漏的错误补丁

UPD:编译MTProto代理的不同实现的存储库: github.com/mtProtoProxy

Source: https://habr.com/ru/post/zh-CN414139/


All Articles