mirror of
https://github.com/Flowseal/tg-ws-proxy.git
synced 2026-05-22 23:41:44 +03:00
Compare commits
6 Commits
v1.6.6
...
bff67b3ecf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bff67b3ecf | ||
|
|
d5abfbf9c2 | ||
|
|
8269ebe3bb | ||
|
|
3770569789 | ||
|
|
e72a44d74b | ||
|
|
33d3147c0b |
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: 🐛 Проблема
|
||||
title: '[Проблема] '
|
||||
description: Сообщить о проблеме
|
||||
labels: ['type: проблема', 'status: нуждается в сортировке']
|
||||
labels: ['bug']
|
||||
|
||||
body:
|
||||
- type: input
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: 🚀 Предложение
|
||||
title: '[Предложение] '
|
||||
description: Предложить улучшение или новую функциональность
|
||||
labels: ['type: предложение', 'status: нуждается в сортировке']
|
||||
labels: ['enhancement']
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
|
||||
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -457,6 +457,10 @@ jobs:
|
||||
body: |
|
||||
##
|
||||
### [❤️ Поддержать развитие проекта](https://github.com/Flowseal/tg-ws-proxy/blob/main/docs/Funding.md)
|
||||
|
||||
> [!TIP]
|
||||
> Не можете скачать?
|
||||
> Добавьте `185.199.109.133 release-assets.githubusercontent.com` в hosts или воспользуйтесь зеркалом: https://sourceforge.net/projects/tg-ws-proxy.mirror/files/
|
||||
files: |
|
||||
dist/TgWsProxy_windows.exe
|
||||
dist/TgWsProxy_windows_7_64bit.exe
|
||||
|
||||
1
.github/workflows/issue-triage.yml
vendored
1
.github/workflows/issue-triage.yml
vendored
@@ -9,6 +9,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
if: contains(github.event.issue.labels.*.name, 'bug')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Comment on new issue
|
||||
|
||||
69
docs/README.docker.md
Normal file
69
docs/README.docker.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# TG WS Proxy для Docker
|
||||
|
||||
## Установка из исходников
|
||||
|
||||
Вводите команды последовательно, одну за другой:
|
||||
|
||||
```bash
|
||||
# Скачиваем репозиторий
|
||||
git clone https://github.com/Flowseal/tg-ws-proxy.git
|
||||
|
||||
# Переходим в папку с проектом
|
||||
cd tg-ws-proxy
|
||||
|
||||
# Собираем образ
|
||||
docker build -t tg-ws-proxy .
|
||||
|
||||
# Запускаем контейнер
|
||||
docker run -d \
|
||||
--name tg-ws-proxy \
|
||||
--restart=always \
|
||||
-p 1443:1443 \
|
||||
tg-ws-proxy:latest
|
||||
|
||||
# Получаем ссылку для подключения
|
||||
docker logs tg-ws-proxy 2>&1 | grep 'tg://proxy'
|
||||
```
|
||||
|
||||
После выполнения последней команды вы увидите ссылку вида:
|
||||
|
||||
```text
|
||||
tg://proxy?server=172.17.0.2&port=1443&secret=dd68f127db1d...
|
||||
```
|
||||
|
||||
## Настройка параметров
|
||||
|
||||
Все настройки задаются переменными окружения при запуске контейнера:
|
||||
|
||||
| Переменная | Описание | По умолчанию |
|
||||
|-----------------------|------------------------------------------------|--------------------------------------|
|
||||
| `TG_WS_PROXY_HOST` | Адрес для приёма подключений | `0.0.0.0` |
|
||||
| `TG_WS_PROXY_PORT` | Порт внутри контейнера | `1443` |
|
||||
| `TG_WS_PROXY_SECRET` | Секретный ключ | `random` |
|
||||
| `TG_WS_PROXY_DC_IPS` | Пары «номер DC:IP» через пробел | `2:149.154.167.220 4:149.154.167.220`|
|
||||
|
||||
Пример с ручным указанием секрета:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name tg-ws-proxy \
|
||||
--restart=always \
|
||||
-p 1443:1443 \
|
||||
-e TG_WS_PROXY_SECRET="ваш_секрет" \
|
||||
tg-ws-proxy:latest
|
||||
```
|
||||
|
||||
Для генерации секрета можно использовать:
|
||||
|
||||
```bash
|
||||
openssl rand -hex 16
|
||||
```
|
||||
|
||||
## Настройка Telegram Desktop
|
||||
|
||||
1. Telegram → **Настройки** → **Продвинутые настройки** → **Тип подключения** → **Прокси**
|
||||
2. Добавьте прокси:
|
||||
- **Тип:** MTProto
|
||||
- **Сервер:** `127.0.0.1` (или переопределенный вами)
|
||||
- **Порт:** `1443` (или переопределенный вами)
|
||||
- **Secret:** из настроек или логов
|
||||
@@ -34,6 +34,7 @@
|
||||
- **[Windows](./README.windows.md)**
|
||||
- **[macOS](./README.macos.md)**
|
||||
- **[Linux](./README.linux.md)**
|
||||
- **[Docker](./README.docker.md)**
|
||||
- [Настройка Cloudflare-домена (CF-прокси)](./CfProxy.md)
|
||||
- [Fake TLS + upstream в Nginx](./FakeTlsNginx.md)
|
||||
- [Файлы конфигурации Tray-приложения](./TrayConfig.md)
|
||||
|
||||
@@ -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"
|
||||
|
||||
__all__ = ["__version__", "get_link_host", "proxy_config", "parse_dc_ip_list"]
|
||||
__all__ = ["__version__", "get_link_host", "proxy_config", "parse_dc_ip_list", "build_github_opener"]
|
||||
@@ -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()
|
||||
|
||||
@@ -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,35 @@ def get_link_host(host: str) -> Optional[str]:
|
||||
link_host = '127.0.0.1'
|
||||
return link_host
|
||||
else:
|
||||
return host
|
||||
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
|
||||
)
|
||||
|
||||
try:
|
||||
return self.do_open(_Conn, req)
|
||||
except Exception:
|
||||
return super().https_open(req)
|
||||
|
||||
|
||||
def build_github_opener() -> urllib.request.OpenerDirector:
|
||||
return urllib.request.build_opener(_PinnedHTTPSHandler())
|
||||
@@ -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")
|
||||
|
||||
15
windows.py
15
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:
|
||||
|
||||
Reference in New Issue
Block a user