Files
2026-09-06 13:51:09 +00:00

150 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: telegram-web-proxy
description: >-
Deploy Telegram Desktop WEB Proxy (tproxy-server) on a VPS.
category: devops
tags:
- telegram
- web-proxy
- tproxy
- mtproto
- caddy
- dpi
---
# Telegram WEB Proxy (tproxy-server)
## When to Use This Skill
Use when you need to:
- Развернуть **WEB Proxy для Telegram Desktop** (telegramdesktop/tproxy-server)
на VPS — маскируется под обычный HTTPS-сайт на 443, настраивается в Telegram
Desktop как WEB Proxy (hostname + secret)
- Починить `mtproxy.service` после установки (203/EXEC, readyz 503)
- Добавить ещё один секрет/профиль (мульти-секреты)
- Понять, почему «снаружи не открываются порты 80/443» после установки
## Architecture
```
TD → HTTPS:443 → Caddy → tproxy-server:8080 → MTProxy:2398 → Telegram
└ admin :8081 (/readyz, /healthz)
```
- Caddy отдаёт Let's Encrypt сертификат (tls-alpn) и проксирует ВЕСЬ трафик на
tproxy-server (127.0.0.1:8080). tproxy-server сам различает: обычные запросы →
сайт-маскировку (`public_dir`), запросы WEB Proxy → MTProxy.
- Снаружи это просто HTTPS-сайт; наружу открыты только 80/443.
- nft-правило (`tproxy-firewall`) закрывает MTProxy-бэкенд 2398/8888 от внешнего
мира: `iifname != "lo" tcp dport {2398, 8888} drop`.
## Deploy
1. Склонировать upstream: `git clone https://github.com/telegramdesktop/tproxy-server.git`
2. Подготовить сайт-маскировку (каталог со статическим `index.html`; нейтральный,
БЕЗ упоминаний Telegram) и secret: `openssl rand -hex 16` (32 hex).
3. Загрузить на сервер (rsync, либо tar+ssh — см. грабли #4).
4. Запустить:
```bash
./deploy/install.sh --hostname HOST --email ME@EXAMPLE.COM \
--site-dir /tmp/tproxy-site --secret "$(cat /tmp/tproxy-secret.txt)"
```
Ставит: ca-certificates curl nftables, Caddy 2.11.4, Go 1.26.5, собирает
tproxy-server, MTProxy (pinned commit), создаёт systemd-сервисы:
`tproxy-server`, `mtproxy`, `tproxy-firewall`, `caddy`, таймер
`refresh-mtproxy-config` (daily, обновляет список IP Telegram в proxy-multi.conf).
5. Проверка:
```bash
systemctl status tproxy-server mtproxy tproxy-firewall caddy # все active
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8081/readyz # 200
curl -s -o /dev/null -w '%{http_code}' https://HOST/ # 200 (сайт)
nft list ruleset | grep -E '2398|8888' # drop для не-loopback
```
## Pitfalls
### 1. mtproxy.service → 203/EXEC (readyz 503)
**Симптом:** tproxy-server active, но `mtproxy` failed (203/EXEC), порт 2398 не
слушается, `/readyz` → 503 (healthz при этом 200).
**Причина:** install.sh собирает MTProxy в `/opt/MTProxy/objs/bin/mtproto-proxy`,
но umask даёт бинарю и каталогам `700 root:root`. Юнит `mtproxy.service`
запускается от пользователя `mtproxy` (NoNewPrivileges, ProtectSystem=strict) —
не может прочитать бинарь → 203/EXEC.
**Фикс:**
```bash
chmod 755 /opt/MTProxy /opt/MTProxy/objs /opt/MTProxy/objs/bin
chown root:mtproxy /opt/MTProxy/objs/bin/mtproto-proxy
chmod 750 /opt/MTProxy/objs/bin/mtproto-proxy
systemctl restart mtproxy
# → active (running), слушает 0.0.0.0:2398, readyz → 200
```
Повторный запуск install.sh безопасен (идемпотентен).
### 2. Флейк `go test ./...` внутри install.sh
Первый прогон (холодный кэш Go, параллельная сборка) может упасть на
`internal/config: TestLoadAcceptsSystemdCredentialReadPermissions`. Повторный —
PASS. Это гонка при холодном прогоне, не баг кода. Лечение: перезапустить
install.sh.
### 3. «Порты 80/443 закрыты снаружи» — ложная тревога
Если после установки curl снаружи не отвечает: сначала `ss -tlnp` на сервере.
Чаще всего на порту просто НИЧЕГО не слушает (curl = connection refused), а
firewall провайдера ни при чём. Проверка: поднять временный слушатель
(`python3 -m http.server 80`) и проверить TCP connect снаружи. У Hostkey
отдельного firewall в панели НЕТ — порты открыты по умолчанию; настройки
«прокси/фаервол» в панели искать не нужно.
Различать: `timeout` = режется (firewall/DPI), `refused` = нет слушателя.
### 4. rsync отсутствует на Debian minimal
Если на сервере нет rsync, грузить дерево tar+ssh:
```bash
tar czf - tproxy-server/ | ssh root@HOST 'mkdir -p /tmp/tproxy-server && tar xzf - -C /tmp'
```
## Multi-profile secrets (несколько секретов)
Поддерживается: `/etc/tproxy-server/profiles.json` — **массив** профилей, у
каждого свой `secret`. Лимит `max_profiles: 32` (в config.json). Все профили по
умолчанию ведут в один MTProxy-бэкенд (127.0.0.1:2398).
```json
{"profiles":[
{"name":"default","secret":"<hex32>","backend":"127.0.0.1:2398"},
{"name":"second","secret":"<hex32>","backend":"127.0.0.1:2398"}
]}
```
- systemd читает через `LoadCredential=profiles.json:/etc/tproxy-server/profiles.json`
**при старте** → после правки `systemctl restart tproxy-server`.
- Права файла должны быть 600 root (иначе Load откажет — тот самый
`TestLoadAcceptsSystemdCredentialReadPermissions`).
- Формат секрета: 16 байт = 32 hex (обычный), либо 17 байт с префиксом `dd`
(fake-TLS/DD режим). `openssl rand -hex 16` — обычный 32-hex, для Telegram
Desktop WEB Proxy это нужно.
## Client setup
Telegram Desktop → Settings → Advanced → Connection Type → Use custom proxy →
NEW PROXY → WEB Proxy: hostname + secret (32 hex).
Ссылка для шаринга не `t.me/proxy?...` (это MTProto-ссылка), а передаётся полями
(hostname/secret) — WEB Proxy не имеет share-ссылки вида `t.me/proxy`.
## Related
- `mtproto-proxy` — классический MTProto proxy через Docker (seriyps), секреты с
`ee` (Fake TLS), ссылки `t.me/proxy`. Другой тип прокси.
- `networking-proxy` — umbrella по DPI-обходу (XRay, AmneziaWG, Shadowsocks, NNTP,
SSH-туннели).
- INSTALL_NOTES.md в репозитории `tproxy-web` (gitverse kpa39l) — полный опыт
установки 2026-08-31.