diff --git a/proxy/__init__.py b/proxy/__init__.py index 9d1ce4d..135c42c 100644 --- a/proxy/__init__.py +++ b/proxy/__init__.py @@ -1,6 +1,6 @@ from .config import parse_dc_ip_list, proxy_config -from .utils import get_link_host +from .utils import get_link_host, build_github_opener -__version__ = "1.6.6" +__version__ = "1.6.5" -__all__ = ["__version__", "get_link_host", "proxy_config", "parse_dc_ip_list"] \ No newline at end of file +__all__ = ["__version__", "get_link_host", "proxy_config", "parse_dc_ip_list", "build_github_opener"] \ No newline at end of file diff --git a/proxy/config.py b/proxy/config.py index b59259d..8c2a32f 100644 --- a/proxy/config.py +++ b/proxy/config.py @@ -7,9 +7,10 @@ import threading from dataclasses import dataclass, field from typing import Dict, List -from urllib.request import Request, urlopen +from urllib.request import Request from .balancer import balancer +from .utils import build_github_opener log = logging.getLogger('tg-mtproto-proxy') @@ -70,7 +71,7 @@ def _fetch_cfproxy_domain_list() -> List[str]: try: req = Request(CFPROXY_DOMAINS_URL + "?" + "".join(random.choices(string.ascii_letters, k=7)), headers={'User-Agent': 'tg-ws-proxy'}) - with urlopen(req, timeout=10) as resp: + with build_github_opener().open(req, timeout=10) as resp: text = resp.read().decode('utf-8', errors='replace') encoded = [ line.strip() for line in text.splitlines() diff --git a/proxy/utils.py b/proxy/utils.py index 3b51aa6..c0f5980 100644 --- a/proxy/utils.py +++ b/proxy/utils.py @@ -1,6 +1,9 @@ import socket as _socket +import urllib.request +import http.client -from typing import Optional +from typing import Optional, Dict +from urllib.request import Request ZERO_64 = b'\x00' * 64 @@ -26,6 +29,11 @@ RESERVED_STARTS = {b'\x48\x45\x41\x44', b'\x50\x4F\x53\x54', b'\xdd\xdd\xdd\xdd', b'\x16\x03\x01\x02'} RESERVED_CONTINUE = b'\x00\x00\x00\x00' +_GITHUB_IPS: Dict[str, str] = { + "release-assets.githubusercontent.com": "185.199.109.133", + "raw.githubusercontent.com": "185.199.109.133", +} + def human_bytes(n: int) -> str: for unit in ('B', 'KB', 'MB', 'GB'): @@ -45,4 +53,32 @@ def get_link_host(host: str) -> Optional[str]: link_host = '127.0.0.1' return link_host else: - return host \ No newline at end of file + return host + + +class _PinnedHTTPSHandler(urllib.request.HTTPSHandler): + def https_open(self, req: Request): + host = req.host.split(":")[0] + ip = _GITHUB_IPS.get(host) + if not ip: + return super().https_open(req) + pinned = ip + + class _Conn(http.client.HTTPSConnection): + def connect(self): + self.sock = _socket.create_connection( + (pinned, self.port or 443), + self.timeout, + self.source_address, + ) + if self._tunnel_host: + self._tunnel() + self.sock = self._context.wrap_socket( + self.sock, server_hostname=self._tunnel_host or self.host + ) + + return self.do_open(_Conn, req) + + +def build_github_opener() -> urllib.request.OpenerDirector: + return urllib.request.build_opener(_PinnedHTTPSHandler()) \ No newline at end of file diff --git a/utils/update_check.py b/utils/update_check.py index 97f8062..f73f711 100644 --- a/utils/update_check.py +++ b/utils/update_check.py @@ -14,7 +14,8 @@ from itertools import zip_longest from pathlib import Path from typing import Any, Dict, Optional, Tuple from urllib.error import HTTPError, URLError -from urllib.request import Request, urlopen +from urllib.request import Request +from proxy.utils import build_github_opener REPO = "Flowseal/tg-ws-proxy" RELEASES_LATEST_API = f"https://api.github.com/repos/{REPO}/releases/latest" @@ -135,7 +136,7 @@ def fetch_latest_release( method="GET", ) try: - with urlopen(req, timeout=timeout) as resp: + with build_github_opener().open(req, timeout=timeout) as resp: code = getattr(resp, "status", None) or resp.getcode() new_etag = resp.headers.get("ETag") raw = resp.read().decode("utf-8", errors="replace") diff --git a/windows.py b/windows.py index 4ccc843..947b6f0 100644 --- a/windows.py +++ b/windows.py @@ -8,8 +8,11 @@ import threading import time import webbrowser import winreg +import tempfile + from pathlib import Path from typing import Optional +from proxy.utils import build_github_opener try: import pyperclip @@ -219,9 +222,6 @@ def update_ctk_form( def _perform_update(download_url: str, set_status=None) -> None: - import tempfile - import urllib.request - def _step(msg: str) -> None: log.info("Update: %s", msg) if set_status: @@ -244,7 +244,14 @@ def _perform_update(download_url: str, set_status=None) -> None: os.close(fd) tmp_path = Path(tmp_name) log.info("Downloading update from %s", download_url) - urllib.request.urlretrieve(download_url, str(tmp_path)) + opener = build_github_opener() + with opener.open(download_url) as _resp: + with open(str(tmp_path), "wb") as _fout: + while True: + _chunk = _resp.read(65536) + if not _chunk: + break + _fout.write(_chunk) except Exception as exc: _err(f"Не удалось скачать:\n{exc}") if tmp_path: