Lançamento do proxy MTProto não oficial em Python, recursos de protocolo

imagem

Recentemente, os desenvolvedores do Telegram publicaram o código-fonte de um servidor proxy que é executado no protocolo MTProto. Os artigos sobre os recursos de sua montagem e a reembalagem do contêiner de docker com ele foram publicados no hub . O servidor proxy oficial, escrito em C, surpreende com a quantidade de código - aproximadamente 23 mil linhas. Ao mesmo tempo, e algumas vezes um pouco antes, surgiram várias implementações alternativas, mas nenhuma delas suportou a possibilidade de anunciar seu canal.

Neste artigo, primeiramente, gostaria de falar sobre os recursos pouco conhecidos do protocolo para comunicar um servidor proxy com servidores externos e, em segundo lugar, sobre seu próprio desenvolvimento - a implementação de um servidor proxy em Python, que acabou de ser lançado e está disponível para todos os usuários. Licença MIT grátis.

Recursos da interação do servidor proxy com servidores externos


  1. O servidor proxy oficial não interage diretamente com os servidores de telegrama, mas usa pelo menos mais uma camada de proxy para isso. Nós os chamaremos de proxy intermediário , sua lista está disponível em core.telegram.org/getProxyConfig e core.telegram.org/getProxyConfigV6 . A conexão IPv6 ainda não é suportada pelo servidor proxy oficial.
  2. Para criptografar dados entre o servidor proxy e o proxy intermediário, é usada uma chave obtida dos endereços IP dos dois nós. Portanto, o servidor proxy para conectar-se ao proxy intermediário deve conhecer seu endereço IP externo; caso contrário, as chaves de criptografia de um lado e do outro serão diferentes. Além disso, os números de porta dos nós e o segredo compartilhado, disponíveis em core.telegram.org/getProxySecret, participam da formação da chave. Os desenvolvedores de telegrama recomendam atualizar esse segredo uma vez por dia.
  3. Ao conectar um servidor proxy ao proxy intermediário, o primeiro transfere seu tempo. Se o tempo diferir em mais de alguns minutos, o segundo lado fecha a conexão.
  4. Ao enviar uma mensagem do cliente para o proxy intermediário, a mensagem é agrupada em uma chamada RPC ao protocolo MTProto. Em cada chamada RPC, o proxy adiciona vários argumentos: ip e porta de ambos os nós, um identificador de conexão aleatório e a tag do servidor proxy usada para exibir o canal de publicidade no aplicativo. Esses argumentos adicionais ocupam aproximadamente 96 bytes. Devido a esse recurso, não será possível exibir canais de publicidade ao trabalhar diretamente, não através do proxy intermediário.
  5. Os servidores de telegrama “acreditam” nas informações sobre o cliente IP recebido do servidor proxy. Esses endereços podem ser vistos nas informações da sessão (o retângulo é desenhado):
    imagem

  6. Uma conexão TCP entre o servidor proxy e o proxy intermediário envia mensagens de diferentes usuários. Nas solicitações e respostas, há um argumento "identificador de conexão aleatória", necessário para que os dados cheguem ao cliente certo.
  7. Um servidor proxy não pode descriptografar dados do cliente, mas pode distinguir mensagens regulares de arquivos transmitidos. Além disso, ele sabe o tamanho de cada mensagem.

Fuf, espero não estar cansado dos detalhes técnicos. Agora deve ficar claro por que em muitos proxies alternativos não há suporte para publicidade - eles enviam mensagens diretamente para os servidores de telegrama, ignorando o proxy do meio. Acontece muito mais fácil. A segunda parte do artigo descreve a primeira implementação não oficial de um servidor proxy que funciona por meio do proxy intermediário. No momento, no domínio público, você pode encontrar três dessas implementações: oficial, em Erlang e esta.

Implementação de proxy Python


Inicialmente, um servidor proxy foi escrito para entender os recursos do protocolo e foi o desenvolvimento de outro projeto - um proxy de meias assíncronas, escrito, por sua vez, para "tocar" em assíncrono / aguardar em Python.

Gradualmente, o projeto começou a ter usuários inundados de perguntas, relatórios de erros e solicitações de recursos. Após melhorias, o projeto entrou no estágio de teste e estabilização beta, que durou cerca de uma semana e envolveu cinco servidores de configurações diferentes.

Antes de falar sobre os recursos que o servidor proxy oficial ainda não possui, mas o proxy alternativo possui (e fique em silêncio sobre as funções que o proxy oficial não possui, a alternativa), falarei sobre o que muitas pessoas pensam quando mencionam a palavra Python .

Desempenho


Para teste de desempenho, uma máquina virtual foi usada em uma nuvem de configuração mínima: 1 CPU, 1024 MB de RAM.

Em testes sintéticos, o servidor proxy conseguiu transmitir cerca de 240 megabits / s ou 3000 mensagens / s. Ao usar uma implementação alternativa do loop de eventos em C, chamada uvloop, e também ao usar o interpretador PyPy, os dados de desempenho são diferentes (todas as medidas são por segundo):
imagem

Ao testar em usuários reais, verificou-se que havia um servidor suficiente para atender 4.000 usuários ou 8.000 ao usar o PyPy. Uma grande surpresa foi que, independentemente de como o servidor de teste era anunciado nos canais de língua russa, ainda 89% dos usuários eram do Irã (talvez para outros países, o número de usuários atendidos simultaneamente seja diferente). É assim:

imagem

Perguntei a vários administradores de outros servidores - a situação deles é a mesma. Talvez isso se deva ao fato de que na Rússia o telegrama funciona bem sem servidores proxy. No Irã, os servidores de teste foram bloqueados para o público várias horas após sua criação.

imagem

Carga do servidor com 2.000 usuários. O momento de bloquear o servidor para os cidadãos iranianos é claramente visível.

Portanto, o desempenho da CPU não é um gargalo no nó de teste. Com 10.000 clientes, é provável que a memória se esgote.

O uso simultâneo de vários núcleos da CPU não é implementado (Olá, GIL).

Recursos que o servidor proxy oficial ainda não possui


Trabalhe no protocolo IPv6.
Um servidor proxy sem configuração adicional pode usar o IPv6 para conexões de saída. As conexões IPv6 não estão bloqueadas na Rússia (por enquanto).

Modo de operação sem proxy intermediário
Se a publicidade do canal não for necessária, o proxy se conectará automaticamente diretamente aos servidores de telegrama, ignorando o proxy do meio. É mais rápido e mais confiável.

Além disso, o " modo rápido " opcional é implementado quando as mensagens do servidor Telegram para o proxy e do proxy para o cliente são criptografadas com a mesma chave. Portanto, o proxy não precisa criptografar novamente as mensagens - ele as envia como estão. Isso não deve afetar a segurança. De qualquer forma, o administrador proxy não tem acesso às mensagens do usuário.

Atualize automaticamente a lista de proxy intermediário e o segredo uma vez por dia.
O servidor proxy oficial para atualizar a lista de proxy do meio recomenda reiniciar o contêiner do docker uma vez por dia, o que redefine todas as conexões. Novas conexões podem não ser estabelecidas se, por exemplo, um servidor estiver bloqueado no país. A versão Python visita periodicamente o site e atualiza a lista.

Multiplataforma
Todas as plataformas executando o Python são suportadas. Acabou sendo executado mesmo no iPad, no entanto, as conexões externas de entrada foram bloqueadas pelo dispositivo. O Windows é suportado separadamente, e foi uma surpresa para mim quantas pessoas iniciam proxies nesse SO. Embora no Windows, você possa executar o cliente oficial se usar tecnologias de virtualização ou janela de encaixe.

A capacidade de executar facilmente sem janela de encaixe.
Se (de repente) houver quem não goste do docker, um proxy poderá ser iniciado sem ele. Você precisa especificar pelo menos dois parâmetros no arquivo de configuração: porta e segredo, também pode definir a tag de publicidade opcional e executar o comando: python3 mtprotoproxy.py. No entanto, nesse caso, você terá que pensar na execução automática no SO, por exemplo, gravar arquivo de unidade para systemd. Você também precisará instalar o pycrypto ou pycryptodome, sem que ele funcione, mas muito lentamente.

No caso da janela de encaixe, o contêiner pode ser reconstruído com o comando docker-compose up --build.

Recursos agendados para o próximo lançamento


Limitando a velocidade de download de arquivos grandes.
Ao baixar arquivos grandes, você pode, no nível TCP, "pedir" ao proxy intermediário ou ao servidor Telegram para enviar dados mais lentamente. Agora, isso é feito configurando um pequeno valor do buffer de recebimento, que economiza adicionalmente a memória do servidor.

Streaming de mensagens.
Agora, todos os servidores proxy conhecidos que trabalham com o proxy intermediário primeiro leem a mensagem do cliente e somente depois a transmitem. O tamanho de uma mensagem pode atingir 1 MB. É necessária uma memória para seu armazenamento e o atraso na transmissão é ligeiramente aumentado. Você pode transferir o fluxo de dados. Isso complicará o código, mas reduzirá o consumo de memória na pior das hipóteses.

Altere o comprimento dos pacotes para ignorar o filtro ao longo do comprimento do pacote .
Não consegui entrar no lançamento.

Instalação e lançamento


  1. git clone -b stable github.com/alexbers/mtprotoproxy.git; cd mtprotoproxy
  2. (opcional, recomendado) especifique PORT , USERS e AD_TAG em config.py
  3. docker-componha --build -d (ou python3 mtprotoproxy.py, portanto, sem docker)
  4. (opcional, exibe um link no formato tg: //) logs do docker-compose

imagem

Outras implementações do proxy MTProto com suporte para publicidade em canais:


Agradecimentos
seriyps - para obter ajuda com testes em usuários reais
shifttstas - para obter dicas do docker
forst (github) - para a ideia e implementação de trabalho no IPv6
p1ratrulezzz (github) - para obter dicas e um artigo sobre o projeto
freekzy (github) - para uma correção de bug com vazamento de identificador

UPD: repositório que compila diferentes implementações do proxy MTProto : github.com/mtProtoProxy

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


All Articles