Зачем они так сделали и зачем нужен секрет https://core.telegram.org/getProxySecret, который все и так знают является для меня большой загадкой. Возможно, у них есть внутренние middle-proxy, секрет которых знают не все.
Авторы протокола предприняли много усилий, чтобы заблокировать было сложно. В протоколе клиент телеграм<->прокси нет сигнатуры, трафик выглядит как случайный поток байт, в котором четыре определённых байта — проверочные, но проверить можно только если знать секрет прокси сервера. Можно блокировать пакеты, которые выглядят как случайный поток байт или определённой длины, но при таких блокировках пострадают другие сервисы, работающие на непопулярных протоколах.
В плане потребления ресурсов они pycryptodome и pycrypto работают примерно одинаково. Мне больше нравится первый, он активнее развивается и под windows легче устанавливается. Slow implementation медленный, но если скорости хватает, то можно оставаться на нём.
В протоколе mtproto элементарная единица информации — rpc-вызов, грубо говоря это длина данных и сами данные. Каждый rpc-вызов официальный прокси отправляет по случайному исходящему соединению на middle proxy. Кидать меньшими кусками чем один rpc вызов на случайное сооединение не получится т.к. один сервер получит "отправить сообщение пользова" а второй "телю bay: привет". Если отправлять маленькими кусками по мере прихода данных от клиента, то все равно нужно сначала написать полный размер сообщения, потом вставить "отправить сообщение пользова" и ждать остальных данных, при этом данное соединение, пока не дождёмся конца сообщения, нельзя использовать для передачи данных других пользователей.
То есть отличие в том, что, используя простую схему с одним исходящим соединением на каждого клиента, прокси может просто брать байты от клиента и передавать их на сервера телеграм вообще не думая не про какие границы сообщений и rpc-вызовы — сервера телеграма на той стороне сами разберутся. А в случае с мультиплексированными соединениеми появляются некоторые сложности.
Видяшка полетит не одним куском, сервер телеграма сам разобьёт её на rpc-сообщения килобайт по 100.
P.S. тут ещё наверно возникнет вопрос почему официальный прокси не может разбить один 100КБ запрос от клиента на два запроса по 50КБ по разным соединениям. Ответ — потому что запрос от клиента зашифрован и прокси не знает каким ключём.
Есть очень простая схема работы прокси сервера — клиент подключается к нему а он — к серверу телеграма. Пришли данные от клиента — перешифровываем, посылаем на сервер и наоборот. Такая схема работает в почти всех альтернативных клиентах, но при этом теряется возможность показывать рекламу т.к. прокси должен как-то "представиться" серверу тг.
Более сложная схема, реализованная в официальном прокси: есть N клиентов и M соединений к вышестоящим прокси. Прокси вычитывает очередной зашифрованный MTProto-вызов от клиента (длину мы знаем, она не шифруется), составляет новый rpc-вызов MTProto к вышестоящему прокси с параметрами, включающими в себя зашифрованный вызов и данные о клиенте. Затем берётся любое из M соединений и туда отсылается этот rpc-вызов. После этого входящие данные от серверов тг для этого клиента начинают приходить в виде rpc-вызовов в этом соединении. Прокси, соответственно, читает читает очередной rpc-вызов из соединения, достаёт оттуда данные о клиенте и сами зашифрованные данные которые нужно ему передать, находит какому клиенту передать и передаёт.
Таким образом можно, например используя одно TCP соединение к вышестоящему прокси-серверу, обслужить 10 клиентов, оборачивая каждое зашифрованное сообщение от клиента в rpc-вызов и передавая его по этому соединению.
Отличный вопрос. Это у них пул соединений к middle proxy (которые перечислены на https://core.telegram.org/getProxyConfig). По одному соединению передаются данные сразу нескольких пользователей, обёрнутые в RPC-вызовы. Когда клиентов становится много, пул соединений увеличивается.
К плюсам такой схемы относится то, что это позволяет сэкономить немного времени при подключении очередного клиента т.к. не нужно устанавливать новое соединение — оно уже есть. Кроме того, это позволяет обойти ограничение протокола TCP в 65 000 исходящих соединений на один и тот же адрес/порт.
Главный минус схемы — необходимость передавать в каждом исходящем сообщении дополнительные данные о клиенте, что приводит к повышенному потреблению исходящего трафика сервером. Другой минус — что по такому "общему" соединению приходится передавать данные на максимальной скорости т.е. нельзя например получить от клиента первые 4096 зашифрованных байтов вызова MTProto и сразу отправить их в соединение, приходится получать всё зашифрованное сообщение, которое часто достигает 100КБ и только потом отправлять. Это приводит к повышенному потреблению памяти прокси-сервером.
Придумал хорошее решение для телеграма —писать в информации о сессиях помимо ip-адреса клиента ещё и адрес прокси сервера, которым он пользовался. Надеюсь, создатели тг тоже придумали такое решение и уже пишут :)
Наконец-то нашёл (точнее мне написали) причину по которой передаётся информация о клиенте — она используется для того, чтобы показать с каких ip был вход, чтобы улучшить безопасность аккаунта. Я в своей реализации забил информацию о клиенте буквами 'A' и теперь вижу такое:
Но, с другой стороны, сейчас стало возможно "убеждать" телеграм, что на наго зашли с произвольного ip
Официальный прокси коннектится к тг через ещё один уровень проксей — так называемый middleware-прокси (это те, которые раз в сутки нужно обновлять и которые живут на https://core.telegram.org/getProxyConfig). Для общения с этими прокси серверами используется rpc-вызовы протокола mtproto, который сам по себе довольно развесистый. Интереснен факт, что ключ, которым шифруются данные между телеграммовским прокси и middleware-прокси получается из данных, включающих строку доступную всем по адресу https://core.telegram.org/getProxySecret и ip/порта клиента и сервера. Таким образом прокси должен знать свой внешний ip/порт, чтобы создать соединение ко middleware-прокси. Официальный докер-образ берёт ip на https://digitalresistance.dog/myIp.
Неофициальные реализации игнорируют middware-прокси и соединяются напрямую к серверам телеграма. Получается проще, надёжнее и экономичнее по трафику — официальный прокси прикрепляет примерно 96 байт в каждое сообщение — информацию о клиенте и рекламный тег). Но при таком способе нельзя добавить рекламу, что является его существенным недостатком.
я тут недавно разбирался с их протоколом, официальный прокси во-первых соединяется с ещё одним уровнем проксей — middleware proxies. Во-вторых он общается с ними по протоколу mtproto, оборачивая каждый кусок отправляемых данных в rpc-вызов протокола mtproto и добавляя примерно 96 байт оверхэда. На загрузку больших файлов не должно влиять, а вот на latency и на объем исходящего трафика при маленьких сообщениях — может
Судя по размеру этого патча, можно сделать вывод, что создатели телеграма использовали очень оригинальную схему передачи тега для таких каналов. В частности там используется ещё один слой проксей на их стороне с которым идёт общение по протоколу mtproto. Каждое сообщение помещается в RPC-вызов этого протокола. Информация о проксе передаётся в каждом исходящем RPC-сообщении, что добавляет около 96 байт оверхэда.
Теперь я понял, почему в официальном прокси сервере 22 тысячи строчки кода.
добавлю, что протокол mtproto сложнее заблокировать сигнатурным анализом т.к. если не знать секретного ключа, протокол общения клиента и прокси неотличим от случайного потока байт
Она печатается на консоль раз в 10 минут. Если запускать через docker-compose, то посмотреть консоль можно командой docker-compose logs. Период статистики может быть изменён с помощью опции STATS_PRINT_PERIOD в config.py
Почитал исходники телеграма. Настройки promoted каналов прилетают с сервера с помощью api-вызова help.getProxyData, который возвращает или help.proxyDataEmpty (пусто) или help.proxyDataPromo. Самое интересное, что вызов help.getProxyData не имеет входных параметров, т.е. телеграм "знает" что клиент в этой сессии сидит через прокси и через какой именно.
Кроме этого, в исходниках реализован ежечасный апдейт promoted channels, что означает что они могут динамически меняться.
Самое вероятное как это может быть сделано — прокси перед передачей первого пакета клиента, вставляет в исходящее tcp-соединение ложный api-вызов со своим уникальным идентификатором (например с api_id и api_hash) и тг-сервер это запоминает.
Я пока видел только один работающий promoted-канал, который утверждает что прокси, ведущие на него, работают на официальном софте от Telegram
С promoted-каналами пока не всё так просто, похоже нужно уметь их регистирировать на стороне телеграма. Если кто знает как это сделать, скиньте пожалуйста личным сообщением.
Не совсем понял вопрос. При подключении к прокси клиент отсылает число от 1 до 5 — номер сервера, к которому нужно подключиться. Ожидается, что прокси подключится именно по адресу, соответствующему заданному серверу, а если подключиться к соседнему, то соединение дропается. Можно настроить маршрутизацию так, чтобы пакеты на эти адреса шли через виртуальное устройство, которое осуществит туннелирование.
Свежие новости: ускорен aes в 665 раз за счёт использования модуля pycrypto, при его наличии. Решена проблема с загрузкой картинок и аудиозаписей — клиент телеграмма при попытке скачивания файлов указывает отрицательный номер сервера, сейчас это корректно обрабатывается. Пока неизвестно бага это или фича, ведь по количеству отрицательных номеров серверов администратор может понять сколько картинок/аудиозаписей/файлов скачал пользователь.
Прокси должен его знать. Официальному прокси нужно указывать ip при запуске с помощью ключа --nat-info, а то он использует ip какого-нибудь интерфейса. Официальный прокси в докер-образе ходит на https://digitalresistance.dog/myIp и узнаёт его. Питоновский ходит на https://v4.ifconfig.co/ip и https://v6.ifconfig.co/ip.
Зачем они так сделали и зачем нужен секрет https://core.telegram.org/getProxySecret, который все и так знают является для меня большой загадкой. Возможно, у них есть внутренние middle-proxy, секрет которых знают не все.
По IP с которого пришёл пакет.
Действительно. Дополнил статью ссылкой на репозиторий https://github.com/mtProtoProxy, в котором собраны разные реализации MTProto-прокси.
Есть идея попробовать опцию SO_REUSEPORT, которая позволяет заслушать один и тот же порт несколькими процессами. Думаю, это должно помочь.
Авторы протокола предприняли много усилий, чтобы заблокировать было сложно. В протоколе клиент телеграм<->прокси нет сигнатуры, трафик выглядит как случайный поток байт, в котором четыре определённых байта — проверочные, но проверить можно только если знать секрет прокси сервера. Можно блокировать пакеты, которые выглядят как случайный поток байт или определённой длины, но при таких блокировках пострадают другие сервисы, работающие на непопулярных протоколах.
В плане потребления ресурсов они pycryptodome и pycrypto работают примерно одинаково. Мне больше нравится первый, он активнее развивается и под windows легче устанавливается. Slow implementation медленный, но если скорости хватает, то можно оставаться на нём.
В протоколе mtproto элементарная единица информации — rpc-вызов, грубо говоря это длина данных и сами данные. Каждый rpc-вызов официальный прокси отправляет по случайному исходящему соединению на middle proxy. Кидать меньшими кусками чем один rpc вызов на случайное сооединение не получится т.к. один сервер получит "отправить сообщение пользова" а второй "телю bay: привет". Если отправлять маленькими кусками по мере прихода данных от клиента, то все равно нужно сначала написать полный размер сообщения, потом вставить "отправить сообщение пользова" и ждать остальных данных, при этом данное соединение, пока не дождёмся конца сообщения, нельзя использовать для передачи данных других пользователей.
То есть отличие в том, что, используя простую схему с одним исходящим соединением на каждого клиента, прокси может просто брать байты от клиента и передавать их на сервера телеграм вообще не думая не про какие границы сообщений и rpc-вызовы — сервера телеграма на той стороне сами разберутся. А в случае с мультиплексированными соединениеми появляются некоторые сложности.
Видяшка полетит не одним куском, сервер телеграма сам разобьёт её на rpc-сообщения килобайт по 100.
P.S. тут ещё наверно возникнет вопрос почему официальный прокси не может разбить один 100КБ запрос от клиента на два запроса по 50КБ по разным соединениям. Ответ — потому что запрос от клиента зашифрован и прокси не знает каким ключём.
Есть очень простая схема работы прокси сервера — клиент подключается к нему а он — к серверу телеграма. Пришли данные от клиента — перешифровываем, посылаем на сервер и наоборот. Такая схема работает в почти всех альтернативных клиентах, но при этом теряется возможность показывать рекламу т.к. прокси должен как-то "представиться" серверу тг.
Более сложная схема, реализованная в официальном прокси: есть N клиентов и M соединений к вышестоящим прокси. Прокси вычитывает очередной зашифрованный MTProto-вызов от клиента (длину мы знаем, она не шифруется), составляет новый rpc-вызов MTProto к вышестоящему прокси с параметрами, включающими в себя зашифрованный вызов и данные о клиенте. Затем берётся любое из M соединений и туда отсылается этот rpc-вызов. После этого входящие данные от серверов тг для этого клиента начинают приходить в виде rpc-вызовов в этом соединении. Прокси, соответственно, читает читает очередной rpc-вызов из соединения, достаёт оттуда данные о клиенте и сами зашифрованные данные которые нужно ему передать, находит какому клиенту передать и передаёт.
Таким образом можно, например используя одно TCP соединение к вышестоящему прокси-серверу, обслужить 10 клиентов, оборачивая каждое зашифрованное сообщение от клиента в rpc-вызов и передавая его по этому соединению.
Отличный вопрос. Это у них пул соединений к middle proxy (которые перечислены на https://core.telegram.org/getProxyConfig). По одному соединению передаются данные сразу нескольких пользователей, обёрнутые в RPC-вызовы. Когда клиентов становится много, пул соединений увеличивается.
К плюсам такой схемы относится то, что это позволяет сэкономить немного времени при подключении очередного клиента т.к. не нужно устанавливать новое соединение — оно уже есть. Кроме того, это позволяет обойти ограничение протокола TCP в 65 000 исходящих соединений на один и тот же адрес/порт.
Главный минус схемы — необходимость передавать в каждом исходящем сообщении дополнительные данные о клиенте, что приводит к повышенному потреблению исходящего трафика сервером. Другой минус — что по такому "общему" соединению приходится передавать данные на максимальной скорости т.е. нельзя например получить от клиента первые 4096 зашифрованных байтов вызова MTProto и сразу отправить их в соединение, приходится получать всё зашифрованное сообщение, которое часто достигает 100КБ и только потом отправлять. Это приводит к повышенному потреблению памяти прокси-сервером.
Придумал хорошее решение для телеграма —писать в информации о сессиях помимо ip-адреса клиента ещё и адрес прокси сервера, которым он пользовался. Надеюсь, создатели тг тоже придумали такое решение и уже пишут :)
Наконец-то нашёл (точнее мне написали) причину по которой передаётся информация о клиенте — она используется для того, чтобы показать с каких ip был вход, чтобы улучшить безопасность аккаунта. Я в своей реализации забил информацию о клиенте буквами 'A' и теперь вижу такое:

Но, с другой стороны, сейчас стало возможно "убеждать" телеграм, что на наго зашли с произвольного ip
я автор реализации на питоне. Действительно, адвертайзинг у них сделан очень интересным способом, когда я добавил её поддержку, размер кода вырос почти в два раза: https://github.com/alexbers/mtprotoproxy/commit/fee5a0c05ae855d97e12a46253e4ad50395df17c.
Официальный прокси коннектится к тг через ещё один уровень проксей — так называемый middleware-прокси (это те, которые раз в сутки нужно обновлять и которые живут на https://core.telegram.org/getProxyConfig). Для общения с этими прокси серверами используется rpc-вызовы протокола mtproto, который сам по себе довольно развесистый. Интереснен факт, что ключ, которым шифруются данные между телеграммовским прокси и middleware-прокси получается из данных, включающих строку доступную всем по адресу https://core.telegram.org/getProxySecret и ip/порта клиента и сервера. Таким образом прокси должен знать свой внешний ip/порт, чтобы создать соединение ко middleware-прокси. Официальный докер-образ берёт ip на https://digitalresistance.dog/myIp.
Неофициальные реализации игнорируют middware-прокси и соединяются напрямую к серверам телеграма. Получается проще, надёжнее и экономичнее по трафику — официальный прокси прикрепляет примерно 96 байт в каждое сообщение — информацию о клиенте и рекламный тег). Но при таком способе нельзя добавить рекламу, что является его существенным недостатком.
я тут недавно разбирался с их протоколом, официальный прокси во-первых соединяется с ещё одним уровнем проксей — middleware proxies. Во-вторых он общается с ними по протоколу mtproto, оборачивая каждый кусок отправляемых данных в rpc-вызов протокола mtproto и добавляя примерно 96 байт оверхэда. На загрузку больших файлов не должно влиять, а вот на latency и на объем исходящего трафика при маленьких сообщениях — может
наконец, сделал поддержку promoted-каналов: https://github.com/alexbers/mtprotoproxy/commit/fee5a0c05ae855d97e12a46253e4ad50395df17c.
Судя по размеру этого патча, можно сделать вывод, что создатели телеграма использовали очень оригинальную схему передачи тега для таких каналов. В частности там используется ещё один слой проксей на их стороне с которым идёт общение по протоколу mtproto. Каждое сообщение помещается в RPC-вызов этого протокола. Информация о проксе передаётся в каждом исходящем RPC-сообщении, что добавляет около 96 байт оверхэда.
Теперь я понял, почему в официальном прокси сервере 22 тысячи строчки кода.
нормально, он писался под очень дикие нагрузки
добавлю, что протокол mtproto сложнее заблокировать сигнатурным анализом т.к. если не знать секретного ключа, протокол общения клиента и прокси неотличим от случайного потока байт
Она печатается на консоль раз в 10 минут. Если запускать через docker-compose, то посмотреть консоль можно командой docker-compose logs. Период статистики может быть изменён с помощью опции STATS_PRINT_PERIOD в config.py
Почитал исходники телеграма. Настройки promoted каналов прилетают с сервера с помощью api-вызова help.getProxyData, который возвращает или help.proxyDataEmpty (пусто) или help.proxyDataPromo. Самое интересное, что вызов help.getProxyData не имеет входных параметров, т.е. телеграм "знает" что клиент в этой сессии сидит через прокси и через какой именно.
Кроме этого, в исходниках реализован ежечасный апдейт promoted channels, что означает что они могут динамически меняться.
Самое вероятное как это может быть сделано — прокси перед передачей первого пакета клиента, вставляет в исходящее tcp-соединение ложный api-вызов со своим уникальным идентификатором (например с api_id и api_hash) и тг-сервер это запоминает.
Я пока видел только один работающий promoted-канал, который утверждает что прокси, ведущие на него, работают на официальном софте от Telegram
поправил pep8: https://github.com/alexbers/mtprotoproxy/commit/e2ade349d2013a0df1696e842637d11b272a221b
С promoted-каналами пока не всё так просто, похоже нужно уметь их регистирировать на стороне телеграма. Если кто знает как это сделать, скиньте пожалуйста личным сообщением.
Не совсем понял вопрос. При подключении к прокси клиент отсылает число от 1 до 5 — номер сервера, к которому нужно подключиться. Ожидается, что прокси подключится именно по адресу, соответствующему заданному серверу, а если подключиться к соседнему, то соединение дропается. Можно настроить маршрутизацию так, чтобы пакеты на эти адреса шли через виртуальное устройство, которое осуществит туннелирование.
Свежие новости: ускорен aes в 665 раз за счёт использования модуля pycrypto, при его наличии. Решена проблема с загрузкой картинок и аудиозаписей — клиент телеграмма при попытке скачивания файлов указывает отрицательный номер сервера, сейчас это корректно обрабатывается. Пока неизвестно бага это или фича, ведь по количеству отрицательных номеров серверов администратор может понять сколько картинок/аудиозаписей/файлов скачал пользователь.
Следующее на очереди — promoted каналы