Intercept TLS, decrypt HTTP, and relay through Apps Script.
(self, host: str, port: int, reader, writer)
| 955 | await self._relay_http_stream(host, port, reader, writer) |
| 956 | |
| 957 | async def _do_mitm_connect(self, host: str, port: int, reader, writer): |
| 958 | """Intercept TLS, decrypt HTTP, and relay through Apps Script.""" |
| 959 | ssl_ctx = self.mitm.get_server_context(host) |
| 960 | |
| 961 | # Upgrade the existing connection to TLS (we are the server) |
| 962 | loop = asyncio.get_running_loop() |
| 963 | transport = writer.transport |
| 964 | protocol = transport.get_protocol() |
| 965 | |
| 966 | try: |
| 967 | new_transport = await loop.start_tls( |
| 968 | transport, protocol, ssl_ctx, server_side=True, |
| 969 | ) |
| 970 | except Exception as e: |
| 971 | # TLS handshake failed. Common causes: |
| 972 | # • Telegram Desktop / MTProto over port 443 sends obfuscated |
| 973 | # non-TLS bytes — we literally cannot decrypt these, and |
| 974 | # since the target IP is blocked we can't direct-tunnel |
| 975 | # either. Telegram will rotate to another DC on its own; |
| 976 | # failing fast here lets that happen sooner. |
| 977 | # • Client CONNECTs but never speaks TLS (some probes). |
| 978 | if is_ip_literal(host) and port == 443: |
| 979 | log.info( |
| 980 | "Non-TLS traffic on %s:%d (likely Telegram MTProto / " |
| 981 | "obfuscated protocol). This DC appears blocked; the " |
| 982 | "client should rotate to another endpoint shortly.", |
| 983 | host, port, |
| 984 | ) |
| 985 | elif port != 443: |
| 986 | log.debug( |
| 987 | "TLS handshake skipped for %s:%d (non-HTTPS): %s", |
| 988 | host, port, e, |
| 989 | ) |
| 990 | else: |
| 991 | log.debug("TLS handshake failed for %s: %s", host, e) |
| 992 | # Close the client side so it fails fast and can retry, rather |
| 993 | # than hanging on a half-open connection. |
| 994 | try: |
| 995 | if not writer.is_closing(): |
| 996 | writer.close() |
| 997 | except Exception: |
| 998 | pass |
| 999 | return |
| 1000 | |
| 1001 | # Update writer to use the new TLS transport |
| 1002 | writer._transport = new_transport |
| 1003 | |
| 1004 | await self._relay_http_stream(host, port, reader, writer) |
| 1005 | |
| 1006 | async def _relay_http_stream(self, host: str, port: int, reader, writer): |
| 1007 | """Read decrypted/origin-form HTTP requests and relay them.""" |
no test coverage detected