Skip to content

Commit 246b473

Browse files
committed
test1
1 parent 9936b98 commit 246b473

4 files changed

Lines changed: 161 additions & 6 deletions

File tree

pyrogram/connection/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def __init__(
6161

6262
async def connect(self) -> None:
6363
for i in range(Connection.MAX_CONNECTION_ATTEMPTS):
64-
self.protocol = self.protocol_factory(ipv6=self.ipv6, proxy=self.proxy, crypto_executor_workers=self.crypto_executor_workers, loop=self.loop)
64+
self.protocol = self.protocol_factory(dc_id=self.dc_id, ipv6=self.ipv6, proxy=self.proxy, crypto_executor_workers=self.crypto_executor_workers, loop=self.loop)
6565

6666
try:
6767
log.info("Connecting...")

pyrogram/connection/transport/tcp/tcp.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class ProxyDict(TypedDict):
3636
scheme: str
3737
hostname: str
3838
port: int
39+
secret: Optional[str]
3940
username: Optional[str]
4041
password: Optional[str]
4142

@@ -154,7 +155,7 @@ async def _connect_via_direct(self, destination: Tuple[str, int]) -> None:
154155
log.info("Connection established")
155156

156157
async def _connect(self, destination: Tuple[str, int]) -> None:
157-
if self.proxy:
158+
if self.proxy and isinstance(self.proxy, dict) and self.proxy.get("scheme", "").lower() in ("socks5", "socks4", "http"):
158159
await self._connect_via_proxy(destination)
159160
else:
160161
await self._connect_via_direct(destination)

pyrogram/connection/transport/tcp/tcp_abridged.py

Lines changed: 149 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,181 @@
2222

2323
from .tcp import TCP, ProxyDict
2424

25+
import hashlib
26+
import os
27+
28+
from pyrogram.crypto import aes
29+
2530
log = logging.getLogger(__name__)
2631

2732

2833
class TCPAbridged(TCP):
2934
def __init__(
3035
self,
36+
dc_id: int,
3137
ipv6: bool = False,
3238
proxy: Optional[Union[str, ProxyDict]] = None,
3339
crypto_executor_workers: int = 1,
3440
loop: Optional[asyncio.AbstractEventLoop] = None,
3541
) -> None:
3642
super().__init__(ipv6, proxy, crypto_executor_workers, loop)
43+
self.dc_id = dc_id
44+
self.encrypt = None
45+
self.decrypt = None
46+
self.secret = None
47+
self.hostname = None
48+
self.port = None
49+
if isinstance(proxy, dict) and proxy.get("scheme", "").lower() == "mtproxy":
50+
self.hostname = proxy.get("hostname")
51+
self.port = proxy.get("port")
52+
self.secret = proxy.get("secret")
53+
54+
async def connect_via_mtproxy(self, address):
55+
self.marker_event.clear()
56+
57+
nonce = bytearray(os.urandom(64))
58+
59+
while (
60+
nonce[0] == 0xef
61+
or nonce[:4] in (b"HEAD", b"POST", b"GET ", b"OPTI", b"\xee"*4)
62+
or nonce[4:8] == b"\x00"*4
63+
):
64+
nonce = bytearray(os.urandom(64))
65+
66+
temp = bytearray(nonce[55:7:-1])
67+
68+
secret = self.secret
69+
70+
if isinstance(secret, str):
71+
if secret.startswith("dd"):
72+
secret = secret[2:]
73+
secret = bytes.fromhex(secret)
74+
75+
encrypt_key = hashlib.sha256(
76+
bytes(nonce[8:40]) + secret
77+
).digest()
78+
79+
decrypt_key = hashlib.sha256(
80+
bytes(temp[:32]) + secret
81+
).digest()
82+
83+
self.encrypt = (
84+
encrypt_key,
85+
bytes(nonce[40:56]),
86+
bytearray(1)
87+
)
88+
89+
self.decrypt = (
90+
decrypt_key,
91+
bytes(temp[32:48]),
92+
bytearray(1)
93+
)
94+
95+
nonce[56:60] = b'\xef\xef\xef\xef'
96+
97+
nonce[60:62] = self.dc_id.to_bytes(
98+
2,
99+
"little",
100+
signed=True
101+
)
102+
103+
encrypted = aes.ctr256_encrypt(
104+
nonce,
105+
*self.encrypt
106+
)
107+
108+
nonce[56:64] = encrypted[56:64]
37109

110+
await super().connect((self.hostname, self.port))
111+
112+
await super().send(
113+
nonce,
114+
wait_for_marker=False
115+
)
116+
117+
self.marker_event.set()
118+
38119
async def connect(self, address: Tuple[str, int]) -> None:
120+
if self.hostname and self.port and self.secret:
121+
return await self.connect_via_mtproxy(address)
122+
39123
self.marker_event.clear()
40124
await super().connect(address)
41125
await super().send(b"\xef", wait_for_marker=False)
42126
self.marker_event.set()
43127

44-
async def send(self, data: bytes, *args) -> None:
128+
async def send_via_mtproxy(self, data: bytes, *args):
45129
length = len(data) // 4
46130

131+
payload = (
132+
bytes([length])
133+
if length <= 126
134+
else b"\x7f" + length.to_bytes(3, "little")
135+
) + data
136+
137+
payload = await self.loop.run_in_executor(
138+
self.crypto_executor,
139+
aes.ctr256_encrypt,
140+
payload,
141+
*self.encrypt
142+
)
143+
await super().send(payload)
144+
145+
async def send(self, data: bytes, *args) -> None:
146+
if self.hostname and self.port and self.secret:
147+
return await self.send_via_mtproxy(data, *args)
148+
149+
length = len(data) // 4
47150
await super().send(
48151
(bytes([length])
49-
if length <= 126
50-
else b"\x7f" + length.to_bytes(3, "little"))
152+
if length <= 126
153+
else b"\x7f" + length.to_bytes(3, "little"))
51154
+ data
52155
)
53156

157+
async def recv_via_mtproxy(self, length: int = 0):
158+
length = await super().recv(1)
159+
160+
if length is None:
161+
return None
162+
163+
length = aes.ctr256_decrypt(
164+
length,
165+
*self.decrypt
166+
)
167+
168+
if length == b"\x7f":
169+
length = await super().recv(3)
170+
171+
if length is None:
172+
return None
173+
174+
length = aes.ctr256_decrypt(
175+
length,
176+
*self.decrypt
177+
)
178+
179+
packet_length = int.from_bytes(
180+
length,
181+
"little"
182+
) * 4
183+
184+
data = await super().recv(packet_length)
185+
186+
if data is None:
187+
return None
188+
189+
return await self.loop.run_in_executor(
190+
self.crypto_executor,
191+
aes.ctr256_decrypt,
192+
data,
193+
*self.decrypt
194+
)
195+
54196
async def recv(self, length: int = 0) -> Optional[bytes]:
197+
if self.hostname and self.port and self.secret:
198+
return await self.recv_via_mtproxy(length)
199+
55200
length = await super().recv(1)
56201

57202
if length is None:
@@ -63,4 +208,4 @@ async def recv(self, length: int = 0) -> Optional[bytes]:
63208
if length is None:
64209
return None
65210

66-
return await super().recv(int.from_bytes(length, "little") * 4)
211+
return await super().recv(int.from_bytes(length, "little") * 4)

pyrogram/session/session.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ async def start(self):
181181

182182
init_connection_params = self.client.init_connection_params
183183

184+
proxy = None
185+
186+
if isinstance(proxy, dict) and proxy.get("scheme", "").lower() == "mtproxy":
187+
proxy = raw.types.InputClientProxy(
188+
address=proxy.get("hostname", ""),
189+
port=proxy.get("port", 0)
190+
)
191+
184192
if isinstance(init_connection_params, dict):
185193
init_connection_params = utils.obj_to_jsonvalue(init_connection_params)
186194

@@ -198,6 +206,7 @@ async def start(self):
198206
lang_code=self.client.lang_code,
199207
query=raw.functions.help.GetConfig(),
200208
params=init_connection_params,
209+
proxy=proxy
201210
)
202211
),
203212
timeout=self.START_TIMEOUT

0 commit comments

Comments
 (0)