| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Warning
This repository is no longer actively maintained. A community fork with ongoing development is available at teleproxy/teleproxy.
Русский | فارسی | Tiếng Việt
Simple MT-Proto proxy. Telegram channel for updates.
This is a fork of MTProxy which includes various improvements and fixes that upstream has not merged due to abandonding their repository. Most of these fixes aim for stable running of MTProxy in production without surprises.
Important
Maintenance notice: This project is maintained by a single developer in their free time. Upstream TelegramMessenger/MTProxy has been abandoned. Continued development and bug fixes depend on community support.
| Channel | Details |
|---|---|
| GitHub Sponsors | Sponsor |
| Tribute | Donate via Telegram (cards, worldwide) |
| YooMoney | Donate (cards & wallets, Russia-friendly) |
| Boosty | Subscribe |
| TON | UQBOGq_b3eL63Qfkj6ykoBibK3zGJDQzLK91v2q-UCY7BPeb (via @wallet in Telegram) |
| USDT (TRC-20) | TNVSj1QjZ5jqdaeshe7VCpXWo2S1n936Hj |
| BTC | bc1qvxxldmanwggula7992uun5a2qxm65ej9h0unj7 |
| Commercial | GetPageSpeed RPM packages (includes support) |
This is the actively maintained fork of TelegramMessenger/MTProxy (upstream abandoned). The table below compares it with the original and the two main third-party alternatives.
| Feature | Original | This fork | mtg | telemt |
|---|---|---|---|---|
| Language | C | C | Go | Rust |
| Protocol | ||||
| Fake-TLS (EE mode) | Yes | Yes | Yes | Yes |
| Direct-to-DC mode | No | Yes | Yes | Yes |
| Ad proxy tag | Yes | Yes | No | Yes |
| Multiple secrets | Yes | Yes (up to 16, with labels) | No | Yes |
| Anti-replay protection | Weak | Yes | Yes | Partial |
| Constant-time HMAC | No | Yes | — | Yes |
| DPI resistance | ||||
| Custom TLS backend (TCP splitting) | Yes | Yes | No | Yes |
| Dynamic Record Sizing (DRS) | No | Yes | Yes | No |
| Traffic mimicry (DRS + timing) | No | Yes | Yes | No |
| SOCKS5 upstream proxy | No | No | Yes | Yes |
| Access control | ||||
| IP blocklist / allowlist | No | Yes | Yes | No |
| Per-user unique IP limits | No | No | No | Yes |
| Proxy Protocol v1/v2 | No | No | Yes | Yes |
| Deployment | ||||
| Docker image | ~57 MB | ~8 MB | ~3.5 MB | ~5 MB |
| ARM64 / Apple Silicon | No | Yes | Yes | Yes |
| IPv6 | Yes | Yes | Yes | Yes |
| Multi-worker processes | Yes | Yes | — | — |
| Static binary releases | No | Yes | Yes | Yes |
| RPM packages | No | Yes | No | No |
| Systemd integration | Partial | Yes | — | Yes |
| Monitoring & management | ||||
| Prometheus metrics | No | Yes | Yes | Yes |
| HTTP stats endpoint | Yes | Yes | — | Yes |
| REST management API | No | No | No | Yes |
| Auto config refresh | No | Yes | Yes | Yes |
| Health checks | No | Yes | Yes | Yes |
| Testing & quality | ||||
| Fuzz testing (CI) | No | Yes | No | Partial |
| E2E tests (real Telegram clients) | No | Yes | No | No |
| Static analysis (CI) | No | Yes | Yes | — |
Why this fork? Battle-tested C codebase from the official Telegram repository, with TDLib-validated fake-TLS (verified against the TDLib source), RPM packaging for enterprise deployment, and the most comprehensive CI pipeline (libFuzzer + Telethon E2E + cppcheck + CodeQL).
For the easiest installation with prebuilt RPM packages, automatic updates, and complete configuration:
👉 GetPageSpeed MTProxy Installation Guide
This includes:
Pre-built static binaries (musl libc, zero dependencies) are available for every release:
# Download (choose amd64 or arm64)
curl -Lo mtproto-proxy https://github.com/GetPageSpeed/MTProxy/releases/latest/download/mtproto-proxy-linux-amd64
chmod +x mtproto-proxy
# Generate a secret
SECRET=$(head -c 16 /dev/urandom | xxd -ps)
# Run in direct mode (simplest — no config files needed)
./mtproto-proxy -S "$SECRET" -H 443 --direct -p 8888 --aes-pwd /dev/nullBinaries are available for linux/amd64 and linux/arm64. SHA256 checksums are published alongside each release.
Install dependencies, you would need common set of tools for building from source, and development packages for openssl and zlib.
On Debian/Ubuntu:
apt install git curl build-essential libssl-dev zlib1g-devOn CentOS/RHEL (not advisable, use packages mentioned above instead):
yum install openssl-devel zlib-devel
yum groupinstall "Development Tools"Clone the repo:
git clone https://github.com/GetPageSpeed/MTProxy
cd MTProxyTo build, simply run make, the binary will be in objs/bin/mtproto-proxy:
make && cd objs/binIf the build has failed, you should run make clean before building it again.
This repository includes a comprehensive test suite. For detailed instructions, see TESTING.md.
To run the tests using Docker:
# Export environment variables (see TESTING.md)
export MTPROXY_SECRET=...
make testcurl --connect-timeout 10 --max-time 30 --retry 3 -fsSL https://core.telegram.org/getProxySecret -o proxy-secretcurl --connect-timeout 10 --max-time 30 --retry 3 -fsSL https://core.telegram.org/getProxyConfig -o proxy-multi.confhead -c 16 /dev/urandom | xxd -ps./mtproto-proxy -u nobody -p 8888 -H 443 -S <secret> --http-stats --aes-pwd proxy-secret proxy-multi.conf -M 1... where:
Also feel free to check out other options using mtproto-proxy --help.
Restrict client connections by IP address using CIDR-based blocklist/allowlist files:
./mtproto-proxy ... --ip-blocklist blocklist.txt --ip-allowlist allowlist.txtFile format (one CIDR range per line, # comments allowed):
# Block known scanner ranges 185.220.101.0/24 2001:db8::/32
By default, MTProxy routes traffic through Telegram's middle-end (ME) relay servers listed in proxy-multi.conf. Direct mode bypasses the ME relays and connects straight to Telegram data centers, reducing latency and simplifying deployment:
Default: Client → MTProxy → ME relay (proxy-multi.conf) → Telegram DC Direct: Client → MTProxy → Telegram DC
To enable direct mode, use --direct:
./mtproto-proxy -u nobody -p 8888 -H 443 -S <secret> --http-stats --directIn direct mode:
MTProxy supports IPv6. To enable it, pass the -6 flag and specify only port numbers to -H (do not include an address like [::]:443).
./mtproto-proxy -6 -u nobody -p 8888 -H 443 -S <secret> --http-stats --aes-pwd proxy-secret proxy-multi.conf -M 1Examples:
ss -ltnp | grep :443
# Expect to see :::443 among listenerscurl -6 http://[::1]:8888/statssysctl net.ipv6.conf.all.disable_ipv6
# should be 0[Unit]
Description=MTProxy (IPv6)
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/MTProxy
ExecStart=/opt/MTProxy/mtproto-proxy -6 -u nobody -p 8888 -H 443 -S <secret> --http-stats -P <proxy tag> --aes-pwd proxy-secret proxy-multi.conf -M 1
Restart=on-failure
[Install]
WantedBy=multi-user.targetMTProxy supports different transport modes that provide various levels of obfuscation:
💡 For complete setup instructions including RPM packages, see the GetPageSpeed MTProxy installation guide
Due to some ISPs detecting MTProxy by packet sizes, random padding is added to packets when this mode is enabled.
Client Setup: Add dd prefix to secret (cafe...babe => ddcafe...babe)
Server Setup: Use -R argument to allow only clients with random padding enabled
📖 See also: GetPageSpeed guide - DD mode setup
EE mode provides enhanced obfuscation by mimicking TLS 1.3 connections, making MTProxy traffic harder to detect and block.
Server Setup:
Add domain configuration: Choose a website that supports TLS 1.3 (e.g., www.google.com, www.cloudflare.com)
./mtproto-proxy -u nobody -p 8888 -H 443 -S <secret> -D www.google.com --http-stats --aes-pwd proxy-secret proxy-multi.conf -M 1Get domain HEX dump:
echo -n www.google.com | xxd -plain
# Output: 7777772e676f6f676c652e636f6dClient Setup: Use the format: ee + server_secret + domain_hex
Example:
Quick Generation:
# Generate complete client secret automatically
SECRET="cafe1234567890abcdef1234567890ab"
DOMAIN="www.google.com"
echo -n "ee${SECRET}" && echo -n $DOMAIN | xxd -plainBenefits:
📖 Complete Fake TLS setup guide: GetPageSpeed MTProxy - Fake TLS section
Instead of mimicking a public website, you can run your own web server (e.g., nginx) behind MTProxy with a real TLS certificate for your domain. Non-MTProxy visitors see a fully functioning HTTPS website, making the server indistinguishable from a normal web server.
How it works:
Active probing resistance: Every connection that fails MTProxy validation — wrong secret, expired timestamp, unknown SNI, replayed handshake, malformed ClientHello, or plain non-TLS traffic — is transparently forwarded to the backend rather than rejected with a TLS error. Anyone probing the server with a standard browser sees a real HTTPS website, making the proxy indistinguishable from a normal web server under active probing.
Dynamic Record Sizing (DRS): TLS connections automatically use graduated record sizes that mimic real HTTPS servers (Cloudflare, Go, Caddy): small MTU-sized records during TCP slow-start (~1450 bytes), ramping to ~4096 bytes, then max TLS payload (~16144 bytes). This defeats statistical traffic analysis that fingerprints proxy traffic by its uniform record sizes. No configuration needed — DRS activates automatically for all TLS connections.
Requirements:
Setup:
Configure nginx to listen on a local port with TLS 1.3:
server {
listen 127.0.0.1:8443 ssl default_server;
server_name mywebsite.com;
ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
root /var/www/html;
location / {
try_files $uri $uri/ =404;
}
}Certificate renewal: Use certbot with DNS-01 challenge (--preferred-challenges dns). HTTP-01 challenge will not work because MTProxy occupies port 443.
Add an /etc/hosts entry so MTProxy resolves the domain to loopback (needed when nginx only listens on 127.0.0.1):
127.0.0.1 mywebsite.com
Note: If nginx listens on all interfaces (0.0.0.0:8443) and the domain's DNS already points to this server, you can skip the /etc/hosts entry.
Run MTProxy with the domain and port:
./mtproto-proxy -u nobody -p 8888 -H 443 -S <secret> -D mywebsite.com:8443 --http-stats --aes-pwd proxy-secret proxy-multi.conf -M 1Generate the client ee secret as usual (using mywebsite.com as the domain):
SECRET="<your_32_hex_secret>"
echo -n "ee${SECRET}" && echo -n mywebsite.com | xxd -plainnano /etc/systemd/system/MTProxy.service[Unit]
Description=MTProxy
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/MTProxy
ExecStart=/opt/MTProxy/mtproto-proxy -u nobody -p 8888 -H 443 -S <secret> -P <proxy tag> <other params>
ExecStart=/opt/MTProxy/mtproto-proxy -u nobody -p 8888 -H 443 -S <secret> --http-stats -P <proxy tag> <other params>
Restart=on-failure
[Install]
WantedBy=multi-user.targetsystemctl daemon-reloadsystemctl restart MTProxy.service
# Check status, it should be active
systemctl status MTProxy.servicesystemctl enable MTProxy.serviceThe simplest way to run MTProxy - no configuration needed:
docker run -d \
--name mtproxy \
-p 443:443 \
-p 8888:8888 \
--restart unless-stopped \
ghcr.io/getpagespeed/mtproxy:latestThe container automatically:
Connection Links at Startup:
The container prints ready-to-share connection links in the logs:
docker logs mtproxy
# ===== Connection Links =====
# https://t.me/proxy?server=203.0.113.1&port=443&secret=eecafe...
# =============================If external IP detection fails, links show <YOUR_SERVER_IP> — set EXTERNAL_IP to fix.
For more control, specify environment variables:
docker run -d \
--name mtproxy \
-p 443:443 \
-p 8888:8888 \
-e SECRET=$(head -c 16 /dev/urandom | xxd -ps) \
-e PROXY_TAG=your_proxy_tag_here \
-v mtproxy-data:/opt/mtproxy/data \
--restart unless-stopped \
ghcr.io/getpagespeed/mtproxy:latestcurl http://localhost:8888/statscurl http://localhost:8888/metricsReturns metrics in Prometheus exposition format, ready for scraping. Available on the same --http-stats port, restricted to private networks. Includes per-secret connection metrics when secret labels are configured.
The simplest Docker Compose setup (create docker-compose.yml):
services:
mtproxy:
image: ghcr.io/getpagespeed/mtproxy:latest
ports:
- "443:443"
- "8888:8888"
restart: unless-stoppedThen run:
docker-compose up -d
docker-compose logs mtproxy | grep "Generated secret"For custom configuration, create a .env file:
SECRET=your_secret_here
PROXY_TAG=your_proxy_tag_here
RANDOM_PADDING=falseFor multiple secrets (per-group access control):
# Option A: comma-separated
SECRET=family_secret_hex,friends_secret_hex,public_secret_hex
# Option B: numbered variables
SECRET_1=family_secret_hex
SECRET_2=friends_secret_hex
SECRET_3=public_secret_hexLabels let you identify which secret a connection is using — useful for revoking leaked secrets or monitoring per-group traffic:
# Inline labels (CLI)
./mtproto-proxy ... -S cafe1234567890abcdef1234567890ab:family -S dead1234567890abcdef1234567890ef:friends
# Inline labels (Docker)
SECRET=cafe1234567890abcdef1234567890ab:family,dead1234567890abcdef1234567890ef:friends
# Separate label env vars (Docker)
SECRET_1=cafe1234567890abcdef1234567890ab
SECRET_LABEL_1=family
SECRET_2=dead1234567890abcdef1234567890ef
SECRET_LABEL_2=friendsLabels appear in:
If no label is given, secrets are auto-labeled secret_0, secret_1, etc.
Label rules: max 32 characters, alphanumeric plus _ and - only.
Prevent a leaked or widely-shared secret from consuming all proxy resources by setting a maximum number of concurrent connections per secret:
# CLI: append :LIMIT after the label
./mtproto-proxy ... -S cafe...90ab:family:1000 -S dead...90ef:public:200
# Without a label, use an empty label field
./mtproto-proxy ... -S cafe...90ab::500
# Docker: numbered env vars
SECRET_1=cafe1234567890abcdef1234567890ab
SECRET_LABEL_1=family
SECRET_LIMIT_1=1000
SECRET_2=dead1234567890abcdef1234567890ef
SECRET_LABEL_2=public
SECRET_LIMIT_2=200
# Docker: inline (comma-separated)
SECRET=cafe...90ab:family:1000,dead...90ef:public:200When the limit is reached, new connections using that secret are rejected:
Existing connections are not affected. Other secrets continue operating normally.
Multi-worker note: with -M N workers, each worker enforces limit / N independently. For single-worker mode (-M 0 or -M 1), the limit is exact.
Limits appear in stats and Prometheus metrics:
Secrets without a limit are unlimited (the default, backward-compatible behavior).
And reference it in your docker-compose.yml:
services:
mtproxy:
image: ghcr.io/getpagespeed/mtproxy:latest
ports:
- "443:443"
- "8888:8888"
environment:
- SECRET=${SECRET}
- PROXY_TAG=${PROXY_TAG}
- RANDOM_PADDING=${RANDOM_PADDING}
restart: unless-stoppedIf you want to build the image yourself:
docker build -t mtproxy .
docker run -d \
--name mtproxy \
-p 443:443 \
-p 8888:8888 \
mtproxyCheck the logs to find your auto-generated secret:
docker logs mtproxy 2>&1 | grep "Generated secret"The Docker container includes a health check that monitors the statistics endpoint. You can check the container health with:
docker ps
# Look for the health status in the STATUS columnThe container includes a daily cron job that automatically refreshes the Telegram DC configuration (proxy-multi.conf). This prevents the proxy from becoming unavailable due to stale server addresses — Telegram periodically rotates DC IPs, and without refresh the proxy may silently lose connectivity.
The refresh process:
No user configuration is needed — this runs automatically.
The container stores proxy-multi.conf (Telegram DC addresses) in /opt/mtproxy/data/. Mount a volume to persist this configuration across container restarts. The proxy-secret file is baked into the image at build time and does not require persistence.
If core.telegram.org is unreachable (e.g., due to network restrictions), the container will use a cached proxy-multi.conf from the data volume when available. On first run without network access, you must manually place proxy-multi.conf in the data volume.
Mount a volume:
-v /path/to/host/data:/opt/mtproxy/data| Back | FazBrowse Home | New Git URL |