Как работают прокси с протоколом UDP и почему это важно для VoIP и стриминга
Содержание
- Прокси и UDP: почему TCP тут не катит
- Как устроен UDP-прокси
- Словарь для хранения клиентских сессий
- Новый клиент — создаём отдельный сокет
- SOCKS5 — единственный адекватный вариант
- curl с поддержкой SOCKS5
- А если нужно именно UDP — используем proxychains
- Почему обычные прокси убивают VoIP
- Стриминг и UDP: меньше буфера — быстрее реакция
- Как проверить, поддерживает ли прокси UDP
- SOCKS5 handshake
- Запрашиваем UDP ASSOCIATE
- Когда UDP-прокси нужен, а когда нет
- Настройка UDP-прокси на сервере
- Установка
- Конфиг
- SOCKS5 с UDP
- Аутентификация
- /etc/dante.conf
- Разрешаем UDP
- Подводные камни
- Итог
Прокси и UDP: почему TCP тут не катит
Большинство думает о прокси как о штуке для HTTP. Открыл браузер, вбил настройки — и погнал. Но есть целый пласт задач, где TCP-прокси ломаются об колено. VoIP-звонки, стриминг, онлайн-игры — всё это висит на UDP. И когда ты пытаешься пропихнуть UDP через обычный HTTP-прокси, начинается треш.
UDP — это про скорость и пофигизм. Отправил пакет — и забыл. Не надо ждать подтверждения, не надо пересылать потерянное. Для голоса или видео это идеально. Потерял пару миллисекунд звука — мозг сам дорисует. Потерял пару секунд на переотправку — получишь эхо и лаги.
Проблема в том, что 90% прокси-серверов заточены под TCP. Они тупо не понимают UDP-трафик. Пакет прилетает, прокси его роняет или пытается завернуть в TCP — и получается хреновый гибрид, который убивает всю магию UDP.
Как устроен UDP-прокси
Здесь всё хитрее, чем с TCP. Нет установки соединения, нет handshake'а. Прокси должен просто перекидывать датаграммы из точки А в точку Б, сохраняя их целостность и порядок (или хотя бы не мешая).
Базовая схема выглядит так:
1. Клиент шлёт UDP-пакет на адрес прокси
2. Прокси читает заголовок, смотрит куда адресован пакет
3. Меняет source-адрес на свой, destination оставляет как есть
4. Отправляет пакет дальше в интернет
5. Ответ ловит на свой сокет, перепаковывает обратно клиенту
В коде на Python это выглядит примерно так:
```python
import socket
def start_udp_proxy(local_host, local_port, remote_host, remote_port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((local_host, local_port))
Словарь для хранения клиентских сессий
sessions = {}
while True:
data, addr = sock.recvfrom(4096)
if addr not in sessions:
Новый клиент — создаём отдельный сокет
remote = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sessions[addr] = remote
else:
remote = sessions[addr]
remote.sendto(data, (remote_host, remote_port))
response, _ = remote.recvfrom(4096)
sock.sendto(response, addr)
```
Примитивно, но работает. На практике добавляют таймауты, очистку сессий, мультиплексирование.
SOCKS5 — единственный адекватный вариант
Если тебе нужен UDP через прокси — забудь про HTTP. SOCKS5 умеет UDP с рождения. Он не лезет в содержимое пакетов, просто перекидывает их.
Как это работает на клиенте:
```bash
curl с поддержкой SOCKS5
curl --socks5-hostname 127.0.0.1:1080 -U username:password https://example.com
А если нужно именно UDP — используем proxychains
proxychains4 -f proxychains.conf your_udp_app
```
Конфиг proxychains для UDP:
```
strict_chain
proxy_dns
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
socks5 127.0.0.1 1080 username password
```
SOCKS5 прокси держит отдельный UDP-ассоциатор. Клиент сообщает: "я буду слать UDP на такой-то хост". Прокси запоминает это и начинает пересылать датаграммы.
Почему обычные прокси убивают VoIP
Возьмём SIP + RTP. SIP — сигнализация, она может идти по TCP. А вот RTP — это чистый UDP. Голосовые пакеты летят каждые 20-30 миллисекунд.
Проблема классического HTTP-прокси:
1. Он ждёт установки TCP-соединения — это 1-2 RTT
2. Каждый пакет подтверждается — добавляет задержку
3. При потере пакета начинается retransmit — получаем заикание в голосе
Сравни задержки:
| Тип прокси | Средняя задержка | Джиттер | Потери пакетов |
|------------|------------------|---------|----------------|
| Без прокси | 5-10 мс | 2-3 мс | 0.1% |
| HTTP-proxy | 50-200 мс | 20-50 мс | 2-5% |
| SOCKS5 UDP | 10-30 мс | 5-10 мс | 0.5-1% |
| Прямой UDP-proxy | 5-15 мс | 3-5 мс | 0.2-0.5% |
Цифры говняные для HTTP, потому что он пытается эмулировать UDP через TCP. Это как гонять Формулу-1 по бездорожью.
Стриминг и UDP: меньше буфера — быстрее реакция
Для стриминга UDP даёт одну важную вещь — низкий latency. RTMP, WebRTC, SRT — все эти протоколы заточены под UDP.
Когда ты используешь прокси для стрима на Twitch или YouTube, каждый лишний миллисекунда превращается в задержку у зрителя. Если через TCP прокси ты получаешь 10 секунд задержки, то через UDP — 1-2 секунды.
Проблема стримеров из регионов с блокировками: они пытаются гнать RTMP через обычный прокси, получают адские лаги и думают, что проблема в канале. На самом деле проблема в протоколе.
Реальный кейс: стример из России гонит 1080p60 на Twitch. Через обычный HTTPS-прокси битрейт скачет от 2000 до 6000 kbps, фризы каждые 10 секунд. Переключились на SOCKS5 с UDP — битрейт стабильно 8000, фризы пропали.
Как проверить, поддерживает ли прокси UDP
Не все прокси, которые пишут "SOCKS5", реально умеют UDP. Бывает, что только TCP, а UDP — фикция.
Проверка через Python:
```python
import socket
def test_udp_proxy(proxy_host, proxy_port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
try:
sock.connect((proxy_host, proxy_port))
SOCKS5 handshake
sock.send(b'\x05\x01\x00')
resp = sock.recv(2)
if resp == b'\x05\x00':
Запрашиваем UDP ASSOCIATE
sock.send(b'\x05\x03\x00\x01' +
socket.inet_aton('0.0.0.0') +
(0).to_bytes(2, 'big'))
resp = sock.recv(10)
if resp[0] == b'\x05' and resp[1] == b'\x00':
print("UDP поддерживается")
return True
except:
print("UDP не поддерживается или прокси недоступен")
finally:
sock.close()
return False
```
Когда UDP-прокси нужен, а когда нет
Не везде UDP — серебряная пуля. Есть сценарии, где TCP прокси рулит.
UDP побеждает:
- VoIP и видеозвонки (WebRTC, SIP)
- Стриминг в реальном времени (OBS + RTMP)
- Онлайн-игры (FPS, MOBA)
- DNS-запросы (если не хочешь, чтобы их перехватывали)
- Торренты (DHT, uTP)
TCP остаётся королём:
- Веб-сёрфинг (HTTP/HTTPS)
- API-запросы (REST, GraphQL)
- Email (SMTP, IMAP)
- Файловые передачи (FTP, SFTP)
Смешанный сценарий: Discord использует и TCP, и UDP. TCP для текста и сигнализации, UDP для голоса. Если твой прокси не умеет UDP, голос будет с задержками или вообще не заработает.
Настройка UDP-прокси на сервере
Если ты админ и хочешь поднять UDP-прокси, забудь про Squid — он только TCP. Бери что-то специализированное.
Вариант на 3proxy:
```bash
Установка
wget https://github.com/3proxy/3proxy/archive/refs/tags/0.9.4.tar.gz
tar xzf 0.9.4.tar.gz
cd 3proxy-0.9.4
make -f Makefile.Linux
Конфиг
cat > /etc/3proxy/3proxy.cfg << EOF
nscache 65536
nserver 8.8.8.8
nserver 8.8.4.4
timeouts 1 5 30 60 180 1800 15 60
daemon
SOCKS5 с UDP
socks -p1080
allow * * * * 1-12/24
maxconn 100
Аутентификация
users username:CL:password
auth strong
EOF
```
Вариант на Dante — классика для SOCKS:
```bash
apt install dante-server
/etc/dante.conf
logoutput: /var/log/dante.log
internal: 0.0.0.0 port = 1080
external: eth0
socksmethod: username
user.privileged: root
user.unprivileged: nobody
Разрешаем UDP
client pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: error
}
socks pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
socksmethod: username
udp.associate
}
```
После настройки обязательно проверь через `nmap`, что порт 1080 открыт и UDP работает.
Подводные камни
UDP-прокси не лишён граблей. Вот основные:
**NAT и keepalive**. UDP-сессии живут недолго. Если клиент замолчал на 30 секунд, прокси может забыть о нём. Приходится слать keepalive-пакеты каждые 10-15 секунд.
**Фрагментация**. UDP-пакеты больше 1500 байт фрагментируются на уровне IP. Не все прокси умеют собирать фрагменты обратно. Решение — не слать пакеты больше MTU.
**Аутентификация**. Не все реализации SOCKS5 корректно обрабатывают UDP с аутентификацией. Некоторые просто игнорируют UDP-ассоциацию, если стоит логин/пароль.
**IPv6**. Многие UDP-прокси не умеют работать с IPv6. Если тебе нужно проксировать IPv6-трафик через UDP — ищи специализированное решение.
Например, на lexic.ml UDP-прокси работает и с IPv4, и с IPv6, но не все провайдеры это поддерживают. Приходится явно указывать протокол.
Итог
UDP-прокси — это не роскошь, а необходимость для всего, что требует реального времени. VoIP без него превращается в радио с помехами, стриминг — в слайд-шоу, игры — в лаг-фестиваль.
Если тебе нужно прокси для работы или развлечений — убедись, что оно умеет UDP. SOCKS5 — минимальный стандарт. Всё остальное — компромиссы, которые сожрут твой пинг и нервы.
Проверяй прокси перед покупкой, гоняй тесты с реальным трафиком, не верь обещаниям на сайтах. Только практика покажет, работает ли UDP так, как надо.