ru1: WEB-прокси Telegram вместо telemt
На ru.ruzzy.dev:443 поднят официальный tproxy-server (relay, carrier websocket) перед официальным MTProxy на loopback. Фронт — nginx в ~/gost, сертификат только на ru.ruzzy.dev. - MTProxy: --nat-info 10.8.1.4:161.97.93.252 вручную — трафик к Telegram выходит через wg0 с IP fr1, автоопределение install.sh ошиблось бы и прокси молча не отвечал бы. - relay на 8090/8091: 8080 занят cadvisor. - telemt удалён окончательно (контейнер, образ, конфиг, том). - certbot до этого не работал вовсе: сертификат был просрочен с 2026-07-01, продлён и запущен. stacks/tproxy/: compose и nginx.conf стека ~/gost, setup-ru1.sh — однократная root-установка relay и MTProxy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
123cdaa19b
commit
2ab38bc1f8
@@ -5,7 +5,7 @@
|
||||
## Серверы
|
||||
- [`servers/de1.md`](servers/de1.md) — 213.136.74.247. **Выведен** (все сервисы остановлены, метрики удалены): был прокси/VPN-нодой (telemt, AmneziaWG, OpenVPN) плюс gitea, openclaw, боты — всё уехало на fr1 или в бэкапы. ⚠️ Сам файл описания под вывод не переписан.
|
||||
- [`servers/fr1.md`](servers/fr1.md) — `fr1.ruzzy.dev` (161.97.93.252). Основная нода (Ubuntu 24.04): мониторинг, gitea, AmneziaWG exit для ru1, боты (claude-channels, openclaw), статика `www`/`share`. Держит апекс `ruzzy.dev`.
|
||||
- [`servers/ru1.md`](servers/ru1.md) — `85.198.109.86` (VDSina, РФ). VPN entry-нода (OpenVPN ×2, AmneziaWG **до fr1** после переключения, WireGuard клиентов, telemt), умный роутинг RU/зарубеж. ⚠️ Файл описания сверялся до переключения.
|
||||
- [`servers/ru1.md`](servers/ru1.md) — `85.198.109.86` (VDSina, РФ). VPN entry-нода (OpenVPN ×2, AmneziaWG **до fr1** после переключения, WireGuard клиентов), умный роутинг RU/зарубеж; WEB-прокси Telegram (tproxy-server + MTProxy) на `ru.ruzzy.dev:443`, telemt удалён 2026-10-09. ⚠️ Файл описания сверялся до переключения.
|
||||
|
||||
## Поддержание описаний в актуальном состоянии
|
||||
Тронул сервер — обнови `servers/<хост>.md` в том же прогоне. Контракт и
|
||||
|
||||
+36
-5
@@ -1,7 +1,7 @@
|
||||
# ru1 — `85.198.109.86` (RU entry node)
|
||||
|
||||
VPN entry-нода в РФ. Точка входа в топологии **RU↔DE**: умный роутинг (RU-трафик → напрямую, зарубежный → туннель AWG до de1). Полный runbook — `~/README.md` на сервере.
|
||||
Секреты (MTProxy user-secrets, ключи WG) — только на сервере, не здесь.
|
||||
Секреты (WEB-proxy secret в `/etc/tproxy-server/profiles.json` и `/etc/mtproxy/mtproxy.env`, `token.key`, ключи WG) — только на сервере, не здесь.
|
||||
|
||||
**Провайдер:** VDSina · РФ
|
||||
**ОС:** Ubuntu 24.04.3 LTS · kernel 6.8.0-78
|
||||
@@ -27,10 +27,34 @@ VPN entry-нода в РФ. Точка входа в топологии **RU↔D
|
||||
| OpenVPN #2 | 1195/udp (`tun1`) | RU-выход (весь трафик через ens3, DNS Yandex). Cfg `/etc/openvpn/server/ruopenvpn.conf` |
|
||||
| AmneziaWG `wg0` | (awg, `45451/udp`) | туннель до de1 (exit). `awg-quick@wg0`, cfg `/etc/amnezia/amneziawg/wg0.conf`, `Table=off` |
|
||||
| WireGuard `wg1` | 51820/udp | VPN для клиентов (Docker `linuxserver/wireguard`), подсеть `10.8.2.0/24`, `~/wireguard/` |
|
||||
| telemt (MTProxy) | 443 | FakeTLS под `ru.ruzzy.dev`, маска → nginx `127.0.0.1:4443`. API `9091`. Docker, `~/gost/` |
|
||||
| nginx | 80, 4443 | маскировочный сайт `ru.ruzzy.dev` (Docker `nginx:alpine`) |
|
||||
| WEB-прокси Telegram | 443 (через nginx) | `tproxy-server` (relay, systemd, `127.0.0.1:8090`, admin `:8091`) → официальный MTProxy (systemd, `2398`, stats `8888`, оба закрыты nftables для не-lo). Подробно — раздел ниже |
|
||||
| nginx | 80, 443 | фронт `ru.ruzzy.dev`: весь 443 → relay. Docker `nginx:alpine`, `~/gost/` |
|
||||
| certbot | — | `certbot renew` раз в 12 ч, webroot `~/gost/certbot/www` |
|
||||
|
||||
Контейнеры: `telemt`, `wireguard`, `nginx` (docker compose в `~/gost` и `~/wireguard`).
|
||||
Контейнеры: `nginx`, `certbot` (`~/gost`), `wireguard` (`~/wireguard`), агент мониторинга (`~/monitoring-agent`). Compose, nginx.conf и скрипт установки — копия в репо `stacks/tproxy/`.
|
||||
|
||||
## WEB-прокси Telegram (с 2026-10-09)
|
||||
Новый тип прокси в клиентах Telegram (Desktop ≥ 7.1.0; мобильные — по сообщениям с 13.0, официально не подтверждено). Клиент держит скрытый WebView к `https://ru.ruzzy.dev/` и гонит по HTTPS/WSS мультиплексированные MTProxy-потоки. Сервер — официальный [`telegramdesktop/tproxy-server`](https://github.com/telegramdesktop/tproxy-server), коммит `c8adb8b` (2026-09-29).
|
||||
- **Клиенту:** server `ru.ruzzy.dev`, secret — 32 hex из `profiles.json`. Ссылка: `https://t.me/webproxy?server=ru.ruzzy.dev&secret=<secret>`; получить на сервере — последней строкой вывода `setup-ru1.sh`.
|
||||
- **Цепочка:** клиент → nginx `:443` (TLS, `ru.ruzzy.dev`) → relay `127.0.0.1:8090` → MTProxy `127.0.0.1:2398` → middle-end Telegram через `wg0` → fr1.
|
||||
- **Mode A, без base path:** relay — единственный шлюз хоста и сам отдаёт публичный сайт из `/srv/tproxy-site` (копия маскировочного `~/gost/nginx/html/index.html`; перечитывается только при рестарте relay). Запросы без валидной capability (`?bridge=` = HMAC от секрета и имени хоста) получают обычный сайт. Base path не включали: по документации его понимает только Desktop.
|
||||
- ⚠️ **NAT для MTProxy задан вручную:** `MTPROXY_NAT_ARGS=--nat-info 10.8.1.4:161.97.93.252` в `/etc/mtproxy/mtproxy.env`. Официальный MTProxy выводит AES-ключи middle-end сессии из своего адреса; трафик к Telegram с ru1 уходит в wg0 и выходит с IP **fr1**. Автоопределение апстримного `install.sh` спросило бы ifconfig-сервис через ens3, получило 85.198.109.86 — и MTProxy принимал бы клиентов, никому не отвечая, без ошибок нигде. Сменится exit-IP fr1 или адрес wg0 — править здесь. Симптом: `journalctl -u mtproxy | grep 'Disconnected from RPC Middle-End'`.
|
||||
- **Юниты:** `tproxy-firewall` (nft-таблица `inet tproxy_backend`: 2398/8888 только с lo), `mtproxy`, `tproxy-server`, `refresh-mtproxy-config.timer` (ежедневно тянет `proxy-multi.conf`, рестарт MTProxy только при изменении). Бинарник relay `/usr/local/bin/tproxy-server` собран локально (`CGO_ENABLED=0 GOOS=linux GOARCH=amd64`), MTProxy — `/opt/MTProxy`, собран `deploy/install-mtproxy.sh` (закреплённый коммит + sha256).
|
||||
- **Carrier: `websocket`** (с 2026-10-09, было `https` по умолчанию) — поле `carrier_mode` профиля в `profiles.json`: один WSS-канал `/api/v1/ws` на все потоки клиента вместо POST + long poll. Клиенту менять нечего, режим выбирает сервер. Relay пингует WSS раз в 25 с простоя (`long_poll`), поэтому `proxy_read_timeout 90s` в nginx канал не рвёт. Смена режима — `systemctl restart tproxy-server`, живые сессии переподключаются. `websocket-lanes` не взят: отдельный WSS на поток, на macOS WebKit сериализует рукопожатия и подключение может не уложиться в таймаут клиента. Бэкап профиля до правки — `profiles.json.bak-20261009`.
|
||||
- ⚠️ Порты relay **8090/8091**, а не дефолтные 8080/8081: `*:8080` занят cadvisor из `~/monitoring-agent`.
|
||||
- ⚠️ **Логи nginx выключены** (`access_log off`): в URI bridge-страницы — capability, в `Sec-WebSocket-Protocol` — токен сессии. Не включать.
|
||||
- **Проверено 2026-10-09:** `readyz` 200; 10 ME-соединений с `10.8.1.4`, `Disconnected` — 0; obfuscated2 + `req_pq_multi` на `127.0.0.1:2398` → `resPQ` за ~60 мс (3/3); capability через публичный фронт → bridge-страница (200, свой CSP). **Живой клиент не проверялся.**
|
||||
- **Диагностика:** `curl -s 127.0.0.1:8091/readyz`, `curl -s 127.0.0.1:8091/metrics | grep tproxy_sessions`, `journalctl -u tproxy-server -u mtproxy`.
|
||||
- **Маршрут:** весь Telegram (`91.108.4/22`, `91.108.8/22`, `91.108.56/22`, `95.161.64/20`, `149.154.160/20`) — в main-таблице `dev wg0`. Упал wg0 — прокси не работает.
|
||||
- **Сертификат** `ru.ruzzy.dev` (LE, webroot, только это имя; перевыпущен 2026-10-09, до 2027-01-07). Продление: `certbot` в контейнере каждые 12 ч; nginx сам делает `reload` раз в 6 ч (цикл в `command` compose).
|
||||
⚠️ До 2026-10-09 контейнера certbot **не было вовсе**, хотя он был описан в compose: сертификат истёк 2026-07-01 и три месяца отдавался просроченным.
|
||||
- ⚠️ `nginx.conf` смонтирован в контейнер **одним файлом**: замена через `mv`/редактор с новым inode контейнер не видит, `nginx -s reload` перечитает старый. После такой замены — `docker compose restart nginx` (2026-10-09 так получили минуту простоя 443).
|
||||
- Открытый прокси для всех, кто знает secret; лимиты — дефолтные апстрима (128 сессий, 4096 потоков).
|
||||
|
||||
### История 2026-10-09
|
||||
1. Под «web-proxy для Telegram» сначала понят Telegram Web в браузере: nginx-прокси на `web.telegram.org` с переписыванием адресов DC (`zws*.ru.ruzzy.dev`) — **убран** в тот же день, не то.
|
||||
2. telemt (MTProxy, FakeTLS под `ru.ruzzy.dev`, был на 443, API `9091` торчал наружу) снят, возвращён, затем **удалён окончательно** по решению владельца: контейнер, образ, `~/gost/telemt-config` (со старым секретом), `telemt-data`, том `gost_mtproxy-config`.
|
||||
3. Поднят WEB-прокси (выше). Бэкапы compose/nginx.conf до изменений — `~/gost/*.bak-20261009*`.
|
||||
|
||||
## Умный роутинг (tun0 и wg1)
|
||||
- `ipset ru_ips` (~11400 подсетей, источник ipdeny.com). До routing decision (mangle PREROUTING):
|
||||
@@ -40,7 +64,7 @@ VPN entry-нода в РФ. Точка входа в топологии **RU↔D
|
||||
- tun1 — без умного роутинга (всегда RU/ens3).
|
||||
|
||||
## AWG Watchdog
|
||||
- `~/awg-watchdog.sh` в root-cron **каждые 3 мин**: если handshake `wg0` старше 5 мин → рестарт `awg-quick@wg0` + чистка дублей iptables. Лог `~/awg-watchdog.log`. (telemt зависит от wg0 — Telegram DC маршрутизируются через туннель до de1.)
|
||||
- `~/awg-watchdog.sh` в root-cron **каждые 3 мин**: если handshake `wg0` старше 5 мин → рестарт `awg-quick@wg0` + чистка дублей iptables. Лог `~/awg-watchdog.log`. (WEB-прокси зависит от wg0: адреса Telegram с хоста идут через туннель.)
|
||||
|
||||
## Клиенты
|
||||
- OpenVPN: `~/gen_client.sh --profile de|ru|both <имя>`, PKI `~/easy-rsa/pki`, профили `~/clients/`. CRL отключён.
|
||||
@@ -60,3 +84,10 @@ VPN entry-нода в РФ. Точка входа в топологии **RU↔D
|
||||
## ⚠️ Грабли (из README)
|
||||
- `wg1.conf` обязан иметь `Table = off` — иначе wg-quick при рестарте сносит default route и сервер теряет SSH (восстановление: `ip route add default via 85.198.109.1 dev ens3`).
|
||||
- Таблица маршрутизации — `vpn` (100), не `awg`.
|
||||
|
||||
## Открытые хвосты
|
||||
- **Живой клиент через WEB-прокси не проверен** (2026-10-09): серверная цепочка проверена по частям (см. раздел WEB-прокси). Поддержка в мобильных клиентах подтверждена только новостью про Telegram 13.0.
|
||||
- **DNS `*.ru.ruzzy.dev`** (CNAME → `ru.ruzzy.dev`, Namecheap) остался от веб-прокси Telegram Web — больше не нужен, удалить. Имена `zws*.ru.ruzzy.dev` уже попали в CT-логи через сертификат от 2026-10-09 (Let's Encrypt) — это не отменить.
|
||||
- `/tmp/tproxy-server` на сервере — исходники и `setup-ru1.sh`, нужны для `deploy/update-relay.sh`; `/tmp` чистится при ребуте — при обновлении заливать заново.
|
||||
- `~/gost/manage.sh` — от прежнего gost/SOCKS5, не используется.
|
||||
- Замечено при снапшоте 2026-10-09, не разбиралось: `iperf3 --server` (порт 5201 наружу, пользователь `iperf3`, PPID 1), cadvisor `unhealthy`. Остальное описание (OpenVPN, AWG, клиенты) сверялось до переключения на fr1 — см. строку в `AGENTS.md`.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# ru1: ~/gost/docker-compose.yml (каталог и имя проекта `gost` — исторические).
|
||||
# Фронт WEB-прокси Telegram. Сам relay и MTProxy — systemd на хосте
|
||||
# (setup-ru1.sh), nginx в host-network проксирует на 127.0.0.1:8090.
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: nginx
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
# certbot живёт в отдельном контейнере и не может дёрнуть nginx —
|
||||
# перечитываем сертификаты раз в 6 часов сами.
|
||||
command: ["/bin/sh", "-c", "while :; do sleep 6h; nginx -s reload; done & exec nginx -g 'daemon off;'"]
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./certbot/conf:/etc/letsencrypt:ro
|
||||
- ./certbot/www:/var/www/certbot:ro
|
||||
|
||||
certbot:
|
||||
image: certbot/certbot
|
||||
container_name: certbot
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./certbot/conf:/etc/letsencrypt
|
||||
- ./certbot/www:/var/www/certbot
|
||||
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --quiet; sleep 12h & wait $${!}; done;'"
|
||||
@@ -0,0 +1,67 @@
|
||||
events {}
|
||||
|
||||
http {
|
||||
server_tokens off;
|
||||
|
||||
# Ничего не логируем по ru.ruzzy.dev: в URI bridge-страницы — capability,
|
||||
# в Sec-WebSocket-Protocol — токен сессии (требование tproxy-server).
|
||||
access_log off;
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' "";
|
||||
}
|
||||
|
||||
upstream tproxy_relay {
|
||||
server 127.0.0.1:8090; # tproxy-server (systemd), 8080 занят cadvisor
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name ru.ruzzy.dev;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# Mode A из tproxy-server: relay — единственный шлюз хоста, он же отдаёт
|
||||
# публичный сайт (/srv/tproxy-site). Никаких отдельных location под сайт,
|
||||
# иначе ответы сайта и транспорта станут различимы для зондирования.
|
||||
server {
|
||||
listen 443 ssl;
|
||||
http2 on;
|
||||
server_name ru.ruzzy.dev;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/ru.ruzzy.dev/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/ru.ruzzy.dev/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
gzip on;
|
||||
|
||||
# Пачки uplink до 2 MiB; дефолтный 1 MiB ломает транспорт с 413.
|
||||
client_max_body_size 4m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://tproxy_relay;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
# Ровно один адрес: список relay отвергает.
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
# long poll relay — 25 с; не резать и не буферизовать.
|
||||
proxy_read_timeout 90s;
|
||||
proxy_send_timeout 90s;
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# Однократная установка WEB-прокси Telegram (tproxy-server + официальный MTProxy)
|
||||
# на ru1. Запускать от root из каталога с исходниками tproxy-server:
|
||||
# sudo bash /tmp/tproxy-server/setup-ru1.sh
|
||||
# Повторный запуск безопасен: секрет и token.key не перегенерируются.
|
||||
#
|
||||
# Отличия от deploy/install.sh апстрима:
|
||||
# - без Caddy: 80/443 держит nginx в docker (~/gost), он проксирует всё в relay;
|
||||
# - relay на 127.0.0.1:8090/8091 — 8080 занят cadvisor (*:8080);
|
||||
# - NAT задан вручную: трафик к Telegram идёт через wg0 и выходит с IP fr1,
|
||||
# а автоопределение install.sh спросило бы ifconfig-сервис через ens3
|
||||
# и получило 85.198.109.86 — MTProxy молча перестал бы отвечать клиентам;
|
||||
# - без base path: его пока понимает только Desktop.
|
||||
set -euo pipefail
|
||||
umask 077
|
||||
|
||||
repo="$(cd "$(dirname "$0")" && pwd)"
|
||||
hostname=ru.ruzzy.dev
|
||||
nat_args="--nat-info 10.8.1.4:161.97.93.252"
|
||||
|
||||
[[ "${EUID}" -eq 0 ]] || { echo "run as root" >&2; exit 1; }
|
||||
cd "$repo"
|
||||
|
||||
# 1. Официальный MTProxy (закреплённый коммит, sha256) + конфиг Telegram.
|
||||
bash deploy/install-mtproxy.sh
|
||||
|
||||
# 2. Relay.
|
||||
id tproxy >/dev/null 2>&1 || useradd --system --home /nonexistent --shell /usr/sbin/nologin tproxy
|
||||
install -o root -g root -m 0755 tproxy-server.bin /usr/local/bin/tproxy-server
|
||||
|
||||
install -d -o root -g root -m 0755 /srv/tproxy-site
|
||||
install -o root -g root -m 0644 /home/mik/gost/nginx/html/index.html /srv/tproxy-site/index.html
|
||||
|
||||
install -d -o root -g tproxy -m 0750 /etc/tproxy-server
|
||||
bash deploy/ensure-token-key.sh
|
||||
|
||||
if [[ ! -f /etc/tproxy-server/profiles.json ]]; then
|
||||
secret="$(openssl rand -hex 16)"
|
||||
printf '{"profiles":[{"name":"default","secret":"%s","backend":"127.0.0.1:2398"}]}\n' \
|
||||
"$secret" > /etc/tproxy-server/profiles.json
|
||||
printf 'MTPROXY_SECRET=%s\nMTPROXY_NAT_ARGS=%s\n' "$secret" "$nat_args" > /etc/mtproxy/mtproxy.env
|
||||
unset secret
|
||||
fi
|
||||
|
||||
cat > /etc/tproxy-server/config.json <<EOF
|
||||
{
|
||||
"public_hostname": "$hostname",
|
||||
"base_path": "",
|
||||
"listen": "127.0.0.1:8090",
|
||||
"admin_listen": "127.0.0.1:8091",
|
||||
"public_dir": "/srv/tproxy-site",
|
||||
"static_routes": "exact",
|
||||
"profiles_file": "/run/credentials/tproxy-server.service/profiles.json"
|
||||
}
|
||||
EOF
|
||||
chown root:tproxy /etc/tproxy-server/config.json /etc/tproxy-server/profiles.json
|
||||
chmod 0640 /etc/tproxy-server/config.json
|
||||
chmod 0400 /etc/tproxy-server/profiles.json
|
||||
chown root:mtproxy /etc/mtproxy/mtproxy.env
|
||||
chmod 0640 /etc/mtproxy/mtproxy.env
|
||||
|
||||
# 3. Юниты, firewall (2398/8888 только с lo), ежедневное обновление конфига Telegram.
|
||||
for unit in tproxy-server.service mtproxy.service tproxy-firewall.service \
|
||||
refresh-mtproxy-config.service refresh-mtproxy-config.timer; do
|
||||
install -o root -g root -m 0644 "deploy/$unit" "/etc/systemd/system/$unit"
|
||||
done
|
||||
install -o root -g root -m 0644 deploy/firewall.nft /etc/tproxy-server/firewall.nft
|
||||
install -o root -g root -m 0755 deploy/refresh-mtproxy-config.sh /usr/local/sbin/refresh-mtproxy-config
|
||||
|
||||
/usr/local/bin/tproxy-server -config /etc/tproxy-server/config.json \
|
||||
-profiles-file /etc/tproxy-server/profiles.json -check
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now tproxy-firewall.service
|
||||
systemctl enable --now mtproxy.service
|
||||
systemctl restart mtproxy.service
|
||||
systemctl enable --now tproxy-server.service
|
||||
systemctl enable --now refresh-mtproxy-config.timer
|
||||
|
||||
for _ in $(seq 20); do
|
||||
curl -fs -o /dev/null http://127.0.0.1:8091/readyz && break
|
||||
sleep 1
|
||||
done
|
||||
curl -fsS http://127.0.0.1:8091/readyz >/dev/null && echo "relay: ready"
|
||||
|
||||
echo "Ссылка для клиента: sudo sed -n 's/.*\"secret\":\"\\([0-9a-f]*\\)\".*/https:\\/\\/t.me\\/webproxy?server=$hostname\\&secret=\\1/p' /etc/tproxy-server/profiles.json"
|
||||
Reference in New Issue
Block a user