Open-source project
seriyps/mtproto_proxy avatar
seriyps/mtproto_proxy

mtproto_proxy: an Erlang MTProto proxy with SNI secrets and split mode

High performance Erlang MTProto proxy that powers https://t.me/socksy_bot

803 stars135 forksErlangApache-2.0

At a glance

What is it?
mtproto_proxy is an Apache 2.0 licensed Erlang implementation of the Telegram MTProto proxy, extracted from the socksy_bot project, with randomised packet sizing, a fake-TLS mode, per-SNI secrets and a split front and back layout. The judgement is that the protocol defences are unusually well thought out, while the project itself has been quiet since the last push on 2026-04-14.
Who is it for?
mtproto_proxy fits an operator who needs a Telegram proxy that survives deep packet inspection and who can afford to run a server, or two in split mode, because the dd and fake-TLS protocols, the per-SNI secrets and the replay protection are implemented in the same Erlang codebase.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Erlang, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An Erlang proxy for Telegram traffic, extracted from a Telegram bot

mtproto_proxy is an MTProto proxy written in Erlang, and it carries an Apache 2.0 licence. It was extracted from the socksy_bot project, and the project page says the same code powers the proxy that socksy_bot runs, so the repository is not a toy implementation that has never faced real traffic.

The job is narrow and mechanical. A Telegram client is configured to point at a proxy instead of at Telegram servers, the client speaks the MTProto protocol to the proxy, and the proxy relays the traffic to Telegram. Everything interesting in this codebase sits in how that relay survives inspection, not in the relay itself.

The build system is rebar3, and the repository carries src/, config/, scripts/, test/, doc/, a Dockerfile, a Makefile, start.sh, AGENTS.md and a bundled rebar3 binary. The Makefile exposes a ROLE variable with the values both, front and back, which selects between different sys.config and vm.args templates, so the same repository produces either a single server or the two halves of the split layout.

Two protocols exist to defeat deep packet inspection

The proxy offers two ways for a client to connect, and both exist for the same reason: a censor that can tell MTProto traffic from ordinary HTTPS can block it.

The first is the secure mode, described as a randomised packet size protocol, in which the secret is 34 symbols starting with dd and the proxy varies the size of the packets it sends so the stream does not have the fixed signature of the original protocol. The second is the fake-TLS protocol, which uses secrets that begin with ee and are base64 encoded, so that the connection looks like TLS to an inspector.

The fake-TLS mode has a further trick behind it. When a browser or an inspection probe connects with a wrong or absent secret, the proxy does not reject the connection, it forwards it transparently to the real HTTPS server named in the SNI field. From the outside the host behaves like an ordinary web server, and there is no error to fingerprint.

A secure-only mode restricts the proxy to dd or fake-TLS connections, and it is set through the allowed_protocols option. When a secret is issued through the standard path, the secret is 32 characters long and the dd prefix is added by the client configuration, so appending dd to the secret yourself produces a broken link.

Per-SNI secrets and the split front and back layout

Two design decisions go beyond the ordinary MTProxy feature set, and they are the reason to look at this project rather than at a stock proxy.

The first is per-SNI derived secrets. Each user gets a unique token tied to the fake-TLS domain they were issued for, and the base secret cannot be recovered from the user links. In practice one operator can hand out links that all point at the same proxy while each link reveals nothing about the master secret, and revoking a single user does not mean rotating the secret for everyone.

The second is the split-mode setup. The client-facing half, called front, runs on a server inside the country of the users, and the Telegram-facing half, called back, runs on a server abroad. The two are joined by Erlang distribution over TLS or over a censorship-resistant tunnel, which is what gets around the practice of blocking direct connections from domestic to foreign addresses. Several front servers can share one back server.

Both features landed in the same release. Version 0.8.4, published on 2026-04-11, is titled Split-mode, SNI-secrets and reliability improvements, and the Makefile carries the matching front and back configuration templates.

The one-line installer and the Docker image

Two deployment routes are documented, and the first one is a single command that downloads and runs an interactive script. The script asks whether the default port, secret, ad-tag and protocols should be changed:

bash
curl -L -o mtp_install.sh https://git.io/fj5ru && bash mtp_install.sh

The same script takes the settings as arguments instead of asking, which is what you want for an unattended provisioning run:

bash
curl -L -o mtp_install.sh https://git.io/fj5ru && bash mtp_install.sh -p 443 -s d0d6e111bada5511fcce9584deadbeef -t dcbe8f1493fa4cd9ab300891c0b5b326 -a dd -a tls -d s3.amazonaws.com

Docker is the other route, and the image is published as seriyps/mtproto-proxy. With the defaults it is:

bash
docker run -d --network=host seriyps/mtproto-proxy

Every option also exists as an environment variable, which is the form that fits a container platform:

bash
docker run -d --network=host -e MTP_PORT=443 -e MTP_SECRET=d0d6e111bada5511fcce9584deadbeef -e MTP_TAG=dcbe8f1493fa4cd9ab300891c0b5b326 seriyps/mtproto-proxy

The flag names follow the environment names, so MTP_PORT maps to the proxy port, MTP_SECRET to the 32 character secret, MTP_TAG to the ad-tag obtained from @MTProxybot, MTP_DD_ONLY to the secure only mode and MTP_TLS_ONLY to the fake-TLS only mode.

Installing into the operating system with Erlang and systemd

The documentation recommends the Docker image for small setups of roughly ten to twenty thousand connections, and an operating system install for anything heavier. The quick recipe assumes a recent Ubuntu and a current Erlang:

bash
sudo apt install erlang-nox erlang-dev build-essential
git clone https://github.com/seriyps/mtproto_proxy.git
cd mtproto_proxy/
make init-config   # copies templates and auto-detects your server's IP
# configure your port, secret, ad_tag. See [Settings](#settings) below.
nano config/prod-sys.config
make && sudo make install
sudo systemctl enable mtproto-proxy
sudo systemctl start mtproto-proxy

There is an inconsistency worth knowing about before you start. The quick section says you need at least Erlang version 25 and recommends Ubuntu 24.04, while the detailed section for older distributions states that Erlang version 20 or higher is needed and then gives apt and yum package lists for Ubuntu 18 and 19, Debian 10 and CentOS 7. The two statements cannot both describe the same release, and the conservative reading is to take the newer requirement.

The build itself is a rebar3 release. The Makefile compiles with the prod profile, copies the result under /opt, and installs a systemd unit named mtproto-proxy that the same Makefile also creates for epmd, the Erlang port mapper daemon that the node needs.

Configuration changes without a restart, and the connection policies

Every setting can be changed while the proxy is running, and the Telegram side of the configuration reloads on its own, so a daily restart to pick up new addresses is not needed. The configuration lives in config/prod-sys.config, generated from a template by make init-config, which also fills in the server's public address in the vm.args file.

The policies are the part that turns the proxy into something an operator can hand to users. Connection limits can be applied per IP, per TLS domain and per port, and there are blacklists and whitelists for both IP addresses and TLS domains. Several ports can be served at once, each with its own secret and its own promotional tag, so different user groups can be given different links with different promotion channels attached.

Two more operational details are documented. Client connections can use IPv6, and metrics can be exported, optionally, so a busy proxy can be watched without reading its logs.

The performance figures quoted are for the Erlang implementation: tens of thousands of connections, one gigabit and ninety thousand connections on a four core server with eight gigabytes of RAM. Multiplexing is also supported, wrapping many client connections into a smaller number of connections towards Telegram, which lowers ping and improves use of the operating system's network stack.

The project's own warning, and where the code stands

The most important line in the documentation is a warning rather than a feature. Telegram is described as cooperating with governments, especially the Russian one, and as neither neutral nor fully independent, so the recommendation is to use it only for non-sensitive messaging and to prefer Signal or Session for private conversations. Any deployment plan that routes anything sensitive through this proxy should start from that warning.

The code side is better kept than the documentation often is. The Makefile wires up a full Erlang quality stack: xref for cross reference checks, eunit for unit tests, ct for the common test suites, proper for property based tests with 50 iterations, dialyzer for type analysis and cover for coverage reporting. The README describes the codebase as small compared to the official implementation and says it is covered by automated tests.

Activity is the weak point. The releases listed are 0.7.4 on 2026-02-17, 0.8.1 on 2026-04-03 and 0.8.4 on 2026-04-11, and the last push was on 2026-04-14, with the repository not archived. Between the last release and now there is a gap of months rather than weeks, and there is no public roadmap beyond TODO.md in the repository root. The licence is Apache 2.0, which carries the usual obligations about notices and the licence text, and the support channel is a Telegram chat at t.me/erlang_mtproxy.

Editorial conclusion

mtproto_proxy fits an operator who needs a Telegram proxy that survives deep packet inspection and who can afford to run a server, or two in split mode, because the dd and fake-TLS protocols, the per-SNI secrets and the replay protection are implemented in the same Erlang codebase. It is the wrong choice if you expect active development, since the last push was on 2026-04-14 and the newest release is 0.8.4 from 2026-04-11, and it is the wrong choice if you intend to carry sensitive traffic, which the project itself warns against. Before you deploy, verify that the release you run matches the Telegram configuration you need, set the 32 character secret and the ad-tag from @MTProxybot, and decide on split mode with make init-config ROLE=front and ROLE=back rather than discovering the topology later.

Frequently asked questions

How do I install mtproto_proxy on a server?

The one-line installer downloads and runs an interactive script that configures the port, secret, ad-tag and protocols: curl -L -o mtp_install.sh https://git.io/fj5ru && bash mtp_install.sh. A Docker image named seriyps/mtproto-proxy is also published for smaller setups, while heavier installations are recommended directly on the operating system.

What is the difference between the dd and fake-TLS protocols in mtproto_proxy?

The secure mode uses a randomised packet size protocol with a 34 symbol secret starting with dd, while the fake-TLS protocol uses secrets that begin with ee and are base64 encoded so the connection resembles TLS. The allowed_protocols option restricts the proxy to one of them or to both.

What is split mode in mtproto_proxy?

Split mode runs the client-facing front on a domestic server and the Telegram-facing back on a foreign server, joined by Erlang distribution over TLS or a censorship-resistant tunnel, which avoids direct domestic to foreign connections being blocked. The Makefile selects the templates with make init-config ROLE=front and ROLE=back.

Is mtproto_proxy still being developed?

The last release listed is 0.8.4 on 2026-04-11 and the last push was on 2026-04-14, with the repository not archived. That is a gap of several months, so plan on running a fixed release rather than on new features.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. seriyps/mtproto_proxy on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/seriyps-mtproto-proxy.svg)](https://hysenlabs.com/projects/seriyps-mtproto-proxy)

Was this useful?