{"id":13466413,"url":"https://github.com/9seconds/mtg","last_synced_at":"2026-02-28T16:01:00.667Z","repository":{"id":41176339,"uuid":"135544649","full_name":"9seconds/mtg","owner":"9seconds","description":"Highly opinionated MTPROTO proxy for Telegram","archived":false,"fork":false,"pushed_at":"2026-02-26T12:56:35.000Z","size":1223,"stargazers_count":2272,"open_issues_count":2,"forks_count":298,"subscribers_count":43,"default_branch":"master","last_synced_at":"2026-02-26T19:37:53.036Z","etag":null,"topics":["mtproto","mtproxy","telegram"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/9seconds.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-05-31T06:55:52.000Z","updated_at":"2026-02-26T18:43:29.000Z","dependencies_parsed_at":"2022-07-14T09:22:36.291Z","dependency_job_id":"3b662d65-3706-418f-8dfd-49837b6c8510","html_url":"https://github.com/9seconds/mtg","commit_stats":{"total_commits":681,"total_committers":21,"mean_commits":32.42857142857143,"dds":0.04992657856093985,"last_synced_commit":"e68d0c7da53b266019d33644b902e8872c84fe32"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/9seconds/mtg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9seconds%2Fmtg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9seconds%2Fmtg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9seconds%2Fmtg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9seconds%2Fmtg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/9seconds","download_url":"https://codeload.github.com/9seconds/mtg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9seconds%2Fmtg/sbom","scorecard":{"id":6483,"data":{"date":"2025-08-11","repo":{"name":"github.com/9seconds/mtg","commit":"e68d0c7da53b266019d33644b902e8872c84fe32"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.2,"checks":[{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":2,"reason":"Found 3/13 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":9,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: topLevel 'checks' permission set to 'read': .github/workflows/ci.yaml:7","Info: topLevel 'contents' permission set to 'read': .github/workflows/ci.yaml:8","Info: topLevel 'deployments' permission set to 'read': .github/workflows/ci.yaml:9","Info: topLevel 'issues' permission set to 'read': .github/workflows/ci.yaml:10","Info: topLevel 'repository-projects' permission set to 'read': .github/workflows/ci.yaml:13","Info: topLevel 'security-events' permission set to 'read': .github/workflows/ci.yaml:14","Info: topLevel 'statuses' permission set to 'read': .github/workflows/ci.yaml:15","Info: topLevel 'actions' permission set to 'read': .github/workflows/ci.yaml:6","Info: topLevel 'discussions' permission set to 'read': .github/workflows/ci.yaml:11","Info: topLevel 'pull-requests' permission set to 'read': .github/workflows/ci.yaml:12","Info: topLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:17","Info: topLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:18","Info: topLevel 'pull-requests' permission set to 'read': .github/workflows/codeql-analysis.yml:19","Warn: topLevel 'security-events' permission set to 'write': .github/workflows/codeql-analysis.yml:20","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:83: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:88: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:95: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:110: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:115: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:120: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:130: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:136: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:142: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:145: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:148: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:157: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:164: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:171: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:77: update your workflow using https://app.stepsecurity.io/secureworkflow/9seconds/mtg/codeql-analysis.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:4","Info:   0 out of  15 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   8 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":10,"reason":"project is fuzzed","details":["Info: GoBuiltInFuzzer integration found: mtglib/internal/faketls/client_hello_fuzz_test.go:12","Info: GoBuiltInFuzzer integration found: mtglib/internal/obfuscated2/client_handshake_fuzz_internal_test.go:12","Info: GoBuiltInFuzzer integration found: mtglib/internal/obfuscated2/server_handshake_fuzz_internal_test.go:10","Info: GoBuiltInFuzzer integration found: mtglib/internal/obfuscated2/server_handshake_fuzz_test.go:10","Info: GoBuiltInFuzzer integration found: mtglib/internal/obfuscated2/server_handshake_fuzz_test.go:34"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v2.1.7 not signed: https://api.github.com/repos/9seconds/mtg/releases/74002184","Warn: release artifact v1.0.12 not signed: https://api.github.com/repos/9seconds/mtg/releases/74001191","Warn: release artifact v2.1.6 not signed: https://api.github.com/repos/9seconds/mtg/releases/62323792","Warn: release artifact v1.0.11 not signed: https://api.github.com/repos/9seconds/mtg/releases/62323615","Warn: release artifact v2.1.5 not signed: https://api.github.com/repos/9seconds/mtg/releases/61609236","Warn: release artifact v2.1.7 does not have provenance: https://api.github.com/repos/9seconds/mtg/releases/74002184","Warn: release artifact v1.0.12 does not have provenance: https://api.github.com/repos/9seconds/mtg/releases/74001191","Warn: release artifact v2.1.6 does not have provenance: https://api.github.com/repos/9seconds/mtg/releases/62323792","Warn: release artifact v1.0.11 does not have provenance: https://api.github.com/repos/9seconds/mtg/releases/62323615","Warn: release artifact v2.1.5 does not have provenance: https://api.github.com/repos/9seconds/mtg/releases/61609236"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":0,"reason":"15 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3554 / GHSA-528q-4pgm-wvg2","Warn: Project is vulnerable to: GO-2023-2402 / GHSA-45x7-px36-x8w8","Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77","Warn: Project is vulnerable to: GO-2022-0969 / GHSA-69cg-p879-7622","Warn: Project is vulnerable to: GO-2022-1144 / GHSA-xrjj-mj9h-534m","Warn: Project is vulnerable to: GO-2023-1571 / GHSA-vvpx-j8f3-3w6h","Warn: Project is vulnerable to: GO-2023-1988 / GHSA-2wrh-6pvc-2jm9","Warn: Project is vulnerable to: GO-2023-2102 / GHSA-4374-p667-p6c8","Warn: Project is vulnerable to: GHSA-qppj-fm5r-hxr3","Warn: Project is vulnerable to: GO-2024-2687 / GHSA-4v7x-pqxf-cx7m","Warn: Project is vulnerable to: GO-2024-3333","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw","Warn: Project is vulnerable to: GO-2024-2611 / GHSA-8r3f-844c-mc37"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 24 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-14T13:39:15.194Z","repository_id":41176339,"created_at":"2025-08-14T13:39:15.194Z","updated_at":"2025-08-14T13:39:15.194Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29941794,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T13:49:17.081Z","status":"ssl_error","status_checked_at":"2026-02-28T13:48:50.396Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["mtproto","mtproxy","telegram"],"created_at":"2024-07-31T15:00:43.789Z","updated_at":"2026-02-28T16:01:00.452Z","avatar_url":"https://github.com/9seconds.png","language":"Go","readme":"# mtg\n\nHighly-opinionated (ex-bullshit-free) MTPROTO proxy for\n[Telegram](https://telegram.org/).\n\n[![CI](https://github.com/9seconds/mtg/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/9seconds/mtg/actions/workflows/ci.yaml)\n[![codecov](https://codecov.io/gh/9seconds/mtg/branch/master/graph/badge.svg?token=JfdDyGVpT4)](https://codecov.io/gh/9seconds/mtg)\n[![Go Reference](https://pkg.go.dev/badge/github.com/9seconds/mtg.svg)](https://pkg.go.dev/github.com/9seconds/mtg/v2)\n\n**If you use v1.0 or upgrade broke you proxy, please read the chapter\n[Version 2](#version-2)**\n\nIf you want to have a proxy that _supports adtag_ (possibility to promote a\nchannel with a special Telegram bot), I recommend to use\n[telemt](https://github.com/telemt/telemt) project. v1 of mtg supports it\nbut I do not see any reasonable point of using it: adtag requires communication\nvia a fragile set of middle proxies, requires complex setup that must expose\na public IPs, has lower bandwidth and latency.\n\nmtg idea is simple: minimal unbloated proxy that can handle a reasonable scale\n~10-20k simultaneous connections, has no user management, but ticks all\ncheckboxes related to its main intent: provide a way to use Telegram.\n\n## Rationale\n\nThere are several available proxies for Telegram MTPROTO available. Here\nare the most notable:\n\n* [Official](https://github.com/TelegramMessenger/MTProxy)\n* [Python](https://github.com/alexbers/mtprotoproxy)\n* [Erlang](https://github.com/seriyps/mtproto_proxy)\n* [Telemt (Rust)](https://github.com/telemt/telemt)\n\nYou can use any of these. They work great and all implementations have\nfeature parity now. This includes support of adtag, replay attack\nprotection, domain fronting, faketls, and so on. mtg has a similar\ngoal: to give a possibility to connect to Telegram in a restricted,\ncensored environment. But it does it slightly differently in details\nthat probably matter.\n\n* **Resource-efficient**\n\n  It has to be resource-efficient. It does not mean that you will see\n  the smallest memory usage. It means that it will try to use allocated\n  resources in zero-waste mode, reusing as much memory as possible and\n  so on.\n\n* **Easily deployable**\n\n  I strongly believe that Telegram proxies should follow the way of\n  [ShadowSocks](https://shadowsocks.org): promoted channels is a strange\n  way of doing business I suppose. I think the only viable way is to\n  have a proxy that can be restored anywhere easily.\n\n* **Supports proxy protocol v1/v2**\n\n  This makes integration with loadbalancers like HAProxy and ELB a first class\n  citizen by supporting their\n  [commuication protocols](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt).\n\n* **A single secret**\n\n  I think that multiple secrets solve no problems and just complex\n  software. I also believe that in the case of throwout proxies, this\n  the feature is a useless luxury.\n\n* **No adtag support**\n\n  Please read [Version 2](#version-2) chapter.\n\n* **No management WebUI**\n\n  This is an implementation of a simple lightweight proxy. I won't do that.\n\n* **Proxy chaining**\n\n  mtg has the support of [SOCKS5](https://en.wikipedia.org/wiki/SOCKS)\n  proxies. So, in theory, you can run this proxy as a frontend\n  and route traffic via [v2ray](https://www.v2ray.com/),\n  [Gost](https://docs.ginuerzh.xyz/gost/),\n  [Trojan](https://trojan-gfw.github.io/trojan/), or any other project\n  you like.\n\n* **Native blocklist support**\n\n  Previously, this was delegated to the [FireHOL](https://firehol.org/)\n  project or similar ones which track attacks and publish a list of\n  potentially dangerous IPs. mtg has native support of such blocklists.\n\n* **Can be used as a library**\n\n  mtg v2 was redesigned in a way so it can be embedded into your\n  software (written in Golang) with a minimum effort + you can replace\n  some parts with those you want.\n\n### Version 2\n\nIf you use version 1.x before, you are probably noticed some major\nbackward non-compatible details:\n\n1. Configuration file\n2. Removed support of adtag\n\nFor the configuration file, please check out the full example in this\nrepository. It has a lot of comments and most of the options are\noptional. We do have only `secret` and `bind-to` sections mandatory.\nOther sections in the example configuration file are filled with default\nvalues.\n\nAdtag support was removed completely. This was done to debloat mtg and\nkeep it simple and obvious. Hopefully, this goal is achieved and the\nsource code is clean and straightforward enough.\n\nI always was quite skeptical about adtag. In my POV, a proxy as a fat\nbig connectivity point for hundreds of clients is an illusion. If you\nwork in a censored environment, the first thing that authority does is\nIP blocking. For us, it means, those big proxies that can benefit from\nhaving a pinned channel are going to be blocked in a minute.\n\nProxy has to be intimate. It has to be shared within a small group as\na family or maybe your college friends. It has to have a small number\nof connections and never publicly announced its presence. It has to fly\nunder the radar. If the proxy is detected, you need to be able to give\na rebirth on a new IP address as soon as possible. I do no think that\nhaving some special channel for such a use case makes any sense.\n\nBut other details like replay attack protection, domain fronting,\naccurate FakeTLS implementation, IP blacklisting, and proxy\nchaining matter here. If you work in censored perimeter like\n[GFW](https://en.wikipedia.org/wiki/Great_Firewall)-protected\ncountry, you probably want to have an MTPROTO proxy as\na frontend that transports traffic via cloaked tunnels\nmade by [Trojan](https://trojan-gfw.github.io/trojan/),\n[Shadowsocks](https://shadowsocks.org), [v2ray](https://www.v2ray.com/),\nor [Gost](https://docs.ginuerzh.xyz/gost/). That's why you have to have\nthe support of chaining as a first-class citizen.\n\nYes, this is possible and doable with optional adtag support. But the\ntruth is that the MTPROTO proxy for Telegram is just a thing that either\nwork as a normal client (direct mode) or doing some RPC calls in [TL\nlanguage](https://core.telegram.org/mtproto/TL) (adtag support). I\nunderstand the intention of the developers and I understand that they\nwere under high pressure fighting with [RKN](https://rkn.gov.ru/) and\ndoing TON after that. Nothing is ideal. But for the proxy, it means that\nsource code is full of complex non-trivial code which is required only\nto support a feature that we barely need.\n\nSo, to have a reasonable MTPROTO proxy, adtag support was removed. This\nis a rare chance in my career where software v2 debloats a previous\nversion. It feels so good :)\n\n### Version 1 and 2\n\nI do continue to support both versions 1 and 2. But in a different mode.\n\nVersion 1 is now officially in maintenance mode. It means that I won't\nmake any new features or improvements there. You can consider a feature\nfreeze there. No bugs are going to be fixed there except for critical\nones. PRs are welcome though. The goal is to keep it working. It will\nget some periodical updates like updates to the new Golang version of\ndependencies version bump, but that's mostly it.\n\n**If you want to have mtg with _adtag support_, please use version 1**.\n\nVersion 2 is going to have all my love, active support, bug fixing, etc.\nIt is under active development and maintenance.\n\nThis project has several main branches\n\n1. [`master`](https://github.com/9seconds/mtg/tree/master) branch\n   contains a bleeding edge. It may potentially have some features\n   which will break your source code.\n2. [`stable`](https://github.com/9seconds/mtg/tree/stable) branch contains\n   dumps of a master branch when we consider it 'stable'. This is a\n   branch you probably want to pick.\n3. [`v2`](https://github.com/9seconds/mtg/tree/v2) has a development\n   of the v2.x version. In theory, it is the same as `master` but this\n   will change when we have v3.x.\n4. [`v1`](https://github.com/9seconds/mtg/tree/v1) has a version 1.x.\n\n## Getting started\n\n### Download mise\n\nmtg uses [mise](https://mise.jdx.dev/) to maintain its development\ndependencies + replaces a make for building things. Please\n[install](https://mise.jdx.dev/getting-started.html) it first.\n\n### Download a tool\n\n#### Download binaries\n\nBinaries can be downloaded from the release page. Also, you can download\ndocker image.\n\nFor the current version, please download like\n\n```console\ndocker pull nineseconds/mtg:2\n```\n\nFor version 1:\n\n```console\ndocker pull nineseconds/mtg:1\n```\n\nYou may also check both [Docker\nHub](https://hub.docker.com/r/nineseconds/mtg/tags) and [Github\nRegistry](https://github.com/users/9seconds/packages/container/package/mtg).\nPlease do not choose `latest` or `stable` if you want to avoid\nsurprises. Always choose some version tag.\n\nAlso, if you have `go` installed, you can always download this tool with `go get`:\n\n```console\ngo install github.com/9seconds/mtg/v2@latest\n```\n\n#### Build from sources\n\n```console\ngit clone https://github.com/9seconds/mtg.git\ncd mtg\nmise install\nmise tasks run build\n```\n\nor for the docker image:\n\n```console\nmise tasks run image\n```\n\n### Generate secret\n\nIf you already have a secret in Base64 format or that, which starts with `ee`,\nyou can skip this chapter. Otherwise:\n\n```console\n$ mtg generate-secret google.com\n7ibaERuTSGPH1RdztfYnN4tnb29nbGUuY29t\n```\n\nor\n\n```console\n$ mtg generate-secret --hex google.com\nee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d\n```\n\nequivalent commands with docker:\n\n```console\n$ docker run --rm nineseconds/mtg:2 generate-secret google.com\n7ibaERuTSGPH1RdztfYnN4tnb29nbGUuY29t\n\n$ docker run --rm nineseconds/mtg:2 generate-secret --hex google.com\nee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d\n```\n\nThis secret is a keystone for a proxy and your password for a client.\nYou need to keep it secured.\n\nWe recommend choosing a hostname wisely. Here we have a _google.com_\nbut in reality, all providers can easily detect that this is not a\nGoogle. Google has a list of networks it officially uses and your IP\naddress won't probably belong to it. It is a great idea to hide behind\nsome domain that has some relation to this IP address.\n\nFor example, you've bought a VPS from [Digital\nOcean](https://www.digitalocean.com/). Then it might be a good idea to\ngenerate a secret for _digitalocean.com_ then.\n\n\n### Simple run mode\n\nmtg supports 2 modes: simple and normal. Simple mode allows starting\nproxy with a small subset of configuration options you usually want to\nmodify. This is quite good for oneliners that you can copy-paste and do\nnot bother about external files whatsoever.\n\nLet's take a look:\n\n```console\nUsage: mtg simple-run \u003cbind-to\u003e \u003csecret\u003e\n\nRun proxy without config file.\n\nArguments:\n  \u003cbind-to\u003e    A host:port to bind proxy to.\n  \u003csecret\u003e     Proxy secret.\n\nFlags:\n  -h, --help                           Show context-sensitive help.\n  -v, --version                        Print version.\n\n  -d, --debug                          Run in debug mode.\n  -c, --concurrency=8192               Max number of concurrent connection to proxy.\n  -b, --tcp-buffer=\"4KB\"               Size of TCP buffer to use.\n  -i, --prefer-ip=\"prefer-ipv6\"        IP preference. By default we prefer IPv6 with fallback to IPv4.\n  -p, --domain-fronting-port=443       A port to access for domain fronting.\n  -n, --doh-ip=1.1.1.1                 IP address of DNS-over-HTTP to use.\n  -t, --timeout=10s                    Network timeout to use\n  -a, --antireplay-cache-size=\"1MB\"    A size of anti-replay cache to use.\n```\n\nSo, if you want to startup a proxy with CLI only, you can do something like\n\n```console\n$ mtg simple-run -n 1.1.1.1 -t 30s -a 512kib 127.0.0.1:3128 7hBO-dCS4EBzenlKbdLFxyNnb29nbGUuY29t\n```\n\nThe rest of the configuration will be taken from default values. But\na simple run is fine if you do not have any special requirements or\ngranular tuning. If you want it, please checkout the configuration\nfiles.\n\n### Prepare a configuration file\n\nPlease checkout an example configuration file. All options except of\n`secret` and `bind-to` are optional. You can safely have this minimal\nconfiguration file:\n\n```toml\nsecret = \"ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d\"\nbind-to = \"0.0.0.0:443\"\n```\n\nThis is enough to run the whole application. All other\noptions already have sensible defaults for the app at almost any scale.\n\nOh, the configuration is done in [TOML format](https://toml.io/en/).\n\n### Run a proxy\n\nPut a binary and a config into your webserver. Just for example,\na binary goes to `/usr/local/bin/mtg` and configuration to `/etc/mtg.toml`.\n\nNow you can create a systemd unit:\n\n```console\n$ cat /etc/systemd/system/mtg.service\n[Unit]\nDescription=mtg - MTProto proxy server\nDocumentation=https://github.com/9seconds/mtg\nAfter=network.target\n\n[Service]\nExecStart=/usr/local/bin/mtg run /etc/mtg.toml\nRestart=always\nRestartSec=3\nDynamicUser=true\nAmbientCapabilities=CAP_NET_BIND_SERVICE\n\n[Install]\nWantedBy=multi-user.target\n$ sudo systemctl daemon-reload\n$ sudo systemctl enable mtg\n$ sudo systemctl start mtg\n```\n\nor you can run a docker image\n\n```console\ndocker run -d -v $PWD/config.toml:/config.toml -p 443:3128 --name mtg-proxy --restart=unless-stopped nineseconds/mtg:2\n```\n\nwhere _443_ is a host port (a port you want to connect to from a\nclient), and _3128_ is the one you have in your config in the `bind-to`\nsection.\n\n### Access a proxy\n\nNow you can generate some useful links:\n\n```console\n$ mtg access /etc/mtg.toml\n{\n  \"ipv4\": {\n    \"ip\": \"x.y.z.a\",\n    \"port\": 3128,\n    \"tg_url\": \"tg://proxy?...\",\n    \"tg_qrcode\": \"https://api.qrserver.com/v1/create-qr-code?data...\",\n    \"tme_url\": \"https://t.me/proxy?...\",\n    \"tme_qrcode\": \"https://api.qrserver.com/v1/create-qr-code?data...\"\n  },\n  \"secret\": {\n    \"hex\": \"...\",\n    \"base64\": \"...\"\n  }\n}\n```\n\nor if you are using docker:\n\n```console\n$ docker exec mtg-proxy /mtg access /config.toml\n```\n\n## Metrics\n\nOut of the box, mtg works with\n[statsd](https://github.com/statsd/statsd) and\n[Prometheus](https://prometheus.io/). Please check configuration file\nexample to get how to set this integration up.\n\nHere goes a list of metrics with their types but without a prefix.\n\n| Name                        | Type    | Tags                             | Description                                                                                |\n|-----------------------------|---------|----------------------------------|--------------------------------------------------------------------------------------------|\n| client_connections          | gauge   | `ip_family`                      | Count of processing client connections.                                                    |\n| telegram_connections        | gauge   | `telegram_ip`, `dc`              | Count of connections to Telegram servers.                                                  |\n| domain_fronting_connections | gauge   | `ip_family`                      | Count of connections to fronting domain.                                                   |\n| iplist_size                 | gauge   | `ip_list`                        | A size of either allowlist or blocklist in use.                                            |\n| telegram_traffic            | counter | `telegram_ip`, `dc`, `direction` | Count of bytes, transmitted to/from Telegram.                                              |\n| domain_fronting_traffic     | counter | `direction`                      | Count of bytes, transmitted to/from fronting domain.                                       |\n| domain_fronting             | counter | –                                | Count of domain fronting events.                                                           |\n| concurrency_limited         | counter | –                                | Count of events, when client connection was rejected due to concurrency limit.             |\n| ip_blocklisted              | counter | `ip_list`                        | Count of events when client connection was rejected because IP was found in the blocklist. |\n| replay_attacks              | counter | –                                | Count of detected replay attacks.                                                          |\n\nTag meaning:\n\n| Name        | Values                     | Description                                   |\n|-------------|----------------------------|-----------------------------------------------|\n| ip_family   | `ipv4`, `ipv6`             | A version of the IP protocol.                 |\n| dc          |                            | A number of the Telegram DC for a connection. |\n| telegram_ip |                            | IP address of the Telegram server.            |\n| direction   | `to_client`, `from_client` | A direction of the traffic flow.              |\n| ip_list     | `allowlist`, `blocklist`   | A type of the IP list.                        |\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F9seconds%2Fmtg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F9seconds%2Fmtg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F9seconds%2Fmtg/lists"}