# Telemt - MTProxy on Rust + Tokio **Telemt** is a fast, secure, and feature-rich server written in Rust: it fully implements the official Telegram proxy algo and adds many production-ready improvements such as connection pooling, replay protection, detailed statistics, masking from "prying" eyes 💥 The configuration structure has changed since version 1.1.0.0, change it in your environment! ⚓ Our implementation of **TLS-fronting** is the most debugged, advanced and **"indistinguishable from the original"**: we are confident we have it right - [see our evidence](#recognizability-for-dpi-and-crawler) # GOTO - [Features](#features) - [Quick Start Guide](#quick-start-guide) - [How to use?](#how-to-use) - [Systemd Method](#telemt-via-systemd) - [Configuration](#configuration) - [Minimal Configuration](#minimal-configuration-for-first-start) - [Advanced](#advanced) - [Adtag](#adtag) - [Listening and Announce IPs](#listening-and-announce-ips) - [Upstream Manager](#upstream-manager) - [IP](#bind-on-ip) - [SOCKS](#socks45-as-upstream) - [FAQ](#faq) - [Recognizability for DPI + crawler](#recognizability-for-dpi-and-crawler) - [Telegram Calls](#telegram-calls-via-mtproxy) - [DPI](#how-does-dpi-see-mtproxy-tls) - [Whitelist on Network Level](#whitelist-on-ip) - [Build](#build) - [Why Rust?](#why-rust) ## Features - Full support for all official MTProto proxy modes: - Classic - Secure - with `dd` prefix - Fake TLS - with `ee` prefix + SNI fronting - Replay attack protection - Optional traffic masking: forward unrecognized connections to a real web server, e.g. GitHub 🤪 - Configurable keepalives + timeouts + IPv6 and "Fast Mode" - Graceful shutdown on Ctrl+C - Extensive logging via `trace` and `debug` with `RUST_LOG` method ## Quick Start Guide **This software is designed for Debian-based OS: in addition to Debian, these are Ubuntu, Mint, Kali, MX and many other Linux** 1. Download release ```bash wget https://github.com/telemt/telemt/releases/latest/download/telemt ``` 2. Move to Bin Folder ```bash mv telemt /bin ``` 4. Make Executable ```bash chmod +x /bin/telemt ``` 5. Go to [How to use?](#how-to-use) section for for further steps ## How to use? ### Telemt via Systemd **This instruction "assume" that you:** - logged in as root or executed `su -` / `sudo su` - you already have an assembled and executable `telemt` in /bin folder as a result of the [Quick Start Guide](#quick-start-guide) or [Build](#build) **0. Check port and generate secrets** The port you have selected for use should be MISSING from the list, when: ```bash netstat -lnp ``` Generate 16 bytes/32 characters HEX with OpenSSL or another way: ```bash openssl rand -hex 16 ``` OR ```bash xxd -l 16 -p /dev/urandom ``` OR ```bash python3 -c 'import os; print(os.urandom(16).hex())' ``` **1. Place your config to /etc/telemt.toml** Open nano ```bash nano /etc/telemt.toml ``` paste your config from [Configuration](#configuration) section then Ctrl+X -> Y -> Enter to save **2. Create service on /etc/systemd/system/telemt.service** Open nano ```bash nano /etc/systemd/system/telemt.service ``` paste this Systemd Module ```bash [Unit] Description=Telemt After=network.target [Service] Type=simple WorkingDirectory=/bin ExecStart=/bin/telemt /etc/telemt.toml Restart=on-failure [Install] WantedBy=multi-user.target ``` then Ctrl+X -> Y -> Enter to save **3.** In Shell type `systemctl start telemt` - it must start with zero exit-code **4.** In Shell type `systemctl status telemt` - there you can reach info about current MTProxy status **5.** In Shell type `systemctl enable telemt` - then telemt will start with system startup, after the network is up ## Configuration ### Minimal Configuration for First Start ```toml # === UI === # Users to show in the startup log (tg:// links) show_link = ["hello"] # === General Settings === [general] prefer_ipv6 = false fast_mode = true use_middle_proxy = false # ad_tag = "..." [general.modes] classic = false secure = false tls = true # === Server Binding === [server] port = 443 listen_addr_ipv4 = "0.0.0.0" listen_addr_ipv6 = "::" # metrics_port = 9090 # metrics_whitelist = ["127.0.0.1", "::1"] # Listen on multiple interfaces/IPs (overrides listen_addr_*) [[server.listeners]] ip = "0.0.0.0" # announce_ip = "1.2.3.4" # Optional: Public IP for tg:// links [[server.listeners]] ip = "::" # === Timeouts (in seconds) === [timeouts] client_handshake = 15 tg_connect = 10 client_keepalive = 60 client_ack = 300 # === Anti-Censorship & Masking === [censorship] tls_domain = "petrovich.ru" mask = true mask_port = 443 # mask_host = "petrovich.ru" # Defaults to tls_domain if not set fake_cert_len = 2048 # === Access Control & Users === # username "hello" is used for example [access] replay_check_len = 65536 ignore_time_skew = false [access.users] # format: "username" = "32_hex_chars_secret" hello = "00000000000000000000000000000000" # [access.user_max_tcp_conns] # hello = 50 # [access.user_data_quota] # hello = 1073741824 # 1 GB # === Upstreams & Routing === # By default, direct connection is used, but you can add SOCKS proxy # Direct - Default [[upstreams]] type = "direct" enabled = true weight = 10 # SOCKS5 # [[upstreams]] # type = "socks5" # address = "127.0.0.1:9050" # enabled = false # weight = 1 ``` ### Advanced #### Adtag To use channel advertising and usage statistics from Telegram, get Adtag from [@mtproxybot](https://t.me/mtproxybot), add this parameter to section `[General]` ```toml ad_tag = "00000000000000000000000000000000" # Replace zeros to your adtag from @mtproxybot ``` #### Listening and Announce IPs To specify listening address and/or address in links, add to section `[[server.listeners]]` of config.toml: ```toml [[server.listeners]] ip = "0.0.0.0" # 0.0.0.0 = all IPs; your IP = specific listening announce_ip = "1.2.3.4" # IP in links; comment with # if not used ``` #### Upstream Manager To specify upstream, add to section `[[upstreams]]` of config.toml: ##### Bind on IP ```toml [[upstreams]] type = "direct" weight = 1 enabled = true interface = "192.168.1.100" # Change to your outgoing IP ``` ##### SOCKS4/5 as Upstream - Without Auth: ```toml [[upstreams]] type = "socks5" # Specify SOCKS4 or SOCKS5 address = "1.2.3.4:1234" # SOCKS-server Address weight = 1 # Set Weight for Scenarios enabled = true ``` - With Auth: ```toml [[upstreams]] type = "socks5" # Specify SOCKS4 or SOCKS5 address = "1.2.3.4:1234" # SOCKS-server Address username = "user" # Username for Auth on SOCKS-server password = "pass" # Password for Auth on SOCKS-server weight = 1 # Set Weight for Scenarios enabled = true ``` ## FAQ ### Recognizability for DPI and crawler Since version 1.1, we have debugged masking perfectly, for all clients without "presenting" a key, we transparently direct traffic to the target host. - We consider this a breakthrough aspect, which few people managed to achieve in perfect form. - Based on this: if configured correctly, **TLS mode is completely identical to real-life handshake + communication** with a specified host: ```bash root@debian:~/telemt# curl -v -I --resolve petrovich.ru:443:212.220.88.77 https://petrovich.ru/ * Added petrovich.ru:443:212.220.88.77 to DNS cache * Hostname petrovich.ru was found in DNS cache * Trying 212.220.88.77:443... * Connected to petrovich.ru (212.220.88.77) port 443 (#0) * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: C=RU; ST=Saint Petersburg; L=Saint Petersburg; O=STD Petrovich; CN=*.petrovich.ru * start date: Jan 28 11:21:01 2025 GMT * expire date: Mar 1 11:21:00 2026 GMT * subjectAltName: host "petrovich.ru" matched cert's "petrovich.ru" * issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign RSA OV SSL CA 2018 * SSL certificate verify ok. * using HTTP/1.x > HEAD / HTTP/1.1 > Host: petrovich.ru > User-Agent: curl/7.88.1 > Accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing < HTTP/1.1 200 OK HTTP/1.1 200 OK < Server: Variti/0.9.3a Server: Variti/0.9.3a < Date: Thu, 01 Jan 2026 00:0000 GMT Date: Thu, 01 Jan 2026 00:0000 GMT < Access-Control-Allow-Origin: * Access-Control-Allow-Origin: * < Content-Type: text/html Content-Type: text/html < Cache-Control: no-store Cache-Control: no-store < Expires: Thu, 01 Jan 2026 00:0000 GMT Expires: Thu, 01 Jan 2026 00:0000 GMT < Pragma: no-cache Pragma: no-cache < Set-Cookie: ipp_uid=XXXXX/XXXXX/XXXXX==; Expires=Tue, 31 Dec 2040 23:59:59 GMT; Domain=.petrovich.ru; Path=/ Set-Cookie: ipp_uid=XXXXX/XXXXX/XXXXX==; Expires=Tue, 31 Dec 2040 23:59:59 GMT; Domain=.petrovich.ru; Path=/ < Content-Type: text/html Content-Type: text/html < Content-Length: 31253 Content-Length: 31253 < Connection: keep-alive Connection: keep-alive < Keep-Alive: timeout=60 Keep-Alive: timeout=60 < * Connection #0 to host petrovich.ru left intact ``` ### Telegram Calls via MTProxy - Telegram architecture **does NOT allow calls via MTProxy**, but only via SOCKS5, which cannot be obfuscated ### How does DPI see MTProxy TLS? - DPI sees MTProxy in Fake TLS (ee) mode as TLS 1.3 - the SNI you specify sends both the client and the server; - ALPN is similar to HTTP 1.1/2; - high entropy, which is normal for AES-encrypted traffic; ### Whitelist on IP - MTProxy cannot work when there is: - no IP connectivity to the target host: Russian Whitelist on Mobile Networks - "Белый список" - OR all TCP traffic is blocked - OR high entropy/encrypted traffic is blocked: content filters at universities and critical infrastructure - OR all TLS traffic is blocked - OR specified port is blocked: use 443 to make it "like real" - OR provided SNI is blocked: use "officially approved"/innocuous name - like most protocols on the Internet; - these situations are observed: - in China behind the Great Firewall - in Russia on mobile networks, less in wired networks - in Iran during "activity" ## Build ```bash # Cloning repo git clone https://github.com/telemt/telemt # Changing Directory to telemt cd telemt # Starting Release Build cargo build --release # Move to /bin mv ./target/release/telemt /bin # Make executable chmod +x /bin/telemt # Lets go! telemt config.toml ``` ## Why Rust? - Long-running reliability and idempotent behavior - Rust’s deterministic resource management - RAII - No garbage collector - Memory safety and reduced attack surface - Tokio's asynchronous architecture ## Issues - ✅ [SOCKS5 as Upstream](https://github.com/telemt/telemt/issues/1) -> added Upstream Management - ✅ [iOS - Media Upload Hanging-in-Loop](https://github.com/telemt/telemt/issues/2) ## Roadmap - Public IP in links - Config Reload-on-fly - Bind to device or IP for outbound/inbound connections - Adtag Support per SNI / Secret - Fail-fast on start + Fail-soft on runtime (only WARN/ERROR) - Zero-copy, minimal allocs on hotpath - DC Healthchecks + global fallback - No global mutable state - Client isolation + Fair Bandwidth - Backpressure-aware IO - "Secret Policy" - SNI / Secret Routing :D - Multi-upstream Balancer and Failover - Strict FSM per handshake - Session-based Antireplay with Sliding window, non-broking reconnects - Web Control: statistic, state of health, latency, client experience...