#!/usr/bin/env python import asyncio import struct import socket import urllib.parse import urllib.request import collections import time print ('------------------------------------------') print ('SOCKS5 PARA TELEGRAM') print ('USUARIO: Telegram SENHA: 1') print ('BY: @LindoFuLL CANAL: @PAYLOADHTTP') print ('APERTE CTRL A D PARA DEIXAR RODANDO') print ('------------------------------------------') PORT = input('\033[34mDIGITE A PORTA PARA O SOCKS5: ') USERS = {"Telegram": "1"} BLOCK_NON_TG_HOSTS = True HIDE_ERRORS_BEFORE_AUTH = True # all networks are /22 TG_NETWORKS = { "91.108.4.0", "91.108.8.0", "91.108.12.0", "91.108.16.0", "91.108.56.0", "149.154.160.0", "149.154.164.0", "149.154.168.0", "149.154.172.0" } STATS_PRINT_PERIOD = 600 PRINT_TG_INFO = True READ_BUF_SIZE = 1024 IPV4_ADDR_LEN = 4 IPV6_ADDR_LEN = 16 BAD_IPV4_ADDR = b"\x00\x00\x00\x00" BAD_PORT = b"\x00\x00" # Consts from RFC1928 SOCKS5_VERSION = b"\x05" SUBNEGOTIATION_VERSION = b"\x01" USERNAME_PASSWORD_METHOD = b"\x02" NO_ACCEPTABLE_METHODS = b"\xff" STATUS_SUCCESS = b"\x00" STATUS_FAIL = b"\x01" CMD_CONNECT = b"\x01" ADDR_IPV4 = b"\x01" ADDR_DOMAINNAME = b"\x03" ADDR_IPV6 = b"\x04" REPLY_SUCCEEDED = b"\x00" REPLY_GENERAL_FAILURE = b"\x01" REPLY_NOT_ALOWED = b"\x02" REPLY_REFUSED = b"\x05" REPLY_CMD_NOT_SUPPORTED = b"\x07" REPLY_ADDR_TYPE_NOT_SUPPORTED = b"\x08" RESERVED = b"\x00" def validate_addr(addr, addr_type): if BLOCK_NON_TG_HOSTS: if addr_type != ADDR_IPV4: return False ip_net = list(struct.unpack("!BBBB", addr)) # calc /22 ip_net[2] = ip_net[2] & 0xfc ip_net[3] = 0 net_addr = ".".join(map(str, ip_net)) if net_addr not in TG_NETWORKS: return False return True def init_stats(): global stats stats = {user: collections.Counter() for user in USERS} def update_stats(user, connects=0, curr_connects_x2=0, octets=0): global stats if user not in stats: stats[user] = collections.Counter() stats[user].update(connects=connects, curr_connects_x2=curr_connects_x2, octets=octets) async def initial_handshake(reader, writer): socks_version = await reader.readexactly(1) if socks_version != SOCKS5_VERSION: return False n_methods = struct.unpack("!B", await reader.readexactly(1))[0] if n_methods == 0: return False methods = await reader.readexactly(n_methods) if USERNAME_PASSWORD_METHOD not in methods: if not HIDE_ERRORS_BEFORE_AUTH: writer.write(SOCKS5_VERSION + NO_ACCEPTABLE_METHODS) await writer.drain() return False # choose user/password auth method writer.write(SOCKS5_VERSION + USERNAME_PASSWORD_METHOD) return True async def negotiate_login(reader, writer): subnegotiation_version = await reader.readexactly(1) if subnegotiation_version != SUBNEGOTIATION_VERSION: return "" user_len = struct.unpack("!B", await reader.readexactly(1))[0] if user_len == 0: return "" user = (await reader.readexactly(user_len)).decode(errors="ignore") password_len = struct.unpack("!B", await reader.readexactly(1))[0] if password_len == 0: return "" password = (await reader.readexactly(password_len)).decode(errors="ignore") if user not in USERS or password != USERS[user]: if not HIDE_ERRORS_BEFORE_AUTH: writer.write(SUBNEGOTIATION_VERSION + STATUS_FAIL) await writer.drain() return "" writer.write(SUBNEGOTIATION_VERSION + STATUS_SUCCESS) return user async def handle_request(reader, writer): "Returns host and port to connect" def gen_reply(reply_code, fam=ADDR_IPV4, ip=BAD_IPV4_ADDR, port=BAD_PORT): return SOCKS5_VERSION + reply_code + RESERVED + fam + ip + port socks_version = await reader.readexactly(1) if socks_version != SOCKS5_VERSION: return None, None cmd = await reader.readexactly(1) if cmd != CMD_CONNECT: writer.write(gen_reply(REPLY_CMD_NOT_SUPPORTED)) await writer.drain() return None, None reserved = await reader.readexactly(1) address_type = await reader.readexactly(1) if address_type == ADDR_IPV4: address = await reader.readexactly(IPV4_ADDR_LEN) elif address_type == ADDR_IPV6: address = await reader.readexactly(IPV6_ADDR_LEN) elif address_type == ADDR_DOMAINNAME: address_len = struct.unpack("!B", await reader.readexactly(1))[0] if address_len == 0: return None, None address = await reader.readexactly(address_len) else: writer.write(gen_reply(REPLY_ADDR_TYPE_NOT_SUPPORTED)) await writer.drain() return None, None if not validate_addr(address, address_type): writer.write(gen_reply(REPLY_NOT_ALOWED)) await writer.drain() return None, None if address_type == ADDR_IPV4: address = socket.inet_ntop(socket.AF_INET, address) elif address_type == ADDR_IPV6: address = socket.inet_ntop(socket.AF_INET6, address) port = struct.unpack("!H", await reader.readexactly(2))[0] try: reader_tgt, writer_tgt = await asyncio.open_connection(address, port) except ConnectionRefusedError as E: writer.write(gen_reply(REPLY_REFUSED)) await writer.drain() return None, None except OSError as E: writer.write(gen_reply(REPLY_GENERAL_FAILURE)) await writer.drain() return None, None writer.write(gen_reply(REPLY_SUCCEEDED, ADDR_IPV4, BAD_IPV4_ADDR, BAD_PORT)) await writer.drain() return reader_tgt, writer_tgt async def handle_client(reader, writer): if not await initial_handshake(reader, writer): writer.close() return user = await negotiate_login(reader, writer) if not user: writer.close() return update_stats(user, connects=1) reader_tgt, writer_tgt = await handle_request(reader, writer) if reader_tgt is None or writer_tgt is None: writer.close() return async def connect_reader_to_writer(rd, wr, user): update_stats(user, curr_connects_x2=1) try: while True: data = await rd.read(READ_BUF_SIZE) if not data: wr.write_eof() await wr.drain() wr.close() return else: update_stats(user, octets=len(data)) wr.write(data) await wr.drain() except (ConnectionResetError, BrokenPipeError, OSError, AttributeError): wr.close() finally: update_stats(user, curr_connects_x2=-1) asyncio.ensure_future(connect_reader_to_writer(reader_tgt, writer, user)) asyncio.ensure_future(connect_reader_to_writer(reader, writer_tgt, user)) async def handle_client_wrapper(reader, writer): try: await handle_client(reader, writer) except (asyncio.IncompleteReadError, ConnectionResetError): writer.close() async def stats_printer(): global stats while True: await asyncio.sleep(STATS_PRINT_PERIOD) print("Stats for", time.strftime("%d.%m.%Y %H:%M:%S")) for user, stat in stats.items(): print("%s: %d connects (%d current), %.2f MB" % ( user, stat["connects"], stat["curr_connects_x2"] // 2, stat["octets"] / 1000000)) print(flush=True) def print_tg_info(): my_ip = socket.gethostbyname(socket.gethostname()) octets = [int(o) for o in my_ip.split(".")] ip_is_local = (len(octets) == 4 and ( octets[0] in [127, 10] or octets[0:2] == [192, 168] or (octets[0] == 172 and 16 <= octets[1] <= 31))) if ip_is_local: my_ip = "YOUR_IP" for user in USERS: params = { "server": my_ip, "port": PORT, "user": user, "pass": USERS[user] } print("tg://socks?" + urllib.parse.urlencode(params), flush=True) def main(): init_stats() loop = asyncio.get_event_loop() stats_printer_task = asyncio.Task(stats_printer()) asyncio.ensure_future(stats_printer_task) task = asyncio.start_server(handle_client_wrapper, "0.0.0.0", PORT, loop=loop) server = loop.run_until_complete(task) try: loop.run_forever() except KeyboardInterrupt: pass stats_printer_task.cancel() server.close() loop.run_until_complete(server.wait_closed()) loop.close() if __name__ == "__main__": if PRINT_TG_INFO: print_tg_info() main()