{"id":13511602,"url":"https://github.com/seriyps/mtproto_proxy","last_synced_at":"2026-04-04T00:08:57.787Z","repository":{"id":34397298,"uuid":"135416916","full_name":"seriyps/mtproto_proxy","owner":"seriyps","description":"High performance Erlang MTProto proxy that powers https://t.me/socksy_bot","archived":false,"fork":false,"pushed_at":"2026-04-03T18:13:20.000Z","size":6235,"stargazers_count":746,"open_issues_count":53,"forks_count":123,"subscribers_count":18,"default_branch":"master","last_synced_at":"2026-04-03T20:54:27.098Z","etag":null,"topics":["censorship-circumvention","erlang","mtproto-proxy","telegram"],"latest_commit_sha":null,"homepage":"https://t.me/erlang_mtproxy","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seriyps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"seriyps"}},"created_at":"2018-05-30T09:03:30.000Z","updated_at":"2026-04-03T19:55:03.000Z","dependencies_parsed_at":"2025-05-16T11:05:43.057Z","dependency_job_id":"6f8f1b12-fd60-4c8a-b946-b91b130c5811","html_url":"https://github.com/seriyps/mtproto_proxy","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/seriyps/mtproto_proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seriyps%2Fmtproto_proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seriyps%2Fmtproto_proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seriyps%2Fmtproto_proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seriyps%2Fmtproto_proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seriyps","download_url":"https://codeload.github.com/seriyps/mtproto_proxy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seriyps%2Fmtproto_proxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31382355,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T23:20:52.058Z","status":"ssl_error","status_checked_at":"2026-04-03T23:20:51.675Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["censorship-circumvention","erlang","mtproto-proxy","telegram"],"created_at":"2024-08-01T03:00:59.502Z","updated_at":"2026-04-04T00:08:57.775Z","avatar_url":"https://github.com/seriyps.png","language":"Erlang","funding_links":["https://github.com/sponsors/seriyps"],"categories":["Erlang"],"sub_categories":[],"readme":"Erlang mtproto proxy\n====================\n\nThis part of code was extracted from [@socksy_bot](https://t.me/socksy_bot).\n\nSupport: https://t.me/erlang_mtproxy .\n\n‼️ DON'T USE TELEGRAM FOR SENSITIVE DATA AND POLITICAL ACTIVITY\n---------------------------------------------------------------\n\nTelegram is known to cooperate with governments, especially with russian.\nTelegram is NOT neutral and NOT fully independent. Please only use Telegram\nfor non-sensitive messaging. For private messaging prefer Signal or Session.\n\nFeatures\n--------\n\n* Promoted channels. See `tag` option.\n* \"secure\" randomized-packet-size protocol (34-symbol secrets starting with 'dd')\n  to prevent detection by DPI\n* Fake-TLS protocol ('ee'/base64 secrets) - another protocol to prevent DPI detection\n* Secure-only mode (only allow connections with 'dd' or fake-TLS).\n  See `allowed_protocols` option.\n* Connection limit policies - limit number of connections by IP / tls-domain / port; IP / tls-domain\n  blacklists / whitelists\n* Multiple ports with unique secret and promo tag for each port\n* Very high performance - can handle tens of thousands connections! Scales to all CPU cores.\n  1Gbps, 90k connections on 4-core/8Gb RAM cloud server.\n* Supports multiplexing (Many connections Client -\u003e Proxy are wrapped to small amount of\n  connections Proxy -\u003e Telegram Server) - lower pings and better OS network utilization\n* Protection from [replay attacks](https://habr.com/ru/post/452144/) used to detect proxies in some countries\n* Domain fronting for fake-TLS connections — when a browser or DPI probe connects with a\n  wrong/absent secret, the connection is forwarded transparently to the real HTTPS server\n  in the SNI field; the proxy is indistinguishable from a normal web server\n* Automatic telegram configuration reload (no need for restarts once per day)\n* IPv6 for client connections\n* All configuration options can be updated without service restart\n* Small codebase compared to official one, code is covered by automated tests\n* A lots of metrics could be exported (optional)\n\nHow to install - one-line interactive installer\n-----------------------------------------------\n\nThis command will run [interactive script](https://gist.github.com/seriyps/dc00ad91bfd8a2058f30845cd0daed83)\nthat will install and configure proxy for your Ubuntu / Debian / CentOS server.\nIt will ask if you want to change default port/secret/ad-tag/protocols:\n\n```bash\ncurl -L -o mtp_install.sh https://git.io/fj5ru \u0026\u0026 bash mtp_install.sh\n```\n\nYou can also just provide port/secret/ad-tag/protocols/tls-domain as command line arguments:\n\n```bash\ncurl -L -o mtp_install.sh https://git.io/fj5ru \u0026\u0026 bash mtp_install.sh -p 443 -s d0d6e111bada5511fcce9584deadbeef -t dcbe8f1493fa4cd9ab300891c0b5b326 -a dd -a tls -d s3.amazonaws.com\n```\n\nIt does the same as described in [How to start OS-install - detailed](#how-to-start-os-install---detailed), but\ngenerates config-file for you automatically.\n\nHow to start - Docker\n---------------------\n\n### To run with default settings\n\n```bash\ndocker run -d --network=host seriyps/mtproto-proxy\n```\n\n### To run on single port with custom port, secret and ad-tag\n\n```bash\ndocker run -d --network=host seriyps/mtproto-proxy -p 443 -s d0d6e111bada5511fcce9584deadbeef -t dcbe8f1493fa4cd9ab300891c0b5b326\n```\n\nor via environment variables\n\n```bash\ndocker run -d --network=host -e MTP_PORT=443 -e MTP_SECRET=d0d6e111bada5511fcce9584deadbeef -e MTP_TAG=dcbe8f1493fa4cd9ab300891c0b5b326 seriyps/mtproto-proxy\n```\n\nWhere\n\n* `-p 443` / `MTP_PORT=…` proxy port\n* `-s d0d6e111bada5511fcce9584deadbeef` / `MTP_SECRET=…` proxy secret (don't append `dd`! it should be 32 chars long!)\n* `-t dcbe8f1493fa4cd9ab300891c0b5b326` / `MTP_TAG=…` ad-tag that you get from [@MTProxybot](https://t.me/MTProxybot)\n* `-a dd` / `MTP_DD_ONLY=t` only allow \"secure\" connections (dd-secrets)\n* `-a tls` / `MTP_TLS_ONLY=t` only allow \"fake-TLS\" connections (base64 secrets)\n\nIt's ok to provide both `-a dd -a tls` to allow both protocols. If no `-a` option provided, all protocols will be allowed.\n\n### To run with custom config-file\n\n1. Get the code `git clone https://github.com/seriyps/mtproto_proxy.git \u0026\u0026 cd mtproto_proxy/`\n2. Copy config templates `cp config/{vm.args.example,prod-vm.args}; cp config/{sys.config.example,prod-sys.config}`\n3. Edit configs. See [Settings](#settings).\n4. Build `docker build -t mtproto-proxy-erl .`\n5. Start `docker run -d --network=host mtproto-proxy-erl`\n\nInstallation via docker can work well for small setups (10-20k connections), but\nfor more heavily-loaded setups it's recommended to install proxy directly into\nyour server's OS (see below).\n\nHow to start OS-install - quick\n-----------------------------------\n\nYou need at least Erlang version 25! Recommended OS is Ubuntu 24.04.\n\n```bash\nsudo apt install erlang-nox erlang-dev build-essential\ngit clone https://github.com/seriyps/mtproto_proxy.git\ncd mtproto_proxy/\ncp config/vm.args.example config/prod-vm.args\ncp config/sys.config.example config/prod-sys.config\n# configure your port, secret, ad_tag. See [Settings](#settings) below.\nnano config/prod-sys.config\nmake \u0026\u0026 sudo make install\nsudo systemctl enable mtproto-proxy\nsudo systemctl start mtproto-proxy\n```\n\nHow to start OS-install - detailed\n--------------------------------------\n\n\n### Install deps\n\nUbuntu 18.xx / Ubuntu 19.xx / Debian 10:\n\n```bash\nsudo apt install erlang-nox erlang-dev  make sed diffutils tar\n```\n\nCentOS 7\n\n```bash\n# Enable \"epel\" and \"Erlang solutions\" repositories\nsudo yum install wget \\\n             https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \\\n             https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm\n# Install Erlang\nsudo yum install erlang-compiler erlang-erts erlang-kernel erlang-stdlib erlang-syntax_tools \\\n     erlang-crypto erlang-inets erlang-sasl erlang-ssl\n```\n\nYou need Erlang version 20 or higher! If your version is older, please, check\n[Erlang solutions esl-erlang package](https://www.erlang-solutions.com/resources/download.html)\nor use [kerl](https://github.com/kerl/kerl).\n\n### Get the code:\n\n```bash\ngit clone https://github.com/seriyps/mtproto_proxy.git\ncd mtproto_proxy/\n```\n\n### Create config file\n\nsee [Settings](#settings).\n\n### Build and install\n\n```bash\nmake \u0026\u0026 sudo make install\n```\n\nThis will:\n* install proxy into `/opt/mtp_proxy`\n* create a system user\n* install systemd service\n* create a directory for logs in `/var/log/mtproto-proxy`\n* Configure ulimit of max open files and `CAP_NET_BIND_SERVICE` by systemd\n\n### Try to start in foreground mode\n\nThis step is optional, but it can be useful to test if everything works as expected\n\n```bash\n./start.sh\n```\n\ntry to run `./start.sh -h` to learn some useful options.\n\n### Start in background and enable start on system start-up\n\n```bash\nsudo systemctl enable mtproto-proxy\nsudo systemctl start mtproto-proxy\n```\n\nDone! Proxy is up and ready to serve now!\n\n### Stop / uninstall\n\nStop:\n\n```bash\nsudo systemctl stop mtproto-proxy\n```\n\nUninstall:\n\n```bash\nsudo systemctl stop mtproto-proxy\nsudo systemctl disable mtproto-proxy\nsudo make uninstall\n```\n\nLogs can be found at\n\n```\n/var/log/mtproto-proxy/application.log\n```\n\nSettings\n--------\n\nAll available documented configuration options could be found\nin [src/mtproto_proxy.app.src](src/mtproto_proxy.app.src). Do not edit this file!\n\nTo change configuration, edit `config/prod-sys.config`:\n\nComments in this file start with `%%`.\nDefault port is 1443 and default secret is `d0d6e111bada5511fcce9584deadbeef`.\n\nSecret key and proxy URLs will be printed on start.\n\n\n### Apply config changes without restart\n\nIt's possible to reload config file without service restart (but if you want to update\nad_tag on existing port, all clients of this port will be disconnected).\n\nThis method doesn't work for Docker!\n\nTo do that, make changes in `config/prod-sys.config` and run following command:\n\n```bash\nsudo make update-sysconfig \u0026\u0026 sudo systemctl reload mtproto-proxy\n```\n\n### Change default port / secret / ad tag\n\nTo change default settings, change `mtproto_proxy` section of `prod-sys.config` as:\n\n```erlang\n {mtproto_proxy,\n  %% see src/mtproto_proxy.app.src for examples.\n  [\n   {ports,\n    [#{name =\u003e mtp_handler_1,\n       listen_ip =\u003e \"0.0.0.0\",\n       port =\u003e 1443,\n       secret =\u003e \u003c\u003c\"d0d6e111bada5511fcce9584deadbeef\"\u003e\u003e,\n       tag =\u003e \u003c\u003c\"dcbe8f1493fa4cd9ab300891c0b5b326\"\u003e\u003e}\n    ]}\n   ]},\n\n {kernel,\n  [{logger_level, info},\n   {logger,\n    [{handler, default, logger_std_h,\n      #{config =\u003e #{file =\u003e \"/var/log/mtproto-proxy/application.log\"}}}\n    ]}]},\n\u003c...\u003e\n```\n(so, remove `%%`s) and replace `port` / `secret` / `tag` with yours.\n\n### Listen on multiple ports / IPs\n\nYou can start proxy on many IP addresses or ports with different secrets/ad tags.\nTo do so, just add more configs to `ports` section, separated by comma, eg:\n\n```erlang\n {mtproto_proxy,\n  %% see src/mtproto_proxy.app.src for examples.\n  [\n   {ports,\n    [#{name =\u003e mtp_handler_1,\n       listen_ip =\u003e \"0.0.0.0\",\n       port =\u003e 1443,\n       secret =\u003e \u003c\u003c\"d0d6e111bada5511fcce9584deadbeef\"\u003e\u003e,\n       tag =\u003e \u003c\u003c\"dcbe8f1493fa4cd9ab300891c0b5b326\"\u003e\u003e},\n     #{name =\u003e mtp_handler_2,\n       listen_ip =\u003e \"0.0.0.0\",\n       port =\u003e 2443,\n       secret =\u003e \u003c\u003c\"100000000000000000000000000000001\"\u003e\u003e,\n       tag =\u003e \u003c\u003c\"cf8e6baff125ed5f661a761e69567711\"\u003e\u003e}\n    ]}\n   ]},\n\n {kernel,\n\u003c...\u003e\n```\n\nEach section should have unique `name`!\n\n### Only allow connections with 'dd'-secrets\n\nThis protocol uses randomized packet sizes, so it's more difficult to detect on DPI by\npacket sizes.\nIt might be useful in Iran, where proxies are detected by DPI.\nYou should disable all protocols other than `mtp_secure` by providing `allowed_protocols` option:\n\n```erlang\n  {mtproto_proxy,\n   [\n    {allowed_protocols, [mtp_secure]},\n    {ports,\n     [#{name =\u003e mtp_handler_1,\n      \u003c..\u003e\n```\n\n### Only allow fake-TLS connections with ee/base64-secrets\n\nAnother censorship circumvention technique. MTPRoto proxy protocol pretends to be\nHTTPS web traffic (technically speaking, TLSv1.3 + HTTP/2).\nIt's possible to only allow connections with this protocol by changing `allowed_protocols` to\nbe list with only `mtp_fake_tls`.\n\n```erlang\n  {mtproto_proxy,\n   [\n    {allowed_protocols, [mtp_fake_tls]},\n    {ports,\n     [#{name =\u003e mtp_handler_1,\n      \u003c..\u003e\n```\n\nFor even stronger DPI resistance you can enable domain fronting — see\n[Domain fronting for fake-TLS](#domain-fronting-for-fake-tls).\n\n### Domain fronting for fake-TLS\n\nWhen `mtp_fake_tls` is the active protocol and an incoming TLS connection fails the MTProto\nhandshake (wrong or absent secret — e.g. a real browser or a DPI probe), the proxy can\n**forward the raw TCP connection transparently** to the real HTTPS host instead of closing it.\nReplay-attack connections are also fronted: the replayed ClientHello is forwarded and the\nprobe receives a genuine TLS certificate from the fronting host. In both cases the proxy\nis indistinguishable from a normal HTTPS server to any external observer.\n\nTwo configuration keys control this feature:\n\n```erlang\n%% Values: off | sni | \"host:port\"\n{domain_fronting, off},\n\n%% TCP connect timeout to the fronting host (seconds).\n{domain_fronting_timeout_sec, 10},\n```\n\nThe SNI domain extracted from the client's TLS ClientHello is always required (if absent,\nthe connection is closed). It is used for policy checks in all modes and as the forwarding\ntarget in `sni` mode.\n\n#### a. Forward to the SNI host (simplest)\n\n```erlang\n{mtproto_proxy,\n [\n  {domain_fronting, sni},\n  {ports,\n   [#{name =\u003e mtp_handler_1,\n      ...\n```\n\nThe proxy connects to whatever domain the client presented in the SNI field, on port 443.\nNo additional configuration is needed.\n\n**Pros:** zero config; works with any domain automatically.\n**Cons:** can be used to relay arbitrary HTTPS traffic through your server.\n\n\u003e **⚠️ Loop risk:** if a client presents an SNI domain that resolves to the proxy's own IP,\n\u003e the proxy will connect back to itself and loop indefinitely, exhausting file descriptors.\n\u003e Use `sni` mode together with policy rules (see below) or switch to the `\"host:port\"` mode,\n\u003e which is not affected by this issue.\n\nYou can optionally restrict which SNI domains get fronted using the same `in_table` /\n`not_in_table` policy rules as normal connections. Two common approaches:\n\n**Domain whitelist** — only front explicitly allowed domains (safest):\n\n```erlang\n{mtproto_proxy,\n [\n  {domain_fronting, sni},\n  {policy,\n   [{in_table, tls_domain, front_allowlist}]},\n  {ports,\n   [#{name =\u003e mtp_handler_1,\n      ...\n```\n\nAdd domains to the whitelist at runtime:\n\n```bash\n/opt/mtp_proxy/bin/mtp_proxy eval '\nmtp_policy_table:add(front_allowlist, tls_domain, \"my-website.com\").'\n```\n\n**IP blacklist** — block the proxy's own public IP to prevent loops:\n\n```erlang\n{mtproto_proxy,\n [\n  {domain_fronting, sni},\n  {policy,\n   [{not_in_table, client_ipv4, ip_blacklist}]},\n  {ports,\n   [#{name =\u003e mtp_handler_1,\n      ...\n```\n\n```bash\n# The proxy auto-detects its external IP; add it to the blacklist once on startup:\n/opt/mtp_proxy/bin/mtp_proxy eval '\n{ok, Ip} = application:get_env(mtproto_proxy, external_ip),\nmtp_policy_table:add(ip_blacklist, client_ipv4, Ip).'\n```\n\n#### b. Forward to a fixed third-party host\n\n```erlang\n{mtproto_proxy,\n [\n  {domain_fronting, \"my-website.com:443\"},\n  {ports,\n   [#{name =\u003e mtp_handler_1,\n      ...\n```\n\nAll unrecognised TLS connections are forwarded to a single fixed target regardless of the\nSNI field. SNI is still extracted and checked against policy rules, but the TCP connection\ngoes to the configured host.\n\n**Pros:** predictable destination; easy to lock down with a whitelist so only your own\ndomains trigger fronting.\n**Cons:** requires knowing the target host in advance.\n\nExample with an SNI whitelist (only listed domains trigger fronting; all others are closed):\n\n```erlang\n{mtproto_proxy,\n [\n  {domain_fronting, \"my-website.com:443\"},\n  {policy,\n   [{in_table, tls_domain, front_allowlist}]},\n  {ports,\n   [#{name =\u003e mtp_handler_1,\n      ...\n```\n\nAdd allowed domains at runtime:\n\n```bash\n/opt/mtp_proxy/bin/mtp_proxy eval '\nmtp_policy_table:add(front_allowlist, tls_domain, \"my-website.com\").'\n```\n\n#### c. Forward to a local web server (Nginx on localhost:1443)\n\nThe most production-ready setup: run a real web server on the same machine so the proxy\nport serves genuine HTTPS content for any browser that connects.\n\n**Step 1 — configure Nginx** to listen on `127.0.0.1:1443`:\n\n```nginx\nserver {\n    listen 127.0.0.1:1443 ssl;\n    server_name my-website.com;\n\n    ssl_certificate     /etc/letsencrypt/live/my-website.com/fullchain.pem;\n    ssl_certificate_key /etc/letsencrypt/live/my-website.com/privkey.pem;\n\n    location / {\n        root /var/www/html;\n        index index.html;\n    }\n}\n```\n\n**Step 2 — obtain a TLS certificate.**\n\nWith [certbot](https://certbot.eff.org/) (Let's Encrypt, recommended — requires a real\ndomain pointing to your server and port 80 open to the internet):\n\n```bash\nsudo apt install certbot\nsudo certbot certonly --standalone -d my-website.com\n```\n\nOr generate a self-signed certificate (works for any hostname, but browsers will show a\nwarning — still enough to fool DPI):\n\n```bash\nopenssl req -x509 -newkey rsa:4096 -keyout /etc/ssl/private/proxy-selfsigned.key \\\n    -out /etc/ssl/certs/proxy-selfsigned.crt -days 3650 -nodes \\\n    -subj \"/CN=my-website.com\"\n```\n\nThen reference those paths in the `ssl_certificate` / `ssl_certificate_key` lines above.\n\n**Step 3 — configure the proxy:**\n\n```erlang\n{mtproto_proxy,\n [\n  {domain_fronting, \"127.0.0.1:1443\"},\n  {ports,\n   [#{name =\u003e mtp_handler_1,\n      ...\n```\n\n**Pros:** proxy port truly serves HTTPS; real certificates; ideal for servers that already\nrun a website.\n**Cons:** requires a running web server and a TLS certificate.\n\n### Connection limit policies\n\nProxy supports flexible connection limit rules. It's possible to limit number of connections from\nsingle IP or to single fake-TLS domain or to single port name; or any combination of them.\nIt also supports whitelists and blacklists: you can allow or forbid to connect from some IP or IP subnet\nor with some TLS domains.\n\nPolicy is set as value of `policy` config key and the value is the list of policy structures.\nIf list is empty, no limits will be checked.\n\nFollowing policies are supported:\n\n* `{in_table, KEY, TABLE_NAME}` - only allow connections if KEY is present in TABLE_NAME (whitelist)\n* `{not_in_table, KEY, TABLE_NAME}` - only allow connections if KEY is *not* present in TABLE_NAME (blacklist)\n* `{max_connections, KEYS, NUMBER}` - EXPERIMENTAL! if there are more than NUMBER connections with\n  KEYS to the proxy, new connections with those KEYS will be rejected. Note: number of connections is not the\n  same as number of unique \"users\". When someone connects to proxy with telegram client, Telegram\n  opens from 3 to 8 connections! So, you need to set this at least 8 * number of unique users.\n\nWhere:\n\n- `KEY` is one of:\n  - `port_name` - proxy port name\n  - `client_ipv4` - client's IPv4 address; ignored on IPv6 ports!\n  - `client_ipv6` - client's IPv6 address; ignored on IPv4 ports!\n  - `{client_ipv4_subnet, MASK}` - client's IPv4 subnet; mask is from 8 to 32\n  - `{client_ipv6_subnet, MASK}` - client's IPv6 subnet; mask is from 32 to 128\n  - `tls_domain` - lowercase domain name from fake-TLS secret; ignored if connection with non-fake-TLS protocol\n- `KEYS` is a list of one or more `KEY`, eg, `[port, tls_domain]`\n- `TABLE_NAME` is free-form text name of special internal database table, eg, `my_table`.\n  Tables will be created automatically when proxy is started; data in tables is not preserved when proxy\n  is restarted!\n  You can add or remove new values from table dynamically at any moment with commands like:\n    - `/opt/mtp_proxy/bin/mtp_proxy eval 'mtp_policy_table:add(my_table, tls_domain, \"google.com\").'` to add\n    - `/opt/mtp_proxy/bin/mtp_proxy eval 'mtp_policy_table:del(my_table, tls_domain, \"google.com\").'` to remove\n\nSome policy recipes / examples below\n\n#### Limit max connections to proxy port from single IP\n\nHere we allow maximum 100 concurrent connections from single IP to proxy port (as it was said earlier, it's not\nthe same as 100 unique \"users\"! Each telegram client opens up to 8 connections; usually 3):\n\n```erlang\n{mtproto_proxy,\n [\n  {policy,\n    [{max_connections, [port_name, client_ipv4], 100}]},\n  {ports,\n    \u003c..\u003e\n```\n\n#### Disallow connections from some IPs\n\n```erlang\n{mtproto_proxy\n [\n   {policy,\n     [{not_in_table, client_ipv4, ip_blacklist}]},\n   {ports,\n     \u003c..\u003e\n```\n\nAnd then add IPs to blacklist with command:\n\n```bash\n/opt/mtp_proxy/bin/mtp_proxy eval '\nmtp_policy_table:add(ip_blacklist, client_ipv4, \"203.0.113.1\").'\n```\n\nRemove from blacklist:\n\n```bash\n/opt/mtp_proxy/bin/mtp_proxy eval '\nmtp_policy_table:del(ip_blacklist, client_ipv4, \"203.0.113.1\").'\n```\n\n#### Personal proxy / multi-secret proxy\n\nWe can limit number of connections with single fake-TLS domain and only allow connections\nwith fake-TLS domains from whitelist.\n\n```erlang\n{mtproto_proxy\n [\n   {policy,\n     [{max_connections, [port_name, tls_domain], 15},\n      {in_table, tls_domain, customer_domains}]},\n   {ports,\n     \u003c..\u003e\n```\n\nNow we can assign each customer unique fake-TLS domain, eg, `my-client1.example.com`\nand give them unique TLS secret.\nBecause we only allow 10 connections with single fake-TLS secret, they will not be able to\nshare their credentials with others. To add client's fake domain to whitelist:\n\n```bash\n/opt/mtp_proxy/bin/mtp_proxy eval '\nmtp_policy_table:add(customer_domains, tls_domain, \"my-client1.example.com\").'\n```\n\nAnd then use https://seriyps.com/mtpgen.html to generate unique link for them.\nBe aware that domains table will be reset if proxy is restarted! Make sure you re-add them\nwhen proxy restarts (eg, via [systemd hook script](https://unix.stackexchange.com/q/326181/70382)).\n\n### IPv6\n\nCurrently proxy only supports client connections via IPv6, but can only connect to Telegram servers\nusing IPv4.\n\nTo enable IPv6, you should put IPv6 address in `listen_ip` config key.\nIf you want proxy to accept clients on the same port with both IPv4 and IPv6, you should\nhave 2 `ports` sections with the same `port`, `secret` and `tag`, but with different names and\ndifferent `listen_ip` (one v4 and one v6):\n\n```erlang\n {mtproto_proxy,\n  %% see src/mtproto_proxy.app.src for examples.\n  [\n   {ports,\n    [#{name =\u003e mtp_handler_all_ipv4,\n       listen_ip =\u003e \"0.0.0.0\",  % IPv4 address, eg 203.0.113.1\n       port =\u003e 1443,\n       secret =\u003e \u003c\u003c\"d0d6e111bada5511fcce9584deadbeef\"\u003e\u003e,\n       tag =\u003e \u003c\u003c\"dcbe8f1493fa4cd9ab300891c0b5b326\"\u003e\u003e},\n     #{name =\u003e mtp_handler_all_ipv6,\n       listen_ip =\u003e \"::\",  % IPv6 address, eg \"2001:db8:85a3::8a2e:370:7334\"\n       port =\u003e 1443,\n       secret =\u003e \u003c\u003c\"d0d6e111bada5511fcce9584deadbeef\"\u003e\u003e,\n       tag =\u003e \u003c\u003c\"dcbe8f1493fa4cd9ab300891c0b5b326\"\u003e\u003e}\n    ]}\n   ]},\n\n {kernel,\n\u003c...\u003e\n```\n\n### Tune resource consumption\n\nIf your server have low amount of RAM, try to set\n\n```erlang\n{upstream_socket_buffer_size, 5120},\n{downstream_socket_buffer_size, 51200},\n{replay_check_session_storage, off},\n{init_timeout_sec, 10},\n{hibernate_timeout_sec, 30},\n{ready_timeout_sec, 120},  % close connection after 2min of inactivity\n```\n\nthis may make proxy slower, it can start to consume bit more CPU, will be vulnerable to replay attacks,\nbut will use less RAM.\nYou should also avoid `max_connections` policy because it uses RAM to track connections.\n\nIf your server have lots of RAM, you can make it faster (users will get higher uppload/download speed),\nit will use less CPU and will be better protected from replay attacks, but will use more RAM:\n\n```erlang\n{max_connections, 128000},\n{upstream_socket_buffer_size, 20480},\n{downstream_socket_buffer_size, 512000},\n{replay_check_session_storage, on},\n{replay_check_session_storage_opts,\n  #{max_memory_mb =\u003e 2048,\n    max_age_minutes =\u003e 1440}},\n```\n\nOne more option to decrease CPU usage is to disable CRC32 checksum check:\n\n```erlang\n{mtp_full_check_crc32, false},\n```\n\nAlso, for highload setups it's recommended to increase sysctl parameters:\n\n```\nsudo sysctl net.ipv4.tcp_max_orphans=128000\nsudo sysctl 'net.ipv4.tcp_mem=179200 256000 384000'\n```\n\nValues for `tcp_mem` are in pages. Size of one page can be found by `getconf PAGESIZE` and is most\nlikely 4kb.\n\nIf you have installed proxy via Docker or use some NAT firewall settings, you may want to increase\nnetfilter conntrack limits to be at least the max number of connections you expect:\n\n```\nsudo sysctl net.netfilter.nf_conntrack_max=128000\n```\n\n\nHelpers\n-------\n\nNumber of connections\n\n```bash\n/opt/mtp_proxy/bin/mtp_proxy eval 'lists:sum([proplists:get_value(all_connections, L) || {_, L} \u003c- ranch:info()]).'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseriyps%2Fmtproto_proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseriyps%2Fmtproto_proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseriyps%2Fmtproto_proxy/lists"}