mirror of https://github.com/by-sonic/tglock.git
Compare commits
No commits in common. "main" and "v0.2.0" have entirely different histories.
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "tg_unblock"
|
||||
version = "0.3.1"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
|
@ -14,9 +14,6 @@ open = "5"
|
|||
tokio-tungstenite = { version = "0.24", features = ["native-tls"] }
|
||||
native-tls = "0.2"
|
||||
futures-util = "0.3"
|
||||
aes = "0.8"
|
||||
ctr = "0.9"
|
||||
cipher = "0.4"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["winuser"] }
|
||||
|
|
|
|||
307
HABR_ARTICLE.md
307
HABR_ARTICLE.md
|
|
@ -1,307 +0,0 @@
|
|||
# Как я написал обход блокировки 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 · Сетевые технологии
|
||||
76
src/main.rs
76
src/main.rs
|
|
@ -226,43 +226,7 @@ impl eframe::App for App {
|
|||
|
||||
// --- Main panel ---
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.add_space(10.0);
|
||||
|
||||
// --- VPN ad (top) ---
|
||||
ui.vertical_centered(|ui| {
|
||||
egui::Frame::new()
|
||||
.fill(egui::Color32::from_rgb(25, 30, 42))
|
||||
.corner_radius(8.0)
|
||||
.inner_margin(egui::Margin::symmetric(14, 8))
|
||||
.show(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.colored_label(
|
||||
egui::Color32::from_rgb(100, 180, 255),
|
||||
egui::RichText::new("by sonic VPN").size(13.0).strong(),
|
||||
);
|
||||
ui.label(
|
||||
egui::RichText::new("Полный обход для всех приложений")
|
||||
.size(12.0)
|
||||
.color(egui::Color32::from_rgb(160, 165, 180)),
|
||||
);
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.add(
|
||||
egui::Button::new(
|
||||
egui::RichText::new("@bysonicvpn_bot")
|
||||
.size(12.0)
|
||||
.strong()
|
||||
.color(egui::Color32::from_rgb(100, 200, 255)),
|
||||
)
|
||||
.frame(false),
|
||||
).clicked() {
|
||||
let _ = open::that("https://t.me/bysonicvpn_bot");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(12.0);
|
||||
ui.add_space(15.0);
|
||||
|
||||
ui.vertical_centered(|ui| {
|
||||
if !running {
|
||||
|
|
@ -351,6 +315,44 @@ impl eframe::App for App {
|
|||
"Не-Telegram трафик проходит напрямую без изменений",
|
||||
);
|
||||
|
||||
ui.add_space(12.0);
|
||||
ui.separator();
|
||||
ui.add_space(6.0);
|
||||
|
||||
// --- VPN ad ---
|
||||
egui::Frame::new()
|
||||
.fill(egui::Color32::from_rgb(30, 35, 50))
|
||||
.corner_radius(10.0)
|
||||
.inner_margin(14.0)
|
||||
.show(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.colored_label(
|
||||
egui::Color32::from_rgb(100, 180, 255),
|
||||
egui::RichText::new("by sonic VPN").size(16.0).strong(),
|
||||
);
|
||||
ui.label(egui::RichText::new(" — ").size(14.0));
|
||||
ui.label(
|
||||
egui::RichText::new("Полный обход блокировок для всех приложений")
|
||||
.size(13.0),
|
||||
);
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Быстрый VPN без ограничений скорости:");
|
||||
let link = ui.add(
|
||||
egui::Hyperlink::from_label_and_url(
|
||||
egui::RichText::new("@bysonicvpn_bot")
|
||||
.size(14.0)
|
||||
.strong()
|
||||
.color(egui::Color32::from_rgb(100, 200, 255)),
|
||||
"https://t.me/bysonicvpn_bot",
|
||||
),
|
||||
);
|
||||
if link.clicked() {
|
||||
let _ = open::that("https://t.me/bysonicvpn_bot");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
223
src/ws_proxy.rs
223
src/ws_proxy.rs
|
|
@ -36,6 +36,7 @@ pub async fn run_proxy(port: u16, stats: Arc<ProxyStats>) -> Result<(), String>
|
|||
if !stats.running.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
|
||||
tokio::select! {
|
||||
result = listener.accept() => {
|
||||
if let Ok((stream, _)) = result {
|
||||
|
|
@ -56,69 +57,18 @@ pub async fn run_proxy(port: u16, stats: Arc<ProxyStats>) -> Result<(), String>
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DC extraction from obfuscated2 init packet (same method as tg-ws-proxy)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
fn extract_dc_from_init(init: &[u8; 64]) -> Option<u8> {
|
||||
use aes::Aes256;
|
||||
use cipher::{KeyIvInit, StreamCipher};
|
||||
type Aes256Ctr = ctr::Ctr128BE<Aes256>;
|
||||
|
||||
let key = &init[8..40];
|
||||
let iv = &init[40..56];
|
||||
|
||||
let mut dec = [0u8; 64];
|
||||
dec.copy_from_slice(init);
|
||||
|
||||
let mut cipher = Aes256Ctr::new(key.into(), iv.into());
|
||||
cipher.apply_keystream(&mut dec);
|
||||
|
||||
let dc_id = i32::from_le_bytes([dec[60], dec[61], dec[62], dec[63]]);
|
||||
let dc = dc_id.unsigned_abs() as u8;
|
||||
if (1..=5).contains(&dc) {
|
||||
Some(dc)
|
||||
} else {
|
||||
None
|
||||
/// DC name mapping from official Telegram MTProto transport docs
|
||||
fn dc_ws_url(dc: u8) -> String {
|
||||
let name = match dc {
|
||||
1 => "pluto",
|
||||
2 => "venus",
|
||||
3 => "aurora",
|
||||
4 => "vesta",
|
||||
5 => "flora",
|
||||
_ => "venus",
|
||||
};
|
||||
format!("wss://{}.web.telegram.org/apiws", name)
|
||||
}
|
||||
}
|
||||
|
||||
fn dc_from_ip(ip: Ipv4Addr) -> Option<u8> {
|
||||
let o = ip.octets();
|
||||
match (o[0], o[1]) {
|
||||
(149, 154) => Some(match o[2] {
|
||||
160..=163 => 1,
|
||||
164..=167 => 2,
|
||||
168..=171 => 3,
|
||||
172..=175 => 1,
|
||||
_ => 2,
|
||||
}),
|
||||
(91, 108) => Some(match o[2] {
|
||||
56..=59 => 5,
|
||||
8..=11 => 3,
|
||||
12..=15 => 4,
|
||||
_ => 2,
|
||||
}),
|
||||
(91, 105) | (185, 76) => Some(2),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_telegram_ip(addr: &str) -> bool {
|
||||
addr.parse::<Ipv4Addr>()
|
||||
.ok()
|
||||
.and_then(dc_from_ip)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
/// Endpoint format used by the proven tg-ws-proxy project
|
||||
fn ws_url(dc: u8) -> String {
|
||||
format!("wss://kws{}.web.telegram.org/apiws", dc)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SOCKS5 handler
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async fn handle_socks5(
|
||||
mut stream: TcpStream,
|
||||
|
|
@ -126,7 +76,6 @@ async fn handle_socks5(
|
|||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
stream.set_nodelay(true)?;
|
||||
|
||||
// --- auth negotiation ---
|
||||
let mut buf = [0u8; 258];
|
||||
let n = stream.read(&mut buf).await?;
|
||||
if n < 2 || buf[0] != 0x05 {
|
||||
|
|
@ -134,7 +83,6 @@ async fn handle_socks5(
|
|||
}
|
||||
stream.write_all(&[0x05, 0x00]).await?;
|
||||
|
||||
// --- CONNECT request ---
|
||||
let n = stream.read(&mut buf).await?;
|
||||
if n < 7 || buf[0] != 0x05 || buf[1] != 0x01 {
|
||||
stream.write_all(&[0x05, 0x07, 0x00, 0x01, 0, 0, 0, 0, 0, 0]).await?;
|
||||
|
|
@ -142,47 +90,38 @@ async fn handle_socks5(
|
|||
}
|
||||
|
||||
let (dest_addr, dest_port) = parse_dest(&buf[3..n])?;
|
||||
let is_tg = is_telegram_ip(&dest_addr);
|
||||
|
||||
// SOCKS5 success (we handle the connection ourselves)
|
||||
let dc = dest_addr
|
||||
.parse::<Ipv4Addr>()
|
||||
.ok()
|
||||
.and_then(telegram_dc);
|
||||
|
||||
if let Some(dc_id) = dc {
|
||||
stream
|
||||
.write_all(&[0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x04, 0x38])
|
||||
.await?;
|
||||
|
||||
if is_tg {
|
||||
// Read the first 64 bytes — obfuscated2 init packet
|
||||
let mut init = [0u8; 64];
|
||||
stream.read_exact(&mut init).await?;
|
||||
|
||||
// Extract DC from init packet (primary), fall back to IP-based
|
||||
let dc = extract_dc_from_init(&init).unwrap_or_else(|| {
|
||||
dest_addr
|
||||
.parse::<Ipv4Addr>()
|
||||
.ok()
|
||||
.and_then(dc_from_ip)
|
||||
.unwrap_or(2)
|
||||
});
|
||||
|
||||
stats.ws_active.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
// Try WebSocket tunnel; fall back to direct TCP on failure
|
||||
let ws_result = relay_via_ws(stream, dc, &init).await;
|
||||
|
||||
let result = relay_via_ws(stream, dc_id).await;
|
||||
stats.ws_active.fetch_sub(1, Ordering::Relaxed);
|
||||
|
||||
if let Err(e) = ws_result {
|
||||
return Err(format!("DC{} tunnel: {}", dc, e).into());
|
||||
if let Err(e) = result {
|
||||
return Err(format!("WS tunnel DC{}: {}", dc_id, e).into());
|
||||
}
|
||||
} else {
|
||||
// Non-Telegram — direct TCP passthrough
|
||||
let target = format!("{}:{}", dest_addr, dest_port);
|
||||
match TcpStream::connect(&target).await {
|
||||
Ok(remote) => {
|
||||
let _ = remote.set_nodelay(true);
|
||||
stream
|
||||
.write_all(&[0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0])
|
||||
.await?;
|
||||
relay_tcp(stream, remote).await;
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!("TCP connect {}: {}", target, e).into());
|
||||
Err(_) => {
|
||||
stream
|
||||
.write_all(&[0x05, 0x05, 0x00, 0x01, 0, 0, 0, 0, 0, 0])
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -221,78 +160,98 @@ fn parse_dest(data: &[u8]) -> Result<(String, u16), Box<dyn std::error::Error +
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// WebSocket tunnel — reads init first, then relays
|
||||
// ---------------------------------------------------------------------------
|
||||
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,
|
||||
164..=167 => 2,
|
||||
168..=171 => 3,
|
||||
172..=175 => 1,
|
||||
_ => 2,
|
||||
}),
|
||||
(91, 108) => Some(match o[2] {
|
||||
56..=59 => 5,
|
||||
8..=11 => 3,
|
||||
12..=15 => 4,
|
||||
_ => 2,
|
||||
}),
|
||||
(91, 105) => Some(2),
|
||||
(185, 76) => Some(2),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn relay_via_ws(
|
||||
tcp_stream: TcpStream,
|
||||
dc: u8,
|
||||
init: &[u8; 64],
|
||||
dc_id: u8,
|
||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
|
||||
let url = ws_url(dc);
|
||||
let mut request = url.as_str().into_client_request()?;
|
||||
let ws_url = dc_ws_url(dc_id);
|
||||
let mut request = ws_url.as_str().into_client_request()?;
|
||||
|
||||
request
|
||||
.headers_mut()
|
||||
.insert("Sec-WebSocket-Protocol", "binary".parse()?);
|
||||
// Required by the Telegram WebSocket transport protocol
|
||||
request.headers_mut().insert(
|
||||
"Sec-WebSocket-Protocol",
|
||||
"binary".parse()?,
|
||||
);
|
||||
request.headers_mut().insert(
|
||||
"Origin",
|
||||
"https://web.telegram.org".parse()?,
|
||||
);
|
||||
|
||||
let connector = tokio_tungstenite::Connector::NativeTls(
|
||||
native_tls::TlsConnector::new().map_err(|e| format!("TLS: {}", e))?,
|
||||
);
|
||||
|
||||
let (mut ws, _resp) = tokio_tungstenite::connect_async_tls_with_config(
|
||||
request, None, false, Some(connector),
|
||||
let (ws, _resp) = tokio_tungstenite::connect_async_tls_with_config(
|
||||
request,
|
||||
None,
|
||||
false,
|
||||
Some(connector),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (mut ws_tx, mut ws_rx) = ws.split();
|
||||
let (mut tcp_rx, mut tcp_tx) = tokio::io::split(tcp_stream);
|
||||
|
||||
// Send the buffered 64-byte init as the first WebSocket message
|
||||
ws.send(tungstenite::Message::Binary(init.to_vec())).await?;
|
||||
|
||||
// Single loop: handles TCP→WS, WS→TCP, and Ping/Pong in one place.
|
||||
// This ensures Pong replies are sent immediately so the server
|
||||
// doesn't kill the connection after a timeout.
|
||||
let up = async {
|
||||
let mut buf = vec![0u8; 32768];
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
biased;
|
||||
|
||||
ws_msg = ws.next() => {
|
||||
match ws_msg {
|
||||
Some(Ok(tungstenite::Message::Binary(data))) => {
|
||||
if tcp_tx.write_all(data.as_ref()).await.is_err() {
|
||||
match tcp_rx.read(&mut buf).await {
|
||||
Ok(0) => break,
|
||||
Ok(n) => {
|
||||
let msg = tungstenite::Message::Binary(buf[..n].to_vec());
|
||||
if ws_tx.send(msg).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Some(Ok(tungstenite::Message::Ping(payload))) => {
|
||||
let _ = ws.send(tungstenite::Message::Pong(payload)).await;
|
||||
Err(_) => break,
|
||||
}
|
||||
Some(Ok(tungstenite::Message::Close(_))) | None => break,
|
||||
Some(Err(_)) => break,
|
||||
}
|
||||
let _ = ws_tx.close().await;
|
||||
};
|
||||
|
||||
let down = async {
|
||||
while let Some(Ok(msg)) = ws_rx.next().await {
|
||||
match msg {
|
||||
tungstenite::Message::Binary(data) => {
|
||||
if tcp_tx.write_all(&data).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tungstenite::Message::Close(_) => break,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
n = tcp_rx.read(&mut buf) => {
|
||||
match n {
|
||||
Ok(0) | Err(_) => break,
|
||||
Ok(n) => {
|
||||
let msg = tungstenite::Message::Binary(buf[..n].to_vec());
|
||||
if ws.send(msg).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tokio::select! {
|
||||
_ = up => {}
|
||||
_ = down => {}
|
||||
}
|
||||
|
||||
let _ = ws.close(None).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
418
РЕШЕНИЯ.md
418
РЕШЕНИЯ.md
|
|
@ -1,418 +0,0 @@
|
|||
# Решения задач по теории вероятностей
|
||||
## Формулы Бернулли, местная и интегральная теоремы Муавра–Лапласа, формула Пуассона
|
||||
|
||||
---
|
||||
|
||||
## Задача 3
|
||||
|
||||
**Условие:** В среднем каждое второе малое предприятие имеет нарушение финансовой дисциплины. Из **n = 1000** предприятий найти вероятность того, что нарушения имеют:
|
||||
|
||||
Дано: n = 1000, p = 1/2 = 0,5, q = 0,5
|
||||
npq = 1000 · 0,5 · 0,5 = 250, √(npq) = √250 ≈ 15,81
|
||||
|
||||
---
|
||||
|
||||
### а) Ровно 480 предприятий
|
||||
|
||||
Используем **местную теорему Муавра–Лапласа**:
|
||||
|
||||
$$P_n(k) \approx \frac{1}{\sqrt{npq}} \cdot \varphi(x), \quad x = \frac{k - np}{\sqrt{npq}}$$
|
||||
|
||||
$$x = \frac{480 - 500}{15{,}81} = \frac{-20}{15{,}81} \approx -1{,}26$$
|
||||
|
||||
φ(1,26) = 0,1826 (по таблице функции Гаусса)
|
||||
|
||||
$$P_{1000}(480) \approx \frac{0{,}1826}{15{,}81} \approx \mathbf{0{,}0116}$$
|
||||
|
||||
---
|
||||
|
||||
### б) Наивероятнейшее число предприятий
|
||||
|
||||
По формуле: **np − q ≤ k₀ ≤ np + p**
|
||||
|
||||
499,5 ≤ k₀ ≤ 500,5 → **k₀ = 500**
|
||||
|
||||
---
|
||||
|
||||
### в) Не менее 480 предприятий
|
||||
|
||||
Используем **интегральную теорему Муавра–Лапласа**:
|
||||
|
||||
$$P(k \geq 480) = 0{,}5 + \Phi\!\left(\frac{np - k_1}{\sqrt{npq}}\right)$$
|
||||
|
||||
$$= 0{,}5 + \Phi(1{,}26) = 0{,}5 + 0{,}3962 \approx \mathbf{0{,}8962}$$
|
||||
|
||||
---
|
||||
|
||||
### г) От 480 до 520 предприятий
|
||||
|
||||
$$x_1 = \frac{480 - 500}{15{,}81} \approx -1{,}26, \quad x_2 = \frac{520 - 500}{15{,}81} \approx 1{,}26$$
|
||||
|
||||
$$P(480 \leq k \leq 520) = \Phi(1{,}26) - \Phi(-1{,}26) = 2\Phi(1{,}26) = 2 \cdot 0{,}3962 \approx \mathbf{0{,}7924}$$
|
||||
|
||||
---
|
||||
|
||||
## Задача 4
|
||||
|
||||
**Условие:** Вероятность банкротства предприятия за время t равна 0,2. Из **n = 6** предприятий найти вероятность того, что **сохранятся**:
|
||||
|
||||
Дано: n = 6, p(сохранится) = 1 − 0,2 = **0,8**, q = 0,2
|
||||
|
||||
Используем **формулу Бернулли**: P_n(k) = C(n,k) · pᵏ · qⁿ⁻ᵏ
|
||||
|
||||
---
|
||||
|
||||
### а) Два предприятия (k = 2)
|
||||
|
||||
$$P_6(2) = C_6^2 \cdot (0{,}8)^2 \cdot (0{,}2)^4 = 15 \cdot 0{,}64 \cdot 0{,}0016 = \mathbf{0{,}0154}$$
|
||||
|
||||
---
|
||||
|
||||
### б) Более двух предприятий (k > 2)
|
||||
|
||||
$$P(k > 2) = 1 - P(k \leq 2) = 1 - [P(0) + P(1) + P(2)]$$
|
||||
|
||||
- P₆(0) = C(6,0) · (0,8)⁰ · (0,2)⁶ = 1 · 1 · 0,000064 = 0,000064
|
||||
- P₆(1) = C(6,1) · (0,8)¹ · (0,2)⁵ = 6 · 0,8 · 0,00032 = 0,001536
|
||||
- P₆(2) = 0,0154 (вычислено выше)
|
||||
|
||||
$$P(k > 2) = 1 - (0{,}000064 + 0{,}001536 + 0{,}0154) \approx 1 - 0{,}0170 = \mathbf{0{,}983}$$
|
||||
|
||||
---
|
||||
|
||||
## Задача 5
|
||||
|
||||
**Условие:** В банк отправлено **n = 4000** пакетов. Вероятность ошибки в комплектации **p = 0,0001**. Найти вероятность обнаружения:
|
||||
|
||||
λ = np = 4000 · 0,0001 = **0,4**
|
||||
|
||||
Используем **формулу Пуассона**: P(k) = (λᵏ / k!) · e⁻λ
|
||||
|
||||
e⁻⁰·⁴ ≈ 0,6703
|
||||
|
||||
---
|
||||
|
||||
### а) Три ошибочно укомплектованных пакета (k = 3)
|
||||
|
||||
$$P(3) = \frac{(0{,}4)^3}{3!} \cdot e^{-0{,}4} = \frac{0{,}064}{6} \cdot 0{,}6703 \approx \mathbf{0{,}00715}$$
|
||||
|
||||
---
|
||||
|
||||
### б) Не более трёх пакетов (k ≤ 3)
|
||||
|
||||
$$P(k \leq 3) = P(0) + P(1) + P(2) + P(3)$$
|
||||
|
||||
- P(0) = e⁻⁰·⁴ = 0,6703
|
||||
- P(1) = 0,4 · e⁻⁰·⁴ = 0,2681
|
||||
- P(2) = (0,4²/2) · e⁻⁰·⁴ = 0,0536
|
||||
- P(3) = 0,00715
|
||||
|
||||
$$P(k \leq 3) = 0{,}6703 + 0{,}2681 + 0{,}0536 + 0{,}00715 \approx \mathbf{0{,}9992}$$
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Домашняя работа
|
||||
|
||||
---
|
||||
|
||||
## Задача 1 (ДЗ)
|
||||
|
||||
**Условие:** Вероятность попадания в цель р = 0,7. Из **n = 80** выстрелов — найти вероятность различных исходов.
|
||||
|
||||
Дано: n = 80, p = 0,7, q = 0,3
|
||||
np = 56, npq = 16,8, √(npq) ≈ 4,10
|
||||
|
||||
---
|
||||
|
||||
### а) Ровно 75 попаданий
|
||||
|
||||
$$x = \frac{75 - 56}{4{,}10} \approx 4{,}63$$
|
||||
|
||||
φ(4,63) ≈ 0,00002 (крайне малое значение)
|
||||
|
||||
$$P_{80}(75) \approx \frac{0{,}00002}{4{,}10} \approx \mathbf{0{,}000005} \approx 0$$
|
||||
|
||||
---
|
||||
|
||||
### б) Не менее 75 попаданий
|
||||
|
||||
$$x_1 = \frac{75 - 56}{4{,}10} \approx 4{,}63$$
|
||||
|
||||
$$P(k \geq 75) = 0{,}5 - \Phi(4{,}63) \approx 0{,}5 - 0{,}5 \approx \mathbf{0}$$
|
||||
|
||||
---
|
||||
|
||||
### в) Менее 75 попаданий
|
||||
|
||||
$$P(k < 75) = 1 - P(k \geq 75) \approx \mathbf{1}$$
|
||||
|
||||
---
|
||||
|
||||
### г) Не более 75 попаданий
|
||||
|
||||
$$P(k \leq 75) = P(k < 75) + P(k = 75) \approx 1 + 0 \approx \mathbf{1}$$
|
||||
|
||||
---
|
||||
|
||||
### д) Более 75 попаданий
|
||||
|
||||
$$P(k > 75) \approx \mathbf{0}$$
|
||||
|
||||
---
|
||||
|
||||
### е) Все 80 выстрелов
|
||||
|
||||
$$P_{80}(80) = (0{,}7)^{80} = e^{80 \ln 0{,}7} = e^{-28{,}5} \approx \mathbf{4{,}4 \times 10^{-13}}$$
|
||||
|
||||
---
|
||||
|
||||
## Задача 2 (ДЗ)
|
||||
|
||||
**Условие:** Вероятность выпуска сверла с браком p = 0,02. Сверла укладываются по 100 штук. Найти наименьшее количество добавочных сверл, чтобы с вероятностью **не менее 0,9** в коробке было **не менее 100 исправных**.
|
||||
|
||||
Пусть в коробке **n** сверл, p(исправное) = 0,98. Нужно: P(X ≥ 100) ≥ 0,9
|
||||
|
||||
$$P(X \geq 100) = 0{,}5 + \Phi\!\left(\frac{np - 100}{\sqrt{np \cdot 0{,}02}}\right) \geq 0{,}9$$
|
||||
|
||||
$$\Rightarrow \frac{0{,}98n - 100}{0{,}14\sqrt{n}} \geq 1{,}28$$
|
||||
|
||||
Подстановка t = √n: 0,98t² − 0,1792t − 100 ≥ 0
|
||||
|
||||
$$t = \frac{0{,}1792 + \sqrt{0{,}1792^2 + 4 \cdot 0{,}98 \cdot 100}}{2 \cdot 0{,}98} = \frac{0{,}179 + 19{,}80}{1{,}96} \approx 10{,}19$$
|
||||
|
||||
$$n \geq (10{,}19)^2 \approx 103{,}9 \Rightarrow n = 104$$
|
||||
|
||||
**Ответ:** нужно добавить **m = 104 − 100 = 4 сверла**
|
||||
|
||||
---
|
||||
|
||||
## Задача 3 (ДЗ)
|
||||
|
||||
**Условие:** Сколько изюминок в среднем должна содержать булочка, чтобы вероятность хотя бы одной изюминки была **не менее 0,99**?
|
||||
|
||||
Используем формулу Пуассона: P(X ≥ 1) = 1 − P(X = 0) = 1 − e⁻λ ≥ 0,99
|
||||
|
||||
$$e^{-\lambda} \leq 0{,}01 \Rightarrow \lambda \geq -\ln(0{,}01) = \ln 100 \approx 4{,}61$$
|
||||
|
||||
**Ответ:** в среднем в булочке должно быть **не менее 5 изюминок** (λ ≥ 4,61)
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Задача (Картофель)
|
||||
|
||||
**Условие:** В складе 20% клубней с пятнами. Отобрано **n = 9** клубней. p(без пятен) = 0,8, q = 0,2.
|
||||
|
||||
---
|
||||
|
||||
### а) Наивероятнейшее число клубней без пятен
|
||||
|
||||
np − q ≤ k₀ ≤ np + p
|
||||
9·0,8 − 0,2 ≤ k₀ ≤ 9·0,8 + 0,8
|
||||
**7,0 ≤ k₀ ≤ 8,0**
|
||||
|
||||
Так как оба конца — целые числа, оба значения k₀ = 7 и k₀ = 8 являются наивероятнейшими (с одинаковой вероятностью).
|
||||
|
||||
---
|
||||
|
||||
### б) Вероятность наивероятнейшего числа
|
||||
|
||||
$$P_9(7) = C_9^7 \cdot (0{,}8)^7 \cdot (0{,}2)^2 = 36 \cdot 0{,}2097 \cdot 0{,}04 \approx \mathbf{0{,}302}$$
|
||||
|
||||
$$P_9(8) = C_9^8 \cdot (0{,}8)^8 \cdot (0{,}2)^1 = 9 \cdot 0{,}1678 \cdot 0{,}2 \approx \mathbf{0{,}302}$$
|
||||
|
||||
P(7) = P(8) ≈ **0,302** — подтверждает, что оба значения равновероятны
|
||||
|
||||
---
|
||||
|
||||
## Задача (Событие А, k₀ = 20)
|
||||
|
||||
**Условие:** Вероятность события А в каждом испытании p = 0,7. Сколько испытаний нужно провести, чтобы **наивероятнейшее число** равнялось **20**?
|
||||
|
||||
np − q ≤ k₀ ≤ np + p, то есть при k₀ = 20:
|
||||
|
||||
$$0{,}7n - 0{,}3 \leq 20 \leq 0{,}7n + 0{,}7$$
|
||||
|
||||
Из левого неравенства: 0,7n ≤ 20,3 → **n ≤ 29**
|
||||
|
||||
Из правого неравенства: 0,7n ≥ 19,3 → **n ≥ 27,57 → n ≥ 28**
|
||||
|
||||
Проверка:
|
||||
- n = 28: np−q = 19,3, np+p = 20,3 → единственное целое k₀ = **20** ✓
|
||||
- n = 29: np−q = 20,0, np+p = 21,0 → k₀ = 20 или 21 (два наивероятнейших)
|
||||
|
||||
**Ответ: n = 28** (или n = 29, если допустимо два наивероятнейших значения)
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Задача 1 (Лотерея)
|
||||
|
||||
**Условие:** Вероятность выигрыша по одному билету p = 1/7. Имея **n = 7** билетов, найти вероятность выигрыша:
|
||||
|
||||
Используем **формулу Бернулли**
|
||||
|
||||
---
|
||||
|
||||
### а) По двум билетам (k = 2)
|
||||
|
||||
$$P_7(2) = C_7^2 \cdot \left(\frac{1}{7}\right)^2 \cdot \left(\frac{6}{7}\right)^5 = 21 \cdot \frac{1}{49} \cdot \frac{7776}{16807} = \frac{163296}{823543} \approx \mathbf{0{,}198}$$
|
||||
|
||||
---
|
||||
|
||||
### б) По трём билетам (k = 3)
|
||||
|
||||
$$P_7(3) = C_7^3 \cdot \left(\frac{1}{7}\right)^3 \cdot \left(\frac{6}{7}\right)^4 = 35 \cdot \frac{1}{343} \cdot \frac{1296}{2401} = \frac{45360}{823543} \approx \mathbf{0{,}055}$$
|
||||
|
||||
---
|
||||
|
||||
## Задача 2 (Мята, гербициды)
|
||||
|
||||
**Условие:** Повреждены гербицидами 15% растений мяты. Отобрано **n = 20** растений. p = 0,15, q = 0,85.
|
||||
|
||||
np − q ≤ k₀ ≤ np + p
|
||||
3 − 0,85 ≤ k₀ ≤ 3 + 0,15
|
||||
2,15 ≤ k₀ ≤ 3,15
|
||||
|
||||
**k₀ = 3** — наивероятнейшее число повреждённых растений
|
||||
|
||||
---
|
||||
|
||||
## Задача 3 (Сбербанк)
|
||||
|
||||
**Условие:** Два филиала. Филиал 1: n₁ = 120, p₁ = 0,94. Филиал 2: n₂ = 140, p₂ = 0,8. Найти наивероятнейшее число клиентов, снявших деньги.
|
||||
|
||||
**Филиал 1:** np₁ = 112,8; np₁ − q₁ = 112,74; np₁ + p₁ = 113,74 → **k₀₁ = 113**
|
||||
|
||||
**Филиал 2:** np₂ = 112,0; np₂ − q₂ = 111,8; np₂ + p₂ = 112,8 → **k₀₂ = 112**
|
||||
|
||||
**Ответ:** Первый филиал обслуживает больше клиентов, снявших деньги: **113 > 112**
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Задача (Событие А, 400 испытаний)
|
||||
|
||||
**Условие:** Найти вероятность того, что событие А наступит **ровно 80 раз** в 400 испытаниях, если p = 0,2.
|
||||
|
||||
Дано: n = 400, k = 80, p = 0,2, q = 0,8
|
||||
np = 80, npq = 64, √(npq) = 8
|
||||
|
||||
$$x = \frac{k - np}{\sqrt{npq}} = \frac{80 - 80}{8} = 0$$
|
||||
|
||||
$$\varphi(0) = \frac{1}{\sqrt{2\pi}} \approx 0{,}3989$$
|
||||
|
||||
$$P_{400}(80) \approx \frac{\varphi(0)}{\sqrt{npq}} = \frac{0{,}3989}{8} \approx \mathbf{0{,}0499}$$
|
||||
|
||||
---
|
||||
|
||||
## Задача (Стрелок)
|
||||
|
||||
**Условие:** Вероятность поражения мишени p = 0,75. При **n = 10** выстрелах найти вероятность **ровно 8 попаданий**.
|
||||
|
||||
$$P_{10}(8) = C_{10}^8 \cdot (0{,}75)^8 \cdot (0{,}25)^2$$
|
||||
|
||||
$$= 45 \cdot \frac{6561}{65536} \cdot \frac{1}{16} = \frac{295245}{1048576} \approx \mathbf{0{,}2816}$$
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Задача (Кинескопы — Интегральная теорема Лапласа)
|
||||
|
||||
**Условие:** 12% кинескопов не проработают гарантийный срок. Из **n = 50** наугад выбранных — найти вероятность того, что проработают гарантийный срок:
|
||||
|
||||
Дано: n = 50, p(проработает) = 1 − 0,12 = **0,88**, q = 0,12
|
||||
np = 44, npq = 50 · 0,88 · 0,12 = 5,28, √(npq) ≈ 2,298
|
||||
|
||||
---
|
||||
|
||||
### а) Ровно 47 кинескопов
|
||||
|
||||
Местная теорема:
|
||||
|
||||
$$x = \frac{47 - 44}{2{,}298} \approx 1{,}305, \quad \varphi(1{,}305) \approx 0{,}1714$$
|
||||
|
||||
$$P_{50}(47) \approx \frac{0{,}1714}{2{,}298} \approx \mathbf{0{,}0745}$$
|
||||
|
||||
---
|
||||
|
||||
### б) Не менее 47 кинескопов
|
||||
|
||||
$$x_1 = \frac{47 - 44}{2{,}298} \approx 1{,}305$$
|
||||
|
||||
$$P(k \geq 47) \approx 0{,}5 - \Phi(1{,}305) = 0{,}5 - 0{,}4040 \approx \mathbf{0{,}0960}$$
|
||||
|
||||
---
|
||||
|
||||
### в) Менее 47 кинескопов
|
||||
|
||||
$$P(k < 47) = 1 - P(k \geq 47) \approx 1 - 0{,}0960 = \mathbf{0{,}9040}$$
|
||||
|
||||
---
|
||||
|
||||
### г) Более 47 кинескопов
|
||||
|
||||
$$x = \frac{48 - 44}{2{,}298} \approx 1{,}740$$
|
||||
|
||||
$$P(k > 47) = P(k \geq 48) \approx 0{,}5 - \Phi(1{,}74) = 0{,}5 - 0{,}4591 \approx \mathbf{0{,}0409}$$
|
||||
|
||||
---
|
||||
|
||||
### д) Не более 47 кинескопов
|
||||
|
||||
$$P(k \leq 47) = 1 - P(k > 47) \approx 1 - 0{,}0409 = \mathbf{0{,}9591}$$
|
||||
|
||||
---
|
||||
|
||||
### е) Все 50 кинескопов
|
||||
|
||||
$$P_{50}(50) = (0{,}88)^{50} \approx \mathbf{0{,}00167}$$
|
||||
|
||||
(Для проверки по местной теореме: x = (50−44)/2,298 ≈ 2,61; φ(2,61) ≈ 0,0136; P ≈ 0,006 — приближение менее точно из-за удалённости от центра)
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Домашнее задание (Интегральная теорема Лапласа)
|
||||
|
||||
---
|
||||
|
||||
## Задача 1 (ДЗ — Новорождённые)
|
||||
|
||||
**Условие:** Среди **n = 1000** новорождённых. Вероятность рождения мальчика p = 0,51. Найти вероятность того, что мальчиков будет:
|
||||
|
||||
np = 510, npq = 1000 · 0,51 · 0,49 = 249,9, √(npq) ≈ 15,81
|
||||
|
||||
---
|
||||
|
||||
### а) Не менее половины (m ≥ 500)
|
||||
|
||||
$$x_1 = \frac{500 - 510}{15{,}81} \approx -0{,}63, \quad x_2 \to +\infty$$
|
||||
|
||||
$$P_{1000}(500 \leq m \leq 1000) \approx \Phi(+\infty) - \Phi(-0{,}63) = 0{,}5 - (-0{,}2357) = \mathbf{0{,}7357}$$
|
||||
|
||||
---
|
||||
|
||||
### б) Менее половины (m < 500, то есть m ≤ 499)
|
||||
|
||||
$$P_{1000}(0 \leq m \leq 499) = 1 - 0{,}7357 = \mathbf{0{,}2643}$$
|
||||
|
||||
---
|
||||
|
||||
## Задача 2 (ДЗ — Картофель при уборке)
|
||||
|
||||
**Условие:** При уборке повреждается в среднем 10% клубней. Из **n = 200** клубней найти вероятность того, что повреждено от 15 до 50 клубней.
|
||||
|
||||
Дано: n = 200, p = 0,10, q = 0,90
|
||||
np = 20, npq = 18, √(npq) ≈ 4,243
|
||||
|
||||
$$x_1 = \frac{15 - 20}{4{,}243} \approx -1{,}18, \quad x_2 = \frac{50 - 20}{4{,}243} \approx 7{,}07$$
|
||||
|
||||
$$P_{200}(15 \leq m \leq 50) \approx \Phi(7{,}07) - \Phi(-1{,}18) \approx 0{,}5 - (-0{,}3810) = 0{,}5 + 0{,}3810 \approx \mathbf{0{,}881}$$
|
||||
Loading…
Reference in New Issue