MTProtoProxy
Fast and Simple NodeJS MTProto Proxy(Telegram Proxy) with the support of PROMOTION CHANNELS, Secured Connection and Fake TLS.
Table of Contents
Install
This is a Node.js module available through the npm registry.
Before installing, download and install Node.js. Node.js 8.0 or higher is required.
Installation is done using the
npm install
command:
$ npm install mtprotoproxy
Introduction
This module is not a tool only, it contains APIs which can be used to cusomize the Telegram MTProto proxy. It can be used to log, limit access and create proxy farms that are very hard to filter. It is designed to be as simple as possible and to understand and study the protocol. This proxy contains the secured protocol and Fake TLS version. Unsecured protocol is not supported. Please remeber that in order to use secured version of the protocol, secret should be started with 'dd' and for Fake TLS protocol, secret should be started with 'ee'.
Documentation
Constructor
const MTProtoProxy = ;let telegram=secretshttpServerenterleaveready
When createing a mtprotoproxy, you have to set the following options:
-
secrets
: An array of secrets that clients have to use to connect to the server. It is an array of 34 character length strings. (Strings should start eighter with 'dd' or 'ee'; when publishing proxies having their secret start with 'ee' you have to manually add SNI name to the end of the proxy. i. e. if your secret inside the program is ee00000000000000000000000000000000 you have to publish your secret as ee00000000000000000000000000000000676f6f676c652e636f6d which 676f6f676c652e636f6d is the hex decoded presentation of 'google.com' and is called SNI) -
enter
: An async function, or a function returning a Promise. This function is called with the user address, port (user's local port), id, secretIndex (which is the index of the secret that client used to connect to proxy) and SNI (in the case of fake TLS proxies).address
: The IP address of the clientport
: The local port of the clientid
: connections id, an Integer number starting from zero, increamenting by one, which is used to label the connection.secretIndex
: is the index of the secret that client used to connect to proxySNI
: SNI in the case of fake TLS proxies,
This data can be used to limit the access of users based on their IP address or the number of concurrent connections or their traffic quota. If it throw an error, the client will be rejected. This function should return AD_TAG which is The advertisement tag used to identify the sponser channel. Can be obtained from @mtproxybot which is an official bot from Telegram. It means that based on the user's IP address, secret and SNI, this function can decide to change advertisement tag. Please note that the rapid change of AD_TAG for a specific user, will cause the telegram client not to show the advertisement.
-
leave
: A function that is called when ever the user leaves the proxy server or when an error occures. options is an object containing the following fields:bytesRead
: total bytes uploaded by the clientbytesWritten
: total bytes downloaded by the clientid
: connections id, which was used previously in theenter
async function.error
: error, the reason that connection was closed.
-
ready
: A function that is called when the proxy has fetched all the options and ready for the clients to connect.
The following options are optional:
httpServer
: An instance of http.Server from NodeJS. It can be used to serve an http server on the MTProtoProxy port.
Sample Code
'use strict' const MTProtoProxy = ;const http = ;const net = ;let ad_tag='cae554f8cbafba5b343a2d4f72e2f8e4' let totalBytesRead=0;let totalBytesWritten=0;let totalConnections=0let ongoingConnections=0let stats=;let tracker=; let httpServer=http; let telegram=secrets:'dd00000000000000000000000000000000''ee00000000000000000000000000000000'httpServerasync trackeroptionsid=options; console; ongoingConnections++; if statsoptionsaddress statsoptionsaddress++; else statsoptionsaddress=1; if optionsaddress==='8.8.8.8' return Promise; //or simply throw error return ad_tag; console; totalBytesRead+=optionsbytesRead; totalBytesWritten+=optionsbytesWritten; statstrackeroptionsidaddress--; if statstrackeroptionsidaddress===0 delete statstrackeroptionsidaddress; totalConnections++; ongoingConnections--; delete trackeroptionsid console let proxy=net; proxy proxy;;
Proxy server with the support for login/logout and complete web reporter.
'use strict' const MTProtoProxy = ;const http = ;const net = ; let totalBytesRead=0;let totalBytesWritten=0;let totalConnections=0let ongoingConnections=0let stats=;let allowedClients={}; let httpServer=http; let telegram= secrets:'dd00000000000000000000000000000000' httpServer async console; ongoingConnections++; statsoptionsid=Object; if allowedClientsoptionsaddress&&+-allowedClientsoptionsaddress<3*3600*1000 allowedClientsoptionsaddress=+; return Promise else delete allowedClientsoptionsaddress return Promise; //or simply throw error return 'cae554f8cbafba5b343a2d4f72e2f8e4'; let proxy=net; proxy proxy; console; allowedClientsoptionsaddress=+; totalBytesRead+=optionsbytesRead; totalBytesWritten+=optionsbytesWritten; Object; statsoptionsidended=true; statsoptionsiddtime=+; totalConnections++; ongoingConnections--; ;
Multi Core
NodeJS runs on one core. If you want to take the advantage of clustering on multiple processes, you have to fork the process and implement all the messaging between Master and Workers. The following code is a sample of implementation for the support of clustering.
'use strict'const cluster = ;const numCPUs = 4;//require('os').cpus().length;const MTProtoProxy = ;const http = ;const net = ; console; if clusterisMaster let totalBytesRead=0; let totalBytesWritten=0; let totalConnections=0 let ongoingConnections=0 let stats={}; { clusterworkersworkerId; } { console; ongoingConnections++; statsoptionsid+':'+core=optionsaddress; }; { console; totalBytesRead+=optionsbytesRead; totalBytesWritten+=optionsbytesWritten; delete statsoptionsid+':'+core; totalConnections++; ongoingConnections--; }; console; for let i = 0; i < numCPUs; i++ cluster; cluster; for const id in clusterworkers { clusterworkersid; }id; else console let rid=0; let queue={}; process { let id=rid; rid++; process; return { queueid=accept; ; } } let httpServer=http; let telegram= secrets:Buffer httpServer async process; return 'cae554f8cbafba5b343a2d4f72e2f8e4' {process} let proxy=net; proxy proxy; ;