Lanzamiento del proxy MTProto no oficial en Python, características del protocolo

imagen

Recientemente, los desarrolladores de Telegram han publicado el código fuente de un servidor proxy que se ejecuta en el protocolo MTProto. Los artículos sobre las características de su ensamblaje y el reempaque del contenedor acoplable con él se publicaron en el hub . El servidor proxy oficial, escrito en C, sorprende con la cantidad de código, aproximadamente 23 mil líneas. Al mismo tiempo, y a veces un poco antes, surgieron varias implementaciones alternativas, pero ninguna de ellas admitía la posibilidad de anunciar su canal.

En este artículo, me gustaría, en primer lugar, hablar sobre las características poco conocidas del protocolo para comunicar un servidor proxy con servidores externos y, en segundo lugar, hablar sobre nuestro propio desarrollo: la implementación de un servidor proxy en Python, que acaba de lanzarse y está disponible para todos Licencia MIT gratuita.

Características de la interacción del servidor proxy con servidores externos.


  1. El servidor proxy oficial no interactúa directamente con los servidores de telegramas, pero utiliza al menos una capa proxy más para esto. Los llamaremos middle-proxy , su lista está disponible en core.telegram.org/getProxyConfig y core.telegram.org/getProxyConfigV6 . La conexión IPv6 aún no es compatible con el servidor proxy oficial.
  2. Para cifrar datos entre el servidor proxy y el proxy medio, se utiliza una clave que se obtiene de las direcciones IP de ambos nodos. Por lo tanto, el servidor proxy para conectarse al proxy medio debe conocer su dirección IP externa, de lo contrario, las claves de cifrado en uno y el otro lado serán diferentes. Además, los números de puerto de ambos nodos y el secreto compartido, disponibles en core.telegram.org/getProxySecret, participan en la formación de la clave. Los desarrolladores de Telegram recomiendan actualizar este secreto una vez al día.
  3. Al conectar un servidor proxy a un proxy medio, el primero transfiere su tiempo. Si el tiempo difiere en más de unos pocos minutos, el segundo lado cierra la conexión.
  4. Al enviar un mensaje del cliente al proxy central, el mensaje se envuelve en una llamada RPC al protocolo MTProto. En cada una de estas llamadas RPC, el proxy agrega varios argumentos: ip y puerto de ambos nodos, un identificador de conexión aleatorio, así como la etiqueta del servidor proxy utilizada para mostrar el canal publicitario en la aplicación. Estos argumentos adicionales ocupan aproximadamente 96 bytes. Debido a esta característica, no será posible mostrar canales publicitarios cuando trabaje directamente, no a través de un proxy intermedio.
  5. Los servidores de Telegram "creen" la información sobre el cliente ip recibido del servidor proxy. Estas direcciones se pueden ver en la información de la sesión (se dibuja el rectángulo):
    imagen

  6. Una conexión TCP entre el servidor proxy y el proxy medio envía mensajes de diferentes usuarios. En las solicitudes y respuestas hay un argumento "identificador de conexión aleatorio", que es necesario para que los datos lleguen al cliente correcto.
  7. Un servidor proxy no puede descifrar los datos del cliente, pero puede distinguir los mensajes regulares de los archivos transmitidos. Además, él conoce el tamaño de cada mensaje.

Fuf, espero no estar cansado de los detalles técnicos. Ahora debe quedar claro por qué en muchos servidores proxy alternativos no hay soporte publicitario: envían mensajes directamente a los servidores de telegramas, sin pasar por el proxy intermedio. Resulta mucho más fácil. La segunda parte del artículo describe la primera implementación no oficial de un servidor proxy que funciona a través del proxy medio. Por el momento, en el dominio público puede encontrar tres implementaciones de este tipo: oficial, en Erlang y esta.

Implementación de proxy Python


Inicialmente, el servidor proxy se escribió para comprender las características del protocolo y fue el desarrollo de otro proyecto: un proxy de calcetines asíncronos, escrito, a su vez, para "tocar" asíncrono / esperar en Python.

Poco a poco, el proyecto comenzó a tener usuarios que se vieron inundados de preguntas, informes de errores y solicitudes de funciones. Después de las mejoras, el proyecto entró en la etapa de prueba beta y estabilización, que duró aproximadamente una semana e involucró a cinco servidores de diferentes configuraciones.

Antes de hablar sobre las características que el servidor proxy oficial aún no tiene, pero el proxy alternativo sí tiene (y guardar silencio sobre las funciones que el proxy oficial no tiene como alternativa), hablaré sobre lo que muchas personas piensan primero cuando mencionan la palabra Python .

Rendimiento


Para las pruebas de rendimiento, se utilizó una máquina virtual en una nube de configuración mínima: 1 CPU, 1024 MB de RAM.

En las pruebas sintéticas, el servidor proxy pudo transmitir aproximadamente 240 megabits / seg o 3000 mensajes / seg. Cuando se usa una implementación alternativa del bucle de eventos en C, que se llama uvloop, y también cuando se usa el intérprete PyPy, los datos de rendimiento son diferentes (todas las mediciones son por segundo):
imagen

Al probar en usuarios reales, resultó que dicho servidor era suficiente para atender cómodamente a 4.000 usuarios u 8.000 cuando usaba PyPy. Una gran sorpresa fue que, sin importar cómo se anunciara el servidor de prueba en los canales de habla rusa, todavía el 89% de los usuarios eran de Irán (quizás para otros países el número de usuarios servidos simultáneamente será diferente). Se ve así:

imagen

Pregunté a varios administradores de otros servidores: su situación es la misma. Quizás esto se deba al hecho de que en Rusia el telegrama funciona bien sin servidores proxy. En Irán, los servidores de prueba fueron bloqueados para el público varias horas después de su creación.

imagen

Carga del servidor con 2.000 usuarios. El momento de bloquear el servidor para los ciudadanos iraníes es claramente visible.

Por lo tanto, el rendimiento de la CPU no es un cuello de botella en el nodo de prueba. Con 10.000 clientes, es probable que se agote la memoria.

No se implementa el uso simultáneo de varios núcleos de CPU (hola, GIL).

Características que el servidor proxy oficial aún no tiene


Trabaja en el protocolo IPv6.
Un servidor proxy sin configuración adicional puede usar IPv6 para conexiones salientes. Las conexiones IPv6 no están bloqueadas en Rusia (por ahora).

Modo de funcionamiento sin proxy intermedio
Si no se necesita publicidad en el canal, el proxy se conecta automáticamente directamente a los servidores de telegramas, sin pasar por el proxy intermedio. Es más rápido y más confiable.

Además, se implementa el " modo rápido " opcional, cuando los mensajes del servidor Telegram al proxy y del proxy al cliente se cifran con la misma clave. Por lo tanto, el proxy no necesita volver a cifrar los mensajes: los envía tal cual. Esto no debería afectar la seguridad. En cualquier caso, el administrador proxy no tiene acceso a los mensajes de los usuarios.

Actualice automáticamente la lista de proxy intermedio y el secreto una vez al día.
El servidor proxy oficial para actualizar la lista de proxy intermedio recomienda reiniciar el contenedor docker una vez al día, lo que restablece todas las conexiones. Es posible que no se establezcan nuevas conexiones si, por ejemplo, un servidor está bloqueado en el país. La versión de Python visita periódicamente el sitio y actualiza la lista.

Multiplataforma
Cualquier plataforma que ejecute Python es compatible. Resultó funcionar incluso en el iPad, sin embargo, el dispositivo bloqueó las conexiones entrantes externas. Windows es compatible por separado, fue una sorpresa para mí cuántas personas lanzan proxies bajo este sistema operativo. Aunque en Windows puede ejecutar el cliente oficial si utiliza tecnologías de virtualización o acoplador.

La capacidad de correr fácilmente sin docker.
Si (de repente) hay quienes no les gusta Docker, se puede iniciar un proxy sin él. Debe especificar al menos dos parámetros en el archivo de configuración: puerto y secreto, también puede establecer la etiqueta publicitaria opcional, luego ejecutar el comando: python3 mtprotoproxy.py. Sin embargo, en este caso, tendrá que pensar en la ejecución automática en el sistema operativo, por ejemplo, escribir un archivo unitario para systemd. También necesitará instalar pycrypto o pycryptodome, sin él funcionará, pero muy lentamente.

En el caso de docker, el contenedor se puede reconstruir con el comando docker-compose up --build.

Características programadas para el próximo lanzamiento


Limitar la velocidad de descarga de archivos grandes.
Al descargar archivos grandes, puede, en el nivel TCP, "pedir" al proxy intermedio o al servidor Telegram que envíe datos más lentamente. Ahora esto se hace configurando un pequeño valor del búfer de recepción, que además ahorra memoria del servidor.

Streaming de mensajes.
Ahora, todos los servidores proxy conocidos que trabajan con proxy intermedio primero leen el mensaje del cliente y solo luego lo transmiten. El tamaño de un mensaje puede alcanzar 1 MB. Se requiere una memoria para su almacenamiento y el retraso de transmisión aumenta ligeramente. Puede transferir la transmisión de datos. Esto complicará el código, pero reducirá el consumo de memoria en el peor de los casos.

Cambie la longitud de los paquetes para omitir el filtro a lo largo de la longitud del paquete .
No logré entrar en el lanzamiento.

Instalación y lanzamiento


  1. git clone -b estable github.com/alexbers/mtprotoproxy.git; cd mtprotoproxy
  2. (opcional, recomendado) especifique PORT , USERS y AD_TAG en config.py
  3. docker-compose up --build -d (o python3 mtprotoproxy.py, sin docker)
  4. (opcional, muestra un enlace de la forma tg: //) registros de docker-compose

imagen

Otras implementaciones de proxy MTProto con soporte para publicidad en canales:


Agradecimientos
seriyps : para obtener ayuda con las pruebas en usuarios reales
shifttstas - para consejos de docker
forst (github): para la idea e implementación del trabajo en IPv6
p1ratrulezzz (github) - para consejos y un artículo sobre el proyecto
freekzy (github): para un parche de error con fuga de mango

UPD: repositorio que compila diferentes implementaciones del proxy MTProto: github.com/mtProtoProxy

Source: https://habr.com/ru/post/es414139/


All Articles