Релиз неофициального MTProto прокси на Python, особенности протокола

    image

    Недавно разработчики Telegram выложили исходные тексты прокси-сервера, работающего по протоколу MTProto. На хабре вышли статьи об особенностях его сборки и перепаковке докер-контейнера с ним. Официальный прокси сервер, написанный на С, удивляет объемом кода — примерно 23 тысячи строк. Одновременно с этим, а иногда и чуть раньше, вышло несколько альтернативных реализаций, но ни одна из них не поддерживала возможность рекламы своего канала.

    В данной статье хотелось бы, во-первых, рассказать о малоизвестных особенностях протокола общения прокси-сервера с внешними серверами и, во-вторых, рассказать о собственной разработке — реализации прокси-сервера на Python, которая только что достигла релиза и доступна всем желающим под свободной лицензией MIT.

    Особенности взаимодействия прокси сервера с внешними серверами


    1. Официальный прокси сервер не взаимодействует с серверами телеграма напрямую, а использует для этого ещё, как минимум, один слой прокси-серверов. Мы будем называть их middle-proxy, их список доступен по ссылкам core.telegram.org/getProxyConfig и core.telegram.org/getProxyConfigV6. Соединение по IPv6 пока не поддерживается официальным прокси-сервером.
    2. Для шифрования данных между прокси-сервером и middle-proxy используется ключ, получаемый из ip адресов обеих узлов. Поэтому, прокси-сервер для соединения с middle-proxy должен знать свой внешний ip-адрес, иначе ключи шифрования на одной и на другой стороне будут разными. Помимо этого, в формировании ключа участвуют номера портов обеих узлов и общий секрет, доступный по адресу core.telegram.org/getProxySecret. Разработчики Телеграма рекомендуют обновлять этот секрет раз в сутки.
    3. При подключении прокси-сервера к middle-proxy, первый из них передаёт своё время. Если время отличается больше чем на несколько минут, вторая сторона закрывает соединение.
    4. При посылке сообщения от клиента к middle proxy, сообщение оборачивается в RPC-вызов протокола MTProto. В каждый такой RPC-вызов прокси добавляет несколько аргументов: ip и порт обеих узлов, случайный идентификатор соединения, а также тег прокси сервера, используемый для показа рекламного канала в приложении. Эти дополнительные аргументы занимают примерно 96 байт. Из-за этой особенности не получится показывать рекламные каналы при работе напрямую, не через middle proxy.
    5. Серверы Телеграма «верят» информации об ip клиента, получаемой от прокси-сервера. Эти адреса можно увидеть в информации о сессиях (прямоугольник дорисован):
      image

    6. По одному TCP-соединению между прокси-сервером и middle-proxy передаются сообщения разных пользователей. В запросах и ответах есть аргумент «случайный идентификатор соединения», который нужен для того, чтобы данные попали к нужному клиенту.
    7. Прокси сервер не может расшифровать данные клиента, но может отличить обычные сообщения от передаваемых файлов. Так же, ему известен размер каждого сообщения.

    Фуф, надеюсь не утомил техническими деталями. Теперь должно быть понятно, почему во многих альтернативных прокси нет поддержки рекламы — они передают сообщения напрямую серверам телеграма, минуя middle-proxy. Получается значительно проще. Во второй части статьи описывается первая неофициальная реализация прокси сервера, которая работает через middle-proxy. В данный момент в свободном доступе можно найти три таких реализации: официальную, на Erlang и эту.

    Реализация прокси сервера на Python


    Изначально прокси-сервер писался для того, чтобы понять особенности протокола и был развитием другого проекта — асинхронного сокс-прокси, написанного, в свою очередь, чтобы «потрогать» async/await в Питоне.

    Постепенно у проекта появились пользователи, которые завалили вопросами, баг-репортами и фич-реквестами. После доработок проект вошёл в стадию бета-тестирования и стабилизации, которая длилась примерно неделю и задействовала пять серверов разных конфигураций.

    Перед тем как рассказать о фичах, которых пока нет у официального прокси сервера, но есть у альтернативного (и умолчать о функциях, которые есть у официального и нет у альтернативного), расскажу о вещи, которая у многих первой приходит в голову при упоминании слова Python.

    Производительность


    Для тестирования производительности использовалась виртуальная машина в облаке минимальной конфигурации: 1 CPU, 1024MB RAM.

    На синтетических тестах прокси сервер оказался способен передавать порядка 240мегабит/сек или 3000 сообщений/сек. При использовании альтернативной реализации event-loop'а на С, которая называется uvloop, а также при использовании интерпретатора PyPy данные производительности получаются иные (все измерения — в секунду):
    image

    При тестировании на реальных пользователях оказалось, что такого сервера хватает, чтобы с комфортом обслуживать 4 000 пользователей или 8 000 при использовании PyPy.Большим сюрпризом оказалось то, что как бы не рекламировался тестовый сервер в русскоязычных каналах, все равно 89% пользователей были из Ирана (возможно, для других стран количество одновременно обслуживаемых пользователей будет отличаться). Выглядит это так:

    image

    Я поспрашивал нескольких администраторов других серверов — у них ситуация такая же. Возможно, это связано с тем, что на территории России телеграм хорошо работает без прокси-серверов. В Иране тестовые сервера блокировались для населения спустя несколько часов после создания.

    image

    Нагрузка на сервер при 2 000 пользователях. Чётко виден момент блокировки сервера для граждан Ирана.

    Таким образом производительность CPU не является узким местом на тестируемом узле. При 10 000 клиентах, скорее всего, закончится память.

    Одновременное использование нескольких ядер CPU не реализовано (привет, GIL).

    Фичи, которых пока нет у официального прокси сервера


    Работа по протоколу IPv6.
    Прокси-сервер без дополнительной настройки умеет использовать IPv6 для исходящих соединений. Соединения по IPv6 не блокируются на территории России (пока).

    Режим работы без middle-proxy
    Если реклама канала не нужна, прокси автоматически соединяется напрямую с серверами телеграма, минуя middle-proxy. Это быстрее и надёжнее.

    Так же, реализован опциональный "быстрый режим", когда сообщения от сервера Телеграма до прокси и от прокси до клиента шифруются одним и тем же ключём. Таким образом прокси не нужно перешифровывать сообщения — он отправляет их как есть. На безопасность это не должно влиять т.к. в любом случае у администратора прокси-сервера нет доступа к сообщениям пользователей.

    Автообновление списка middle-proxy и секрета раз в сутки.
    Официальный прокси сервер для обновления списка middle-proxy рекомендует рестартовать docker-контейнер раз в сутки, что сбрасывает все соединения. Новые соединения могут не установиться если, например, в стране заблокировали сервер. Питоновская версия периодически ходит на сайт и обновляет список.

    Многоплатформенность
    Поддерживаются любые платформы, на которых запускается Python. Получалось запустить его даже на iPad, правда, внешние входящие соединения блокировались устройством. Отдельно поддерживается Windows, для меня стало сюрпризом как много людей запускают прокси под данной ОС. Хотя под Windows можно запустить и официальный клиент, если использовать технологии виртуализации или докер.

    Возможность простого запуска без докера.
    Если (вдруг) есть те, кто не любят докер, прокси может быть запущен и без него. Нужно указать минимум два параметра в файле конфигурации: порт и секрет, также можно задать опциональный рекламный тег, затем выполнить команду: python3 mtprotoproxy.py. Правда, в таком случае придётся думать над автозапуском в ОС, например писать unit-file для systemd. Ещё нужно будет установить pycrypto или pycryptodome, без него будет работать, но очень медленно.

    В случае с докером контейнер можно пересобрать командой docker-compose up --build.

    Фичи, запланированные на следующий релиз


    Ограничение скорости скачивания больших файлов.
    При скачивании больших файлов можно, на уровне TCP, «просить» middle-proxy или сервер Телеграма посылать данные медленнее. Сейчас это сделано с помощью установки маленького значения буфера приёма, что дополнительно экономит память сервера.

    Потоковая передача сообщений.
    Сейчас, все известные прокси-серверы, работающие с middle-proxy, сначала считывают от клиента сообщение и только потом его передают. Размер одного сообщения может достигать 1МБ. Требуется память на его хранение и немного увеличивается задержка передачи. Можно передавать данные потоково. Это усложнит код, но сократит потребление памяти в худшем случае.

    Изменение длины пакетов для обхода фильтра по длине пакета.
    Не успело попасть в релиз.

    Установка и запуск


    1. git clone -b stable github.com/alexbers/mtprotoproxy.git; cd mtprotoproxy
    2. (опционально, рекомендуется) указать PORT, USERS и AD_TAG в config.py
    3. docker-compose up --build -d (или python3 mtprotoproxy.py, чтобы без докера)
    4. (опционально, выводит ссылку вида tg://) docker-compose logs

    image

    Другие реализации MTProto-прокси с поддержкой рекламы каналов:


    Благодарности
    seriyps — за помощь с тестированием на реальных пользователях
    shifttstas — за советы по докеру
    forst(github) — за идею и реализацию работы по IPv6
    p1ratrulezzz(github) — за советы и за статью про проект
    freekzy(github) — за патч бага с утечкой дескрипторов

    UPD: репозиторий, в котором собраны разные реализации MTProto-прокси: github.com/mtProtoProxy
    Поделиться публикацией
    Комментарии 80
      +3
      > Одновременное использование нескольких ядер CPU не реализовано (привет, GIL).

      После прочтения этой строки как-то сразу появилось желание попробовать повторить реализацию на Go…
        0

        Можно попробовать запилить.
        Но мне сама идея MTProxy не очень нравится, легкость обнаружения и блокировки. Имхо нужен протокол, который легче прятать.

          +2

          Авторы протокола предприняли много усилий, чтобы заблокировать было сложно. В протоколе клиент телеграм<->прокси нет сигнатуры, трафик выглядит как случайный поток байт, в котором четыре определённых байта — проверочные, но проверить можно только если знать секрет прокси сервера. Можно блокировать пакеты, которые выглядят как случайный поток байт или определённой длины, но при таких блокировках пострадают другие сервисы, работающие на непопулярных протоколах.

            +2
            Вот тут проблема, что там всем наплевать что пострадает :(
              0

              Недавно была статья, где по пунктам разобраны слабые места протокола, упрощающие обнаружение.
              Можете подробнее рассказать, как именно протокол усложняет блокировку?

                0

                Могу. В самом начале клиент генерирует случайные 56 байт и посылает их серверу. На основе этих байт и общего секрета, обе стороны генерируют по два ключа шифрования: для шифрования данных от сервера к клиенту и в обратную сторону. После этого и клиент и сервер перед посылкой данных шифруют их соответствующими ключами.
                После случайных 56 байт клиент посылает зашифрованные магические четыре байта и номер датацентра с которым его должен соединить прокси. По этим магическим четырем байтам сервер понимает, что с ним действительно общаются по нужному протоколу, но, для внешнего наблюдателя эти данные выглядят как случайные т.к. он не знает секрета, на основе которого сформированы ключи шифрования.

            +3

            Erlang версия умеет по ядрам расползаться. Другой вопрос, что из за того как активно прокси блокируют, удобнее иметь 10 одноядерных виртуалок с 10 IP адресами, чем одну на 12 ядер с одним адресом. (Если есть возможность иметь одну с 10 IP адресами то это, конечно, приобретает смысл.)


            Плюс к этому в статье умпоянуто, что обычно узкое место это не CPU, а память.

              +1
              Ну так питон по памяти тоже немного прожорливее Go/C/Erlang.
                0
                Эти 10 адресов будут наверняка в одной небольшой подсети)
              0
              Спасибо, в отличие от официального mtproxy, эта реализация работает без проблем.

              Вопрос возник, при запуске оно ругается что нет pycryptodome или pycrypto, что из этого лучше выбрать в плане наименьшего потребления ресурсов? Или можно на slow AES implementation оставаться?
                +2

                В плане потребления ресурсов они pycryptodome и pycrypto работают примерно одинаково. Мне больше нравится первый, он активнее развивается и под windows легче устанавливается. Slow implementation медленный, но если скорости хватает, то можно оставаться на нём.

                  0

                  А какой из crypto/cryptodome он выберет, если стоят оба, и как на это повлиять?

                    0

                    Насколько я знаю оба установить не получится т.к. у них модули называются одинаково. Есть pycryptodomex у которого называются по-другому модули. Ещё, кстати, поддержал pycryptography, он должен быть очень быстрый т.к. использует openssl

                0
                Одновременное использование нескольких ядер CPU не реализовано (привет, GIL).

                А думали над тем, что бы просто запускать несколько инстансов и через что-то их роутить? Как делает gunicorn например. Из самых простых способов, это nginx + streams.

                  0

                  Нужно как-то передавать по всей цепочке IP адрес клиента (если мы не хотим врать телеграму про IP адреса пользователей). При простой TCP балансировке это невозможно, нужно какой-то протокол изобретать.

                    0

                    Ну, nginx может такие штуки делать.

                      0

                      Ну так и первый способ с proxy_bind это какое-то совсем шаманство, а второе proxy_protocol, как я и сказал, потребует для mtproto proxy дописывать ещё поддержку PROXY protocol.

                    +2

                    Есть идея попробовать опцию SO_REUSEPORT, которая позволяет заслушать один и тот же порт несколькими процессами. Думаю, это должно помочь.

                    0

                    Призываю Vespertilio. Он как раз интересовался подробностями.
                    Тем временем предпосылки к очередной головной боли.

                      0
                      Я вот одного не могу понять, почему возможность использовать несколько SECRET есть, а несколько AD_TAG — нет?
                      Неужели только я хотел бы для узкого круга приближенных дать просто прокси, а всем остальным навязать свой канал и все это без необходимости запуска двух инстансов прокси?
                        0
                        Вот, но это слегка «грязноватая» реализация.
                        0
                        Отличная содержательная статья. Одна из лучших. А почему обойдены вниманием реализации на rust и go? На go даже вполне рабочая (хоть и простая).
                          +2

                          Действительно. Дополнил статью ссылкой на репозиторий https://github.com/mtProtoProxy, в котором собраны разные реализации MTProto-прокси.

                          +1
                          Я бы ещё сделал автоматический образ (чтобы сам подтягивал изменения на github) docker на DockerHub. На той же alpine. И перебивку параметров config.py через командную строку.
                            0
                            Причем на alpine pypy3
                              +2

                              Хорошая идея, попробую реализовать в ближайшее время

                                0
                                А можете сделать 2 образа, один с pypy, другой с cpython (либо один образ, но с опциональным переключением)? Если память является узким местом, то PyPy — не лучший выбор. Помимо скорости, он еще ощутимо более прожорливый в смысле оперативки.
                                  +1

                                  На самом деле потребление памяти получается примерно одинаковым, там почти вся память — разнобразные буферы, которые занимают примерно одинаково на си и на питоне.


                                  С pypy3 и alpine возникла проблема — такого пакета по умолчанию нет. Проблема находится в процессе решения.

                                    0
                                    Гуглится докер для сборки. Там достаточно простой патч и OpenSSL, да.
                            0
                            Кстати, а как определяется IP которым идет подпись?
                              +1

                              По IP с которого пришёл пакет.

                                0
                                Не совсем понял, там же мой proxy добавляет свой IP при коннекте к middle-proxy…
                                  +1

                                  Прокси должен его знать. Официальному прокси нужно указывать 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, секрет которых знают не все.

                              +1
                                0
                                в формировании ключа участвуют номера портов обеих узлов

                                А проверяет ли middleProxy то, что по переданному IP:port слушает именно этот сервис?

                                  0

                                  Почитал. "Проверяет". Но используется не ip:port "сервиса", а ip:port исходящего соединения mtproto proxy в сторону middle proxy.

                                    0
                                    А вот берет он откуда его…
                                      0

                                      Код берёт его из getsockname(). Но из этого следует, что MTProxy адекватно работать не должна за почти любым NAT, в том числе и за докерным. А она вроде как работает.
                                      Надо проверить что ли :-)

                                        0
                                        Родной лезет на сайт и там берет — посмотри в скрипт запуска
                                          0

                                          Это IP. С IP всё сравнительно просто в "обычных" случаях. Мне интересно поведение приложения, если случится на NAT изменение source port, которое в случае с docker носит вероятностный характер.

                                            +1

                                            В таком случае у двух сторон получатся разные ключи шифрования и они "не поймут" друг друга.

                                              0

                                              Да-да. Так и должно быть. Но если это так, это означает, что инструкция имени schors по запуску telegrammessenger/proxy намного лучше, чем официальная. Что довольно забавно :-)

                                                0
                                                Ага, понятно почему на NAT VPS ничего не работало.
                                            +1

                                            Я разобрался, почему никто не говорит про проблемы с докерным NAT и MTProto proxy. Их не то чтоб нет, но они маловероятны.


                                            • Официальный прокси мультиплексирует несколько пользователей в одно исходящее соединение. Т.е. исходящих соединений сравнительно немного.
                                            • Выбор исходящего порта внутри контейнера зависит от port_offset, который зависит от IP клиента. У каждого контейнера свой внутренний IP, поэтому при небольшом числе контейнеров и небольшом числе соединений конфликтов по исходящим TCP портам не случается.
                                            • SNAT и MASQUERADE, через которые трафик из контейнера уходит в интернет, не меняют порт при отсутствии конфликтов: where possible, no port alteration will occur.
                                      0
                                      Хотелось бы конфигурационный файл отдельной сущностью с возможностью указывать через опцию при запуске и в YAML или TOML формате.
                                        0
                                        Да там параметров-то кот наплакал
                                        +1

                                        Чтобы конфигурационный файл был в yaml и указывался через опцию можно написать примерно так: https://pastebin.com/Amzh5jJe


                                        Для других форматов это будет выглядеть аналогично.

                                          0
                                          На мой взгляд конфиг было бы удобнее сделать полностью отдельной сущностью, которую можно положить в любое место и без правки питоновских исходников.
                                        +1
                                        Эта реализация не порождает 50 потоков сразу после запуска как официальная?
                                          +1

                                          Не, не порождает

                                            0
                                            Это уже радует. Запустил на погонять вместо официального. По аппетитам сабжевая реализация потребляет CPU/RAM заметно меньше.
                                              0
                                              А сколько порождает? Или он деманд?
                                                +2

                                                Он деманд

                                                  0

                                                  А что под потоками подразумевается? Трелы ОС в python версии не запускаются вообще, всё однопоточное (asyncio).
                                                  Важное различие между официальным прокси и всеми остальными, что официальный мультиплексирует много коннектов клиент-прокси в небольшое количество коннектов прокси-сервер телеграм.
                                                  Другие реализации всегда создают пару сокетов.

                                                    0
                                                    Сабжевый прокси
                                                    $ sudo systemctl status mtproxy-python.service
                                                    ● mtproxy-python.service - Telegram proxy Python
                                                    ...
                                                    Tasks: 1 (limit: 4915)

                                                    Официальная реализация
                                                    $ sudo systemctl status mtproxy.service
                                                    ● mtproxy.service - Telegram proxy
                                                    ...
                                                    Tasks: 50 (limit: 4915)

                                                      0

                                                      Так это были реально потоки ОС? Я когда увидел 50 посчитал что речь идёт о TCP-потоках.


                                                      Кстати, у прокси есть недокументированная особенность. Если хочется больше одного таска, например, у вас многоядерный CPU и не хватает производительности, то можно просто запустить несколько экземпляров программы. Они автоматически поделят между собой нагрузку.

                                                0

                                                https://github.com/alexbers/mtprotoproxy/issues/20 тут это обсуждается

                                                +2
                                                Молодец, очень радует что развиваешь и что на питоне.
                                                  0
                                                  У меня тоже вопрос в стиле «Неужели только я хотел бы».

                                                  Интересно, почему в реализации прокси полностью отсутствует возможность использования по логину/паролю.
                                                  Неужели только я хотел бы сделать приватный прокси без рекламы только для пользователей своего сайта/сервиса/проекта/стартапа и т.д. Который бы был не публичный, соответственно и менее подвержен блокировке.

                                                  Т.е. чтобы не secret, которых всего 16 штук, а с привязкой к логину/паролю пользователя.
                                                  Отсутствие логина/пароля подается как плюс, однако для меня это жирный минус.
                                                    +2

                                                    Отличный вопрос. У меня есть проект, который работает ровно так как описано: https://github.com/alexbers/tgsocksproxy. Правда, работает по протоколу socks т.к. протокол MTProto не поддерживает испльзование логина/пароля.

                                                      0
                                                      Логин/пароль для socks передаются в открытом виде? Или я ошибаюсь?
                                                        +1

                                                        Да, такой протокол. С этим, к сожалению, ничего не поделать

                                                          +1
                                                          А впилить нельзя? Раз все-равно своя реализация?
                                                            +1

                                                            Впилить можно, но тогда нужно будет пропатчить всех клиентов, чтобы они не передавали в открытом виде пароль.


                                                            В MTProto-версии поддерживается произвольное число секретов, но сильно много не рекомендуется.

                                                              0
                                                              А почему много не рекомендуется? Нагрузка больше?
                                                                +2

                                                                Когда клиент подключается к mtproto серверу, то он присылает 64байта — данные сессии, зашифрованные этим вот секретом. Если расшифровать эти 64 байта правильным секретом, то там в расшифрованном пакете определённой позиции будет проверочная сумма. Если она не совпала, то нужно пробовать расшифровать следующим ключом. Т.е. в худшем случае придётся много раз расшифровывать, перебирая ключ.

                                                                  0
                                                                  Вот оно как. Понятно, спасибо.
                                                                    0
                                                                    А список «клиент-ключ» и его обслуживание сильно повлияет на потребление памяти/CPU?
                                                                    Отслеживание мертвых записей, удаление отключившихся, вот это всё.
                                                                      0

                                                                      Не понял вопрос.
                                                                      Если вы про python mtprotoproxy, то чем больше вы секретов для одного порта назначите, тем больше будет нагрузка на CPU на установление подключения. Максимальная нагрузка будет если кто-то подключится и отправит 64 байта данных, к которым не один ключ не подойдёт, потому что сервер будет вынужден перепробовать их все.

                                                            0

                                                            А чего вы опасаетесь? Если боитесь, что перехватят пароль от вашего сервиса прослушивая трафик SOCKS, генерируйте вашим пользователям отдельные пароли для SOCKS, отличные от паролей от сервиса.

                                                              0
                                                              Да нет, все-равно нужно отдельный пароль делать.

                                                              Начал было отвечать, но понял, что опасения-то одни — что для открытого пароля, что для шифрованного. Разница по возможности утечки не велика, потому что утечка более вероятна от самого пользователя, чем от маловероятного перехвата.
                                                                0
                                                                Это, конечно, в контексте обсуждения SOCKS-прокси, а не MTProto.
                                                                MTProto вообще не вижу как использовать в таком режиме — у всех один секрет (ну или у группы). В случае утечки менять секрет придется не у одного пользователя, а у всех сразу.
                                                          0

                                                          Телеграм сейчас сконцентрирован на количестве и качестве публичных прокскй, поэтому и монетизацию прикрутили в виде промоченный каналов. А приватные прокси в данный момент времени телеграму особо не нужны.

                                                            0
                                                            Как мне кажется, лучше множество неблокируемых приватных, чем быстро блокируемые публичные.
                                                            Точнее — может быть и не лучше, но добавило бы немало.
                                                              0
                                                              Все верно, именно так и живет все, что касается, например, ShadowSocks: быстро разворачиваем, пользуемся, пока не прибили. Сами прокси передаются либо сарафанным радио (во всех клиентах даже есть возможность считывания QR-кода + его генерация для каких-нибудь существующих), либо через сайты вроде free-ss.site Какие уж спонсорские штуки, да множественные секреты.
                                                          0
                                                          Какая производительность офицального прокси на том же железе?
                                                            0
                                                            >Возможность простого запуска без докера
                                                            Официальная версия тоже может работать без докера, достаточно собрать из исходников и запустить. Все это делается в течении двух минут.
                                                              0

                                                              Ключевое слово "простого". Когда я собрал официальный прокси, я дочитал readme до слов "Simple MT-Proto proxy" и ошибочно подумал что запуск будет простым. Примерно таким ./proxy <port> <secret>. Я запустил его с --help и увидел следующее: https://alexbers.com/proxy.png. Затем было несколько часов безуспешных попыток его поднять, закончившиеся гуглением.


                                                              Перечислю несколько проблем, которые усложняют запуск без докера:


                                                              1. Не указан минимальный набор опций, которые необходимо передать, чтобы прокси заработал.
                                                              2. В параметрах сказано, что прокси может быть запущен с конфигурационным файлом, однако, нет информации о формате, в котором он должен быть или примера такого файла
                                                              3. Базовые и экспертные опции идут вперемешку. Понять, что делают некоторые опции можно только читая исходный текст
                                                              4. Для запуска нужно совершить действия, которые, кажутся "магическими": загрузить "секрет" из адреса в интернете, передать свой внутренний и внешний ip-адрес, загрузить некий список узлов
                                                              5. В выводе --help надпись "Simple MT-Proto proxy" вводит в заблуждение. Вместо "simple" можно было бы написать что без чтения readme даже не пытайтесь его поднять.

                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                            Самое читаемое