mirror of https://github.com/by-sonic/tglock.git
Add Habr article, LICENSE, CI/CD workflow
Made-with: Cursor:
This commit is contained in:
parent
d0646af85d
commit
7d7a519365
|
|
@ -0,0 +1,307 @@
|
|||
# Как я написал обход блокировки Telegram на Rust — без VPN, без серверов, через WebSocket
|
||||
|
||||
**Простой · 7 мин · Rust · Open source · Windows · Сетевые технологии · Из песочницы**
|
||||
|
||||
**TL;DR:** Написал open-source десктопное приложение **TG Unblock** на Rust, которое в один клик обходит блокировку Telegram через локальный WebSocket-прокси. Трафик заворачивается в обычный HTTPS к `web.telegram.org` — DPI не видит MTProto, провайдер не может шейпить. Без VPN, без серверов, без абонентки. Код на GitHub — [by-sonic/tglock](https://github.com/by-sonic/tglock).
|
||||
|
||||
---
|
||||
|
||||
## Предыстория: почему GoodbyeDPI не спасает
|
||||
|
||||
С весны 2025 года Telegram в России стал работать, мягко говоря, через боль. Сообщения доходят по 10 секунд, медиа не грузятся, звонки рвутся. Классическая картина: провайдер + DPI = страдания.
|
||||
|
||||
Первое, что приходит в голову — **GoodbyeDPI**. Запустил, пакеты фрагментируются, DPI не узнаёт MTProto... и вроде работает. Но:
|
||||
|
||||
- **Пинг 200+ мс** — при норме 40–60
|
||||
- **Постоянные переподключения** — DPI переобучается и режет соединения
|
||||
- **IP-шейпинг** — провайдер троттлит весь трафик к подсетям Telegram (149.154.x.x, 91.108.x.x)
|
||||
|
||||
GoodbyeDPI обманывает DPI на уровне пакетов, но **не решает проблему IP-шейпинга**. Если провайдер тупо режет скорость ко всем IP Telegram — хоть как фрагментируй, будет медленно.
|
||||
|
||||
VPN — вариант. Но:
|
||||
- Платные стоят денег и сливают скорость
|
||||
- Бесплатные сливают данные
|
||||
- Не все работают стабильно
|
||||
- Для одного Telegram гонять весь трафик через VPN — оверкилл
|
||||
|
||||
Нужно решение, которое **маскирует сам факт подключения к Telegram**, а не просто прячет протокол.
|
||||
|
||||
## Идея: WebSocket-туннель через web.telegram.org
|
||||
|
||||
Я провёл серию тестов. Прямое подключение к серверам Telegram (149.154.167.51:443) — либо таймаут, либо 200+ мс. А вот `web.telegram.org` отвечает стабильно за 50–80 мс через HTTPS. Провайдер его не трогает — это же «обычный сайт».
|
||||
|
||||
И тут я полез в [документацию MTProto](https://core.telegram.org/mtproto/transports) и нашёл золотую жилу:
|
||||
|
||||
> **WebSocket:** Implementation of the WebSocket transport is pretty much the same as with TCP... all data received and sent through WebSocket messages is to be treated as a single duplex stream of bytes, just like with TCP.
|
||||
|
||||
Telegram **официально поддерживает WebSocket-транспорт**. Серверы `pluto.web.telegram.org`, `venus.web.telegram.org` и т.д. — это не просто веб-клиент. Это **полноценные точки входа в сеть Telegram** через WSS.
|
||||
|
||||
Схема:
|
||||
|
||||
```
|
||||
Telegram Desktop
|
||||
│
|
||||
▼ SOCKS5
|
||||
┌──────────────────┐
|
||||
│ TG Unblock │ 127.0.0.1:1080
|
||||
│ WS-прокси │
|
||||
└──────┬───────────┘
|
||||
│
|
||||
├── IP Telegram? ──► WSS к {dc}.web.telegram.org/apiws
|
||||
│ (провайдер видит: HTTPS к web.telegram.org)
|
||||
│
|
||||
└── Другой IP? ────► Прямой TCP (без изменений)
|
||||
```
|
||||
|
||||
Провайдер видит:
|
||||
- Соединение к `venus.web.telegram.org` по порту 443
|
||||
- Обычный TLS/HTTPS трафик
|
||||
- Никакого MTProto
|
||||
|
||||
DPI видит:
|
||||
- Ничего подозрительного
|
||||
- Обычный WebSocket внутри HTTPS
|
||||
|
||||
Результат:
|
||||
- **Полная скорость** — провайдер не шейпит web.telegram.org
|
||||
- **Нет переподключений** — DPI не трогает HTTPS
|
||||
- **Нулевая задержка** — нет промежуточных серверов, трафик идёт напрямую к Telegram
|
||||
|
||||
## Реализация: Rust, SOCKS5, WebSocket
|
||||
|
||||
### Почему Rust?
|
||||
|
||||
Не Electron. Не Python. Не Node.js. **Rust.** Потому что:
|
||||
- Один бинарник ~6 МБ, без зависимостей
|
||||
- Нативная скорость — прокси не должен добавлять задержку
|
||||
- Async I/O через tokio — тысячи одновременных соединений
|
||||
- Компилируется, запускается, работает
|
||||
|
||||
### Архитектура
|
||||
|
||||
Приложение состоит из 4 модулей:
|
||||
|
||||
| Модуль | Что делает |
|
||||
|---|---|
|
||||
| `main.rs` | GUI на egui + управление прокси |
|
||||
| `ws_proxy.rs` | SOCKS5-сервер + WebSocket-туннель |
|
||||
| `bypass.rs` | DNS-настройка, системные утилиты |
|
||||
| `network.rs` | Сетевая диагностика |
|
||||
|
||||
### SOCKS5 → WebSocket: как это работает
|
||||
|
||||
Когда Telegram Desktop подключается через SOCKS5-прокси, происходит следующее:
|
||||
|
||||
**1. SOCKS5 handshake**
|
||||
|
||||
```rust
|
||||
// Клиент: [0x05, 0x01, 0x00] — SOCKS5, 1 метод, no auth
|
||||
// Сервер: [0x05, 0x00] — принято
|
||||
// Клиент: [0x05, 0x01, 0x00, 0x01, IP, PORT] — CONNECT к IP:PORT
|
||||
```
|
||||
|
||||
**2. Определение DC по IP**
|
||||
|
||||
Telegram использует фиксированные подсети для каждого Data Center. Из [документации](https://core.telegram.org/mtproto/transports):
|
||||
|
||||
```rust
|
||||
fn telegram_dc(ip: Ipv4Addr) -> Option<u8> {
|
||||
let o = ip.octets();
|
||||
match (o[0], o[1]) {
|
||||
(149, 154) => Some(match o[2] {
|
||||
160..=163 => 1, // DC1
|
||||
164..=167 => 2, // DC2
|
||||
168..=171 => 3, // DC3
|
||||
172..=175 => 1, // DC1 alt
|
||||
_ => 2,
|
||||
}),
|
||||
(91, 108) => Some(match o[2] {
|
||||
56..=59 => 5, // DC5
|
||||
8..=11 => 3, // DC3
|
||||
12..=15 => 4, // DC4
|
||||
_ => 2,
|
||||
}),
|
||||
(91, 105) => Some(2),
|
||||
(185, 76) => Some(2),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**3. WebSocket-туннель**
|
||||
|
||||
Каждый DC имеет именованный WebSocket-эндпоинт (имена из официальной документации Telegram):
|
||||
|
||||
| DC | Имя | URL |
|
||||
|---|---|---|
|
||||
| 1 | Pluto | `wss://pluto.web.telegram.org/apiws` |
|
||||
| 2 | Venus | `wss://venus.web.telegram.org/apiws` |
|
||||
| 3 | Aurora | `wss://aurora.web.telegram.org/apiws` |
|
||||
| 4 | Vesta | `wss://vesta.web.telegram.org/apiws` |
|
||||
| 5 | Flora | `wss://flora.web.telegram.org/apiws` |
|
||||
|
||||
Обязательный заголовок (из доки Telegram): `Sec-WebSocket-Protocol: binary`.
|
||||
|
||||
```rust
|
||||
let mut request = ws_url.as_str().into_client_request()?;
|
||||
request.headers_mut().insert(
|
||||
"Sec-WebSocket-Protocol", "binary".parse()?,
|
||||
);
|
||||
|
||||
let (ws, _) = tokio_tungstenite::connect_async_tls_with_config(
|
||||
request, None, false, Some(connector),
|
||||
).await?;
|
||||
```
|
||||
|
||||
**4. Двунаправленный relay**
|
||||
|
||||
Ключевая цитата из документации Telegram:
|
||||
|
||||
> All data received and sent through WebSocket messages is to be treated as a **single duplex stream of bytes**, just like with TCP.
|
||||
|
||||
Это значит, что нам не нужно парсить MTProto. Просто relay байтов: TCP → WebSocket binary frame, WebSocket binary frame → TCP.
|
||||
|
||||
```rust
|
||||
let up = async {
|
||||
let mut buf = vec![0u8; 32768];
|
||||
loop {
|
||||
match tcp_rx.read(&mut buf).await {
|
||||
Ok(0) => break,
|
||||
Ok(n) => {
|
||||
let msg = Message::Binary(buf[..n].to_vec());
|
||||
if ws_tx.send(msg).await.is_err() { break; }
|
||||
}
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let down = async {
|
||||
while let Some(Ok(msg)) = ws_rx.next().await {
|
||||
if let Message::Binary(data) = msg {
|
||||
if tcp_tx.write_all(&data).await.is_err() { break; }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tokio::select! { _ = up => {}, _ = down => {} }
|
||||
```
|
||||
|
||||
### GUI: egui, не Electron
|
||||
|
||||
Нативный GUI через `egui` / `eframe`. Никакого браузера, никакого DOM, никакого JavaScript. Вся отрисовка — immediate mode, 60 FPS.
|
||||
|
||||
Кнопка «Запустить обход» делает:
|
||||
1. Меняет DNS на Cloudflare (1.1.1.1) — обходит DNS-блокировку
|
||||
2. Запускает SOCKS5-прокси на 127.0.0.1:1080
|
||||
3. Предлагает автонастройку Telegram через `tg://socks?server=127.0.0.1&port=1080`
|
||||
|
||||
Кнопка «Настроить автоматически» — открывает Telegram Desktop с готовой конфигурацией прокси. Один клик.
|
||||
|
||||
## Технические детали, которые пришлось решить
|
||||
|
||||
### Проблема 1: Не-Telegram трафик
|
||||
|
||||
Если Telegram Desktop пускает через SOCKS5 не только MTProto, но и запросы к CDN, стикер-серверам, обновлениям — их нельзя заворачивать в WebSocket. Решение: проверяем IP по маппингу Telegram-подсетей. Telegram IP → WebSocket. Всё остальное → прямой TCP passthrough.
|
||||
|
||||
### Проблема 2: Определение DC
|
||||
|
||||
Telegram Desktop использует obfuscated2 транспорт. Первые 64 байта — зашифрованный хендшейк, в котором закодирован DC ID. Парсить его — целый проект.
|
||||
|
||||
Решение проще: определяем DC по destination IP. Telegram использует фиксированные подсети для каждого DC — маппинг стабильный и документированный.
|
||||
|
||||
### Проблема 3: TLS к WebSocket-эндпоинтам
|
||||
|
||||
WebSocket-соединение идёт через WSS (TLS). Используем `native-tls` — системные сертификаты Windows, без привязки к OpenSSL.
|
||||
|
||||
```rust
|
||||
let connector = tokio_tungstenite::Connector::NativeTls(
|
||||
native_tls::TlsConnector::new()?,
|
||||
);
|
||||
```
|
||||
|
||||
### Проблема 4: Graceful shutdown
|
||||
|
||||
При остановке прокси нужно:
|
||||
- Сбросить DNS обратно на DHCP
|
||||
- Корректно закрыть все WebSocket-соединения
|
||||
- Не оставить Telegram без связи
|
||||
|
||||
Используем `AtomicBool` для флага остановки — все задачи проверяют его и завершаются.
|
||||
|
||||
## Сравнение с альтернативами
|
||||
|
||||
| | GoodbyeDPI | Zapret | VPN | **TG Unblock** |
|
||||
|---|---|---|---|---|
|
||||
| Подход | Фрагментация пакетов | Desync пакетов | Туннель через сервер | WebSocket-туннель |
|
||||
| DPI видит MTProto? | Нет | Нет | Нет | **Нет** |
|
||||
| IP-шейпинг? | Не обходит | Не обходит | Обходит | **Обходит** |
|
||||
| Нужен сервер? | Нет | Нет | Да | **Нет** |
|
||||
| Скорость | Зависит от DPI | Зависит от DPI | Зависит от сервера | **Полная** |
|
||||
| Весь трафик? | Нет | Нет | Да | **Только Telegram** |
|
||||
| Стоимость | Бесплатно | Бесплатно | $3–10/мес | **Бесплатно** |
|
||||
|
||||
## Стек
|
||||
|
||||
| Технология | Зачем |
|
||||
|---|---|
|
||||
| **Rust** | Скорость, один бинарник, без зависимостей |
|
||||
| **egui / eframe** | Нативный GUI без браузера |
|
||||
| **tokio** | Async I/O, тысячи соединений |
|
||||
| **tokio-tungstenite** | WebSocket-клиент с TLS |
|
||||
| **native-tls** | Системные сертификаты Windows |
|
||||
| **GitHub Actions** | CI/CD — автобилд при новом теге |
|
||||
|
||||
## Цифры
|
||||
|
||||
- **5 DC** — полный маппинг всех Telegram Data Center
|
||||
- **1 бинарник** — ~6 МБ, без зависимостей
|
||||
- **0 серверов** — всё работает локально
|
||||
- **0₽** — полностью бесплатно и open-source
|
||||
- **1 клик** — от запуска до работающего Telegram
|
||||
|
||||
## Как попробовать
|
||||
|
||||
### Скачать готовый .exe
|
||||
|
||||
1. Скачайте `tg_unblock.exe` из [Releases](https://github.com/by-sonic/tglock/releases)
|
||||
2. Запустите (желательно от администратора — для DNS)
|
||||
3. Нажмите **«Запустить обход»**
|
||||
4. Нажмите **«Настроить автоматически»**
|
||||
5. В Telegram нажмите «Подключить»
|
||||
|
||||
### Собрать из исходников
|
||||
|
||||
```bash
|
||||
git clone https://github.com/by-sonic/tglock.git
|
||||
cd tglock
|
||||
cargo build --release
|
||||
# Бинарник: target/release/tg_unblock.exe
|
||||
```
|
||||
|
||||
## Что дальше
|
||||
|
||||
- **Автоопределение DC из obfuscated2** — парсинг первых 64 байт для точного маппинга
|
||||
- **Fallback на GoodbyeDPI** — если WebSocket-эндпоинт недоступен
|
||||
- **Linux / macOS** — porability через tokio + egui (уже почти готово)
|
||||
- **Статистика** — скорость, задержка, количество туннелей в реальном времени
|
||||
|
||||
## Вместо заключения
|
||||
|
||||
Telegram — это не просто мессенджер. Для миллионов людей это рабочий инструмент, канал связи, источник информации. Когда он работает через боль — страдают все.
|
||||
|
||||
GoodbyeDPI — отличный инструмент, но у него есть потолок. Когда DPI побеждён, а трафик всё равно шейпится — нужен другой подход. WebSocket-туннель через `web.telegram.org` — это как проехать мимо камеры на легальной машине вместо того, чтобы заклеивать номера.
|
||||
|
||||
Код полностью открыт. Если пригодился — поставьте звезду на GitHub. Если нашли баг — PR приветствуются.
|
||||
|
||||
**GitHub:** [github.com/by-sonic/tglock](https://github.com/by-sonic/tglock)
|
||||
|
||||
**P.S.** Если нужен полный обход блокировок для всех приложений (YouTube, Discord, Instagram и др.) — попробуйте [by sonic VPN](https://t.me/bysonicvpn_bot). Быстрый, стабильный, без ограничений скорости.
|
||||
|
||||
---
|
||||
|
||||
*by sonic*
|
||||
|
||||
**Теги:** telegram, dpi bypass, websocket, rust, socks5, mtproto, обход блокировок, open-source
|
||||
|
||||
**Хабы:** Rust · Open source · Windows · Сетевые технологии
|
||||
Loading…
Reference in New Issue