Знакомая ситуация: вы настроили прокси, браузер открывает сайты, парсер собирает данные, всё выглядит идеально. А потом вы запускаете видеозвонок, и собеседник вас не слышит. Или заходите в онлайн-игру, и матч не подключается. Или запускаете голосовой чат, и он молчит. Прокси ведь работает? Работает. Но что-то сломано на глубоком уровне, и понять это без знаний о транспорте практически невозможно.

Причина почти всегда одна и та же: ваш прокси не пропускает UDP-трафик. И это не поломка, а фундаментальное свойство. Одни типы прокси умеют работать с UDP по стандарту, другие не умеют в принципе. Разница между этими двумя мирами определяет, будет ли у вас работать реальное общение в интернете или только загрузка веб-страниц.

В этом руководстве мы разберём тему от самого фундамента до практических инструментов проверки. Вы узнаете, как устроена команда UDP ASSOCIATE в протоколе SOCKS5, почему HTTP-прокси через метод CONNECT не может передавать датаграммы физически, что именно ломается у пользователя без UDP и как самостоятельно, буквально за несколько минут, проверить любой прокси на реальную поддержку UDP. Мы будем говорить только о транспорте: без разбора выбора между типами прокси и без инструкций по настройке конкретных приложений.

Основы: TCP против UDP, датаграммы и уровень работы прокси

Чтобы понять, почему UDP так капризен в прокси-инфраструктуре, нужно вернуться к базовым понятиям транспортного уровня. Не пугайтесь: мы объясним всё простыми аналогиями.

Два транспортных протокола, две философии

В интернете данные передаются поверх двух основных транспортных протоколов: TCP (Transmission Control Protocol) и UDP (User Datagram Protocol). Оба работают поверх IP, но ведут себя абсолютно по-разному.

TCP напоминает телефонный разговор с постоянным подтверждением. Прежде чем начать обмен данными, две стороны устанавливают соединение через процедуру рукопожатия. Каждый отправленный пакет подтверждается получателем. Если что-то потерялось, оно переотправляется. Порядок пакетов гарантируется. Это надёжный, упорядоченный, но относительно медленный поток. TCP идеален для загрузки веб-страниц, скачивания файлов, отправки почты, то есть везде, где важна каждая порция данных и их правильный порядок.

UDP напоминает отправку открыток без уведомления о вручении. Вы бросаете датаграмму в сеть и не ждёте подтверждения. Нет установления соединения, нет гарантии доставки, нет гарантии порядка. Пакет может потеряться, прийти дважды или в перепутанном порядке, и протокол этим не озаботится. Звучит как недостаток? Только на первый взгляд. Именно эта простота даёт UDP главное преимущество: скорость и минимальную задержку.

Что такое датаграмма

Датаграмма это самостоятельная порция данных в UDP. В отличие от TCP, где данные текут непрерывным потоком байтов, в UDP каждый пакет самодостаточен. Он содержит адрес назначения, порт и полезную нагрузку. Датаграмма не знает ничего о датаграммах, отправленных до неё или после. Это как отдельные письма без нумерации в общей переписке.

Почему это важно для нашей темы? Потому что прокси, который умеет пересылать непрерывный поток TCP, совершенно не обязательно умеет пересылать разрозненные самостоятельные датаграммы UDP. Это принципиально разные задачи с точки зрения реализации.

Где именно в цепочке живёт прокси

Представим сетевую модель как этажи здания. На нижних этажах физическая передача сигналов и IP-адресация. Выше транспортный уровень с TCP и UDP. Ещё выше прикладной уровень с HTTP, DNS, протоколами звонков.

Прокси-сервер это посредник, который стоит между вами и целевым ресурсом. Но на каком именно уровне он работает, зависит от его типа. И вот здесь начинается самое интересное.

  • HTTP-прокси изначально понимает прикладной уровень HTTP. Он читает HTTP-запросы, видит заголовки, умеет их модифицировать и кешировать. Это прокси, заточенный под конкретный прикладной протокол поверх TCP.
  • SOCKS-прокси работает ниже, ближе к транспортному уровню. Он не вникает в содержимое прикладного протокола, а просто пересылает соединения. Именно поэтому SOCKS универсальнее: ему всё равно, что вы передаёте, HTTP или что-то экзотическое.

Эта разница в уровне работы и есть корень всей истории. HTTP-прокси заперт в мире HTTP поверх TCP. SOCKS5 задуман как универсальный транспортный посредник, и именно поэтому в его спецификацию вписали механизм передачи UDP.

Глубокое погружение: как SOCKS5 передаёт UDP

Протокол SOCKS5 описан в стандарте RFC 1928. Это компактный, элегантный протокол, и понять его логику стоит каждому, кто серьёзно работает с прокси. Давайте разберём его команды и особое устройство UDP-передачи.

Три команды SOCKS5: CONNECT, BIND, UDP ASSOCIATE

После того как клиент подключился к SOCKS5-серверу и прошёл этап аутентификации, он отправляет запрос с одной из трёх команд. Каждая команда задаёт, какой тип операции нужен.

  • CONNECT (код 0x01) самая распространённая команда. Она говорит прокси: установи для меня исходящее TCP-соединение к указанному адресу и порту, а затем пересылай байты в обе стороны. Именно эту команду использует ваш браузер, когда ходит в интернет через SOCKS5. 99% повседневного трафика идёт через CONNECT.
  • BIND (код 0x02) команда для входящих соединений. Она нужна протоколам вроде классического FTP, где сервер сам инициирует обратное подключение к клиенту. Прокси открывает слушающий порт и ждёт входящее соединение. Сегодня BIND используется редко.
  • UDP ASSOCIATE (код 0x03) звезда нашего разговора. Эта команда создаёт ассоциацию для передачи UDP-датаграмм через прокси. Именно она позволяет SOCKS5 работать с голосом, видео, играми, QUIC и DNS поверх UDP.

Как устроена UDP ASSOCIATE изнутри

Вот здесь кроется красивый архитектурный трюк, который часто вызывает недопонимание. Команда UDP ASSOCIATE отправляется по TCP-соединению. Да, вы не ослышались: чтобы начать передавать UDP, клиент устанавливает управляющее TCP-соединение с прокси и отправляет по нему команду.

Зачем нужно управляющее TCP-соединение, если мы хотим передавать UDP? Причин несколько, и они гениальны в своей практичности.

  1. По TCP надёжно проходит аутентификация и согласование параметров. UDP для этого не годится, так как ненадёжен.
  2. Управляющее TCP-соединение служит индикатором жизни UDP-ассоциации. Пока TCP-соединение открыто, UDP-ассоциация действует. Как только клиент закрывает управляющее TCP-соединение, прокси обязан немедленно освободить ресурсы и прекратить пересылку датаграмм. Это элегантный способ управления временем жизни.

После получения команды UDP ASSOCIATE прокси-сервер выделяет специальный relay-порт для UDP и сообщает клиенту его адрес и номер в ответе. Именно на этот relay-порт клиент будет слать свои датаграммы, а прокси будет пересылать их дальше к цели и возвращать ответы обратно.

Роль relay-порта и адреса привязки

В ответе на UDP ASSOCIATE сервер возвращает поля BND.ADDR и BND.PORT. Это адрес и порт, на которые клиент должен направлять свои UDP-датаграммы для ретрансляции. Важный нюанс: адрес в ответе может отличаться от адреса, к которому клиент подключился по TCP. Грамотный клиент должен корректно интерпретировать этот адрес, особенно когда сервер возвращает нулевой адрес, означающий использовать тот же хост, что и для управляющего соединения.

Именно на этом этапе спотыкаются многие реализации. Неправильная обработка BND.ADDR приводит к тому, что клиент шлёт датаграммы не туда, и UDP-передача молча не работает, хотя формально ассоциация установлена.

Формат инкапсуляции UDP-датаграммы в SOCKS5

Просто так отправить UDP-датаграмму на relay-порт нельзя. Прокси должен знать, куда её переслать дальше. Поэтому каждая UDP-датаграмма, отправляемая клиентом на relay-порт, оборачивается в специальный заголовок SOCKS5. Разберём его по полям, потому что понимание этой структуры отличает того, кто действительно разбирается в теме.

Заголовок UDP-инкапсуляции состоит из следующих полей:

  • RSV (2 байта) зарезервированное поле, всегда заполняется нулями. Оставлено на будущее, но пока не используется.
  • FRAG (1 байт) номер фрагмента. Это поле предназначено для фрагментации больших датаграмм. Значение 0 означает, что датаграмма стоит отдельно и не фрагментирована. На практике фрагментацию UDP через SOCKS5 почти никто не реализует, и большинство серверов и клиентов работают только с FRAG равным нулю.
  • ATYP (1 байт) тип адреса назначения. Может быть 0x01 для IPv4, 0x03 для доменного имени, 0x04 для IPv6. Это поле сообщает прокси, в каком формате читать следующее поле адреса.
  • DST.ADDR (переменная длина) адрес назначения датаграммы. Его длина зависит от ATYP: 4 байта для IPv4, 16 байт для IPv6, а для доменного имени первый байт задаёт длину, за которым следует само имя.
  • DST.PORT (2 байта) порт назначения в сетевом порядке байтов.
  • DATA собственно полезная нагрузка, то есть исходная UDP-датаграмма приложения.

Когда прокси получает такую обёрнутую датаграмму на relay-порт, он снимает заголовок SOCKS5, читает адрес и порт назначения и отправляет чистую полезную нагрузку по назначению уже как обычный UDP-пакет. Когда приходит ответ, прокси делает обратную операцию: оборачивает ответную датаграмму в такой же заголовок и шлёт клиенту на relay-порт.

Обратите внимание на изящество схемы. Клиент никогда не общается с целью напрямую по UDP. Всё проходит через relay-порт прокси, а заголовок инкапсуляции служит адресной этикеткой. Это надёжный и стандартизированный способ переносить разрозненные датаграммы через посредника.

Почему поле FRAG чаще всего мёртвое

Стоит остановиться на фрагментации отдельно. Теоретически SOCKS5 позволяет разбивать большие UDP-датаграммы на фрагменты и собирать их на стороне прокси. На практике это создаёт огромную сложность: нужно буферизовать фрагменты, обрабатывать таймауты сборки, защищаться от атак. Поэтому подавляющее большинство реализаций просто требуют FRAG равным нулю и отбрасывают всё остальное. Для приложений это означает: датаграмма должна помещаться в один пакет. К счастью, большинство реальных протоколов, использующих UDP, и так работают с небольшими датаграммами.

Почему HTTP и HTTPS-прокси через CONNECT не могут передавать UDP

Теперь мы подошли к вопросу, который вызывает больше всего заблуждений. Люди часто думают: раз HTTPS-прокси умеет туннелировать зашифрованный трафик через метод CONNECT, значит он универсален и должен уметь UDP. Это ошибка, и сейчас мы объясним, почему она принципиальна.

Как работает метод CONNECT в HTTP-прокси

Когда браузер идёт через HTTP-прокси на защищённый сайт, он не может просто передать HTTP-запрос, потому что содержимое зашифровано. Вместо этого он отправляет прокси специальную команду CONNECT с указанием хоста и порта. Прокси устанавливает TCP-соединение к этому хосту и после успеха отвечает статусом об установлении туннеля. Дальше прокси просто перекачивает байты между клиентом и сервером в обе стороны, не вникая в содержимое.

Ключевое слово здесь TCP. Метод CONNECT по своей спецификации создаёт именно TCP-туннель. Он открывает потоковое TCP-соединение и связывает два потока байтов. В самом определении CONNECT нет никакого механизма для работы с датаграммами.

Три фундаментальные причины несовместимости

Разберём по пунктам, почему это не техническая недоработка, а концептуальная невозможность.

  1. CONNECT завязан на потоковую модель. HTTP это протокол поверх TCP. Метод CONNECT наследует эту потоковую природу. Он умеет связывать два TCP-потока, но UDP это не поток, а набор независимых датаграмм. Между ними нет соответствия. Нельзя запихнуть множество разрозненных датаграмм с разными адресами назначения в единственный TCP-туннель без дополнительного протокола инкапсуляции, которого в HTTP CONNECT просто нет.
  2. Нет механизма адресации датаграмм. В UDP каждая датаграмма может лететь к своему адресу и порту. Голосовое приложение может одновременно общаться с несколькими серверами. TCP-туннель CONNECT связывает вас с одним конкретным адресом, заданным в момент установления. Он не предусматривает поля для указания адреса назначения каждой отдельной датаграммы, в отличие от SOCKS5 с его заголовком инкапсуляции DST.ADDR и DST.PORT.
  3. Нет relay-порта для UDP. SOCKS5 специально выделяет отдельный UDP relay-порт и сообщает его клиенту. HTTP-прокси не имеет подобного механизма в принципе. Его архитектура вообще не предполагает открытия UDP-сокетов на стороне сервера для ретрансляции. Программный код HTTP-прокси работает с TCP-соединениями, и добавить туда UDP означало бы написать по сути новый протокол.

Вывод, который стоит запомнить навсегда

HTTP и HTTPS-прокси не поддерживают UDP не потому, что разработчики поленились, а потому, что их протокол построен исключительно вокруг TCP. Метод CONNECT это TCP-туннель, и точка. Если вам нужен UDP через прокси, единственный стандартный путь это SOCKS5 с поддержкой команды UDP ASSOCIATE. Никакой HTTP-прокси, каким бы продвинутым он ни был, не пропустит вам голос, видео или игровой трафик по UDP.

Что именно ломается без UDP: полная карта симптомов

Теперь самое практичное. Давайте разберём, какие технологии зависят от UDP и как выглядит их поломка глазами обычного пользователя. Это поможет вам мгновенно диагностировать проблему по симптомам.

WebRTC и связка STUN/TURN

WebRTC это технология реального времени, на которой построены видеозвонки в браузере, голосовые чаты, демонстрации экрана и многие конференц-сервисы. В основе передачи медиапотока лежит UDP, потому что для живого разговора важнее скорость, чем гарантия доставки каждого пакета. Небольшая потеря пакетов в голосе почти незаметна, а вот задержки от TCP-переотправки убивают качество.

Для установления соединения WebRTC использует протоколы STUN и TURN. STUN помогает узнать свой внешний адрес за NAT, а TURN служит ретранслятором, когда прямое соединение невозможно. И STUN, и медиапотоки по умолчанию идут по UDP.

Симптом со стороны пользователя: звонок вроде бы устанавливается, идёт индикация набора, но собеседник вас не слышит и не видит, или связь односторонняя. Иногда звонок обрывается через несколько секунд. Веб-интерфейс работает, чат работает, а звук и картинка не идут. Это классический признак заблокированного UDP.

QUIC и HTTP/3 с откатом на TCP

QUIC это современный транспортный протокол, построенный поверх UDP. На нём работает HTTP/3, самая новая версия протокола веба. QUIC даёт более быстрое установление соединения и лучше справляется с потерями пакетов, чем классический TCP. К 2026 году значительная доля крупных сайтов и сервисов уже поддерживает HTTP/3.

Когда UDP недоступен, происходит интересная вещь: приложение или браузер обычно откатывается на HTTP/2 или HTTP/1.1 поверх TCP. Это заложенный в дизайн механизм отказоустойчивости.

Симптом со стороны пользователя: чаще всего явной поломки нет, сайты открываются. Но вы теряете преимущества QUIC: соединения устанавливаются медленнее, при нестабильной сети возможны подвисания. Опытный наблюдатель заметит, что HTTP/3 недоступен, хотя сервер его поддерживает. Для большинства это скрытая деградация, а не явный сбой.

DNS по 53 порту через UDP

Классические DNS-запросы традиционно идут по UDP на порт 53. Это быстро и эффективно для коротких запросов имени.

Здесь есть тонкость, зависящая от того, как приложение резолвит имена. Если резолвинг выполняется на стороне прокси, проблемы может и не быть. Но если приложение хочет само отправить UDP DNS-запрос через прокси, а UDP не поддерживается, резолвинг сломается.

Симптом со стороны пользователя: имена сайтов не резолвятся, приложение сообщает, что хост не найден, хотя интернет есть. Иногда наблюдаются задержки, когда система пытается UDP, не получает ответа и переключается на TCP-вариант DNS.

VoIP и голосовая связь

VoIP это передача голоса по интернету. Голосовые протоколы почти всегда используют UDP для передачи звука, потому что задержка критична. Живой разговор невозможен, если каждый пакет ждёт подтверждения.

Симптом со стороны пользователя: вызов проходит, но звук отсутствует, прерывается или сильно запаздывает. Односторонняя слышимость, металлические артефакты, обрыв через несколько секунд разговора. Всё это признаки проблем с UDP-транспортом.

Онлайн-игры

Многие сетевые игры, особенно динамичные шутеры и соревновательные проекты, используют UDP для передачи состояния игрового мира. Причина всё та же: задержка важнее гарантии доставки. Устаревший пакет с позицией игрока бесполезен, лучше получить свежий.

Симптом со стороны пользователя: игра не подключается к матчу, зависает на экране соединения, выбрасывает по таймауту. Или подключение есть, но игра идёт с рывками, персонажи телепортируются, действия не регистрируются. Меню и магазин при этом могут работать, потому что они часто ходят по HTTP поверх TCP.

Торренты и P2P

Многие P2P-протоколы активно используют UDP для обмена служебной информацией и передачи данных. Без UDP функциональность деградирует: часть механизмов обнаружения узлов и передачи не работает.

Симптом со стороны пользователя: замедленная работа, проблемы с поиском источников, неполная функциональность.

Сводная таблица зависимости сценариев от UDP

Ниже практическая таблица, которую стоит сохранить. Она мгновенно подскажет, чего ждать в каждом сценарии.

  • Видеозвонок и видеочат. Использует UDP: да, критично. Без поддержки UDP: звонок устанавливается визуально, но нет звука и видео, односторонняя связь или обрыв. Основной функционал не работает.
  • Онлайн-игра. Использует UDP: да, для большинства динамичных игр. Без поддержки UDP: нет подключения к матчу, таймауты, рывки, телепортация. Игровой процесс невозможен или сильно деградирует.
  • DNS-запросы. Использует UDP: да, классический DNS на порту 53. Без поддержки UDP: возможны проблемы резолвинга или задержки, если приложение резолвит само; при резолвинге на стороне прокси проблемы может не быть.
  • QUIC и HTTP/3. Использует UDP: да, целиком построен на UDP. Без поддержки UDP: незаметный откат на TCP HTTP/2, потеря скорости и преимуществ, но сайты открываются.
  • Торрент и P2P. Использует UDP: да, для многих механизмов. Без поддержки UDP: деградация функций, проблемы с поиском источников и передачей.
  • Обычный парсинг и веб-скрапинг. Использует UDP: нет, обычно чистый TCP через HTTP. Без поддержки UDP: всё работает нормально, UDP не требуется.
  • VoIP-звонок. Использует UDP: да, для голосового потока. Без поддержки UDP: нет звука, обрывы, задержки, односторонняя слышимость.

Обратите внимание на последнюю строку. Для классических задач вроде парсинга или обычного веб-серфинга UDP не нужен вообще. Именно поэтому многие годами пользуются прокси без UDP и не подозревают об ограничении, пока не столкнутся со звонком или игрой.

Практика проверки: как узнать, поддерживает ли прокси UDP

Пришло время инструментов. Мы разберём несколько методов проверки, от простых до продвинутых, и объясним, почему популярные способы часто вводят в заблуждение.

Почему curl проверяет только TCP

Многие пробуют проверить прокси командой вида curl через socks5-hostname на какой-нибудь сайт. Если запрос проходит, делают вывод: прокси работает, значит и UDP работает. Это ловушка.

Дело в том, что HTTP-запрос через curl идёт по TCP. Команда с флагом socks5-hostname проверяет, что SOCKS5-прокси умеет выполнять команду CONNECT и резолвить имя на своей стороне. Но CONNECT это TCP. Успех такой проверки говорит только о том, что TCP через прокси работает. О поддержке UDP ASSOCIATE он не сообщает ровным счётом ничего.

Запомните железное правило: проверка TCP-инструментом не проверяет UDP. Чтобы проверить UDP, нужно явно инициировать команду UDP ASSOCIATE и попробовать передать датаграмму.

Метод 1: скрипт на Python через сокеты

Самый прозрачный способ понять и проверить UDP ASSOCIATE это написать небольшой скрипт, работающий с сокетами напрямую. Опишем логику пошагово, без привязки к конкретному коду, чтобы вы поняли суть.

  1. Откройте TCP-соединение с прокси. Подключитесь к хосту и порту SOCKS5-сервера обычным TCP-сокетом.
  2. Пройдите этап приветствия. Отправьте версию протокола и список поддерживаемых методов аутентификации. Получите выбранный сервером метод. При необходимости выполните аутентификацию логином и паролем.
  3. Отправьте команду UDP ASSOCIATE. Сформируйте запрос с версией, кодом команды 0x03, зарезервированным байтом и адресом. В качестве адреса и порта часто указывают нули, что означает: клиент пока не знает, с какого адреса будет слать датаграммы.
  4. Прочитайте ответ сервера. Здесь ключевой момент. Первое поле после версии это код ответа. Значение 0x00 означает успех. Если вы видите 0x07, это Command not supported, то есть прокси не умеет UDP ASSOCIATE. Другие ненулевые коды тоже сигнализируют об ошибке.
  5. Извлеките relay-адрес. При успехе прочитайте BND.ADDR и BND.PORT из ответа. Это адрес и порт для отправки ваших датаграмм.
  6. Отправьте тестовую датаграмму. Создайте UDP-сокет, оберните тестовую полезную нагрузку в заголовок SOCKS5 с полями RSV, FRAG, ATYP, DST.ADDR, DST.PORT и отправьте на relay-порт. В качестве цели удобно взять публичный сервис, отвечающий по UDP.
  7. Дождитесь ответа. Если приходит корректно инкапсулированный ответ, UDP через прокси реально работает. Если тишина, несмотря на успешный код ответа, значит ассоциация формально есть, но фактическая пересылка датаграмм не проходит.

Этот метод даёт исчерпывающую картину. Вы отдельно проверяете, принимает ли сервер команду UDP ASSOCIATE, и отдельно проверяете, действительно ли летят датаграммы.

Метод 2: STUN-запрос через прокси

Отличный практический тест использовать STUN-запрос как полезную нагрузку. STUN это лёгкий протокол, публичные STUN-серверы отвечают быстро, и такой тест ближе всего к реальному сценарию WebRTC.

Логика та же: устанавливаете UDP-ассоциацию, оборачиваете STUN-запрос типа Binding Request в заголовок инкапсуляции SOCKS5, шлёте на relay-порт с адресом публичного STUN-сервера. Если приходит STUN-ответ с вашим внешним адресом, значит UDP-путь через прокси полностью функционален, включая двустороннюю передачу. Это самый убедительный тест для сценариев реального времени.

Метод 3: dig через прокси для DNS по UDP

DNS-запрос тоже хороший тест, потому что это компактная UDP-датаграмма с понятным ответом. Идея в том, чтобы направить DNS-запрос по UDP через SOCKS5-прокси к публичному DNS-серверу.

Стандартный dig сам по себе не умеет ходить через SOCKS5 по UDP, поэтому обычно используют вспомогательную обёртку, которая направляет UDP-трафик через прокси, либо реализуют инкапсуляцию вручную по описанной выше схеме. Если DNS-ответ приходит, UDP-канал работает. Если запрос уходит в никуда, а TCP при этом работает, вывод очевиден: UDP не поддерживается.

Метод 4: socat и вспомогательные утилиты

Утилита socat это мощный швейцарский нож для работы с сокетами. С её помощью можно строить цепочки перенаправлений, включая связку UDP и SOCKS. Однако важно понимать ограничение: не все версии и режимы socat напрямую поддерживают UDP ASSOCIATE. Часто socat используют в комбинации с прослойкой, которая берёт на себя SOCKS5 UDP-инкапсуляцию, а socat отвечает за локальное перенаправление UDP.

Практический подход: поднять локальный UDP-приёмник, направить через прослойку UDP-трафик в прокси и проверить, доходит ли полезная нагрузка до цели и возвращается ли ответ. Это более инженерный путь, полезный при отладке инфраструктуры.

Как правильно читать код ответа 0x07

Код 0x07 Command not supported это самый честный и прямой сигнал. Он означает, что SOCKS5-сервер получил вашу команду UDP ASSOCIATE, распознал её, но отвечает: я эту команду не выполняю. Такой ответ типичен для прокси, которые реализуют только CONNECT.

Однако будьте внимательны к более коварному сценарию. Иногда сервер отвечает кодом успеха 0x00 на команду UDP ASSOCIATE, но реальная пересылка датаграмм не работает. Причины разные: сетевой фильтр между прокси и целью, неправильная обработка relay-адреса, ограничения хостинга. Поэтому недостаточно проверить только код ответа. Настоящая проверка это успешная сквозная передача датаграммы и получение ответа. Именно поэтому мы так настаиваем на STUN или DNS-тесте с реальным ответом.

Чек-лист проверки UDP-поддержки прокси

  • Убедитесь, что вы тестируете именно SOCKS5, а не HTTP-прокси, так как последний UDP не умеет по определению.
  • Установите управляющее TCP-соединение и пройдите аутентификацию.
  • Отправьте команду UDP ASSOCIATE и проверьте код ответа. 0x00 хорошо, 0x07 означает отсутствие поддержки.
  • Извлеките и правильно интерпретируйте BND.ADDR и BND.PORT, учитывая случай нулевого адреса.
  • Отправьте реальную тестовую датаграмму, обёрнутую по формату инкапсуляции.
  • Дождитесь корректно инкапсулированного ответа. Только это подтверждает работу UDP.
  • Повторите тест несколько раз, чтобы исключить случайную потерю пакета.

UDP в мобильных сетях: NAT-таймауты и keepalive

Отдельная и очень важная тема поведение UDP в мобильных сетях. Здесь скрывается причина многих загадочных обрывов, которые кажутся необъяснимыми.

Почему UDP-сессия отваливается раньше TCP

Между вашим устройством и интернетом всегда стоит NAT, механизм трансляции сетевых адресов. NAT хранит таблицу соответствий внутренних и внешних адресов и портов. Для каждого соединения создаётся запись в этой таблице, и она живёт ограниченное время.

И вот ключевая разница. Для TCP у NAT есть чёткие сигналы начала и конца соединения: он видит рукопожатие и видит закрытие. Поэтому TCP-записи в таблице NAT обычно живут долго, иногда десятки минут или дольше.

Для UDP всё иначе. UDP не имеет понятия соединения, поэтому NAT не знает, когда сессия началась и закончилась. Он просто держит запись, пока по ней идёт трафик, и удаляет её после периода тишины. Этот период тишины называется UDP NAT-таймаут, и в мобильных сетях он часто очень короткий, иногда всего десятки секунд.

Результат: если по UDP-каналу некоторое время нет трафика, NAT молча выбрасывает запись. Ваши последующие датаграммы уже некуда доставить в обратную сторону, и сессия обрывается. При этом TCP-соединение в тех же условиях продолжало бы жить.

Зачем нужен keepalive

Keepalive это регулярная отправка небольших пакетов, чтобы NAT считал сессию активной и не удалял запись. Для UDP keepalive особенно критичен именно из-за коротких таймаутов.

Хорошо спроектированные протоколы реального времени сами шлют периодические keepalive или служебные пакеты. Например, в WebRTC механизм проверки связности постоянно подтверждает путь. Но если приложение молчит, а таймаут NAT короткий, обрыв неизбежен. Поэтому при работе с UDP через прокси в мобильных сетях стоит учитывать необходимость поддерживать канал живым.

Практические наблюдения по мобильным сетям

  • Мобильные операторы часто применяют более агрессивную политику по UDP, чем по TCP, ради экономии ресурсов NAT.
  • UDP NAT-таймаут может отличаться у разных операторов и меняться со временем, поэтому единого значения нет.
  • Симптом короткого таймаута: соединение отлично работает в активной фазе, но обрывается во время пауз, например когда собеседник молчит в звонке.
  • Управляющее TCP-соединение SOCKS5 для UDP-ассоциации тоже нужно поддерживать живым, иначе прокси закроет всю ассоциацию.

Это тонкий момент, который отличает поверхностное понимание от глубокого. Даже когда прокси корректно поддерживает UDP ASSOCIATE, нестабильность может приходить со стороны мобильного NAT, а не самого прокси. Диагностируя обрывы, всегда держите в голове фактор таймаутов.

Типичные ошибки при работе с UDP через прокси

Соберём в одном месте самые распространённые заблуждения. Избегая их, вы сэкономите часы отладки.

Ошибка 1: путать socks5 и socks5h

В настройках многих инструментов есть два варианта записи SOCKS5. Схема socks5 обычно означает, что резолвинг доменного имени выполняется локально, на стороне клиента, а прокси получает уже готовый IP-адрес. Схема socks5h означает, что резолвинг выполняется на стороне прокси-сервера.

Почему это важно? Во-первых, локальный резолвинг может утекать через ваш обычный DNS, что нежелательно для приватности задачи. Во-вторых, при неправильном выборе схемы часть логики может вести себя не так, как вы ожидаете. Путаница между socks5 и socks5h порождает трудноуловимые баги, когда кажется, что прокси работает через раз. Всегда осознанно выбирайте, где именно резолвится имя.

Ошибка 2: считать, что раз SOCKS5, значит UDP работает

Это, пожалуй, самое частое и самое опасное заблуждение. Стандарт SOCKS5 предусматривает команду UDP ASSOCIATE, но не обязывает каждую реализацию её поддерживать. Огромное количество SOCKS5-прокси реализуют только CONNECT и BIND, а на UDP ASSOCIATE отвечают кодом 0x07.

Иными словами, надпись SOCKS5 это не гарантия UDP. Это лишь возможность, которая может быть, а может не быть реализована. Единственный способ узнать наверняка это проверить, как мы описали выше. Никогда не полагайтесь на маркетинговую этикетку, полагайтесь на реальный тест.

Ошибка 3: проверять UDP браузером

Некоторые пытаются проверить поддержку UDP, просто открыв сайт через прокси в браузере. Но браузер ходит на сайты по TCP. Даже если сайт поддерживает HTTP/3 по UDP, при недоступности UDP браузер тихо откатится на TCP, и вы ничего не заметите. Успешное открытие страницы не доказывает работу UDP.

Более того, WebRTC в браузере имеет собственную сложную логику обхода сетевых ограничений и может использовать TURN поверх TCP в некоторых конфигурациях, что дополнительно запутывает картину. Поэтому браузер плохой инструмент для чистой проверки UDP-транспорта. Используйте прямые сокет-тесты.

Ошибка 4: игнорировать сквозную проверку

Как мы уже подчёркивали, ответ 0x00 на UDP ASSOCIATE не равен рабочему UDP. Ошибка полагаться только на код ответа. Всегда доводите тест до реального обмена датаграммами с получением ответа. Это отделяет формальную поддержку от фактической работоспособности.

Ошибка 5: не учитывать keepalive и таймауты

Настроив UDP, легко забыть про NAT-таймауты. Тогда канал работает в момент теста, но обрывается на паузах в реальной эксплуатации. Всегда закладывайте механизм поддержания канала живым, особенно в мобильных сетях.

Ошибка 6: неправильно обрабатывать relay-адрес

Как отмечалось, сервер может вернуть в BND.ADDR нулевой адрес, подразумевая тот же хост управляющего соединения. Клиенты, которые слепо шлют датаграммы на нулевой адрес, ломаются. Правильная реализация подставляет адрес прокси из TCP-соединения. Эта тонкость становится причиной множества молчаливых сбоев.

Инструменты и ресурсы для работы с UDP через SOCKS5

Подведём практический арсенал, который стоит держать под рукой.

Инструменты диагностики

  • Собственный скрипт на Python с сокетами. Самый гибкий и прозрачный инструмент. Даёт полный контроль над формированием команды UDP ASSOCIATE и инкапсуляцией датаграмм. Идеален для точной диагностики.
  • STUN-клиент через прокси. Лучший тест для сценариев реального времени. Быстрый ответ, понятный результат, максимально близко к WebRTC.
  • DNS-тест по UDP. Компактный и наглядный, отлично подходит для проверки сквозной передачи коротких датаграмм.
  • socat и прослойки для UDP-инкапсуляции. Инженерный инструментарий для построения и отладки цепочек перенаправления UDP через SOCKS5.
  • Анализатор трафика. Наблюдение за пакетами помогает увидеть, действительно ли датаграммы уходят на relay-порт и приходят ли ответы. Незаменимо при глубокой отладке.

Что важно знать о стандартах

Ключевой документ по SOCKS5 это RFC 1928, где описаны команды, формат запросов и ответов, а также инкапсуляция UDP. Понимание этого стандарта отличает эксперта от пользователя, который действует наугад. Дополнительно полезно понимать принципы STUN, QUIC и работы NAT, потому что именно на стыке этих технологий возникают практические проблемы с UDP.

Мини-фреймворк принятия решения

  1. Определите, нужен ли вам UDP вообще. Для парсинга и обычного веба нет, для звонков, игр, реального времени да.
  2. Если UDP нужен, убедитесь, что прокси именно SOCKS5, а не HTTP.
  3. Проверьте реальную поддержку UDP ASSOCIATE сквозным тестом, а не по этикетке.
  4. Учтите keepalive и NAT-таймауты, особенно в мобильных сетях.
  5. Правильно обрабатывайте relay-адрес и формат инкапсуляции.

Кейсы и результаты применения

Разберём несколько типичных ситуаций, показывающих, как знание транспорта решает реальные проблемы.

Кейс 1: молчащий видеозвонок

Ситуация. Пользователь жалуется, что через прокси открываются все сайты, чат в конференции работает, но во время звонка нет ни звука, ни видео. Собеседники видят индикацию соединения, но общения нет.

Диагностика. TCP-проверка через прокси проходит успешно, что поначалу сбивает с толку. Затем проводится сквозной STUN-тест через UDP ASSOCIATE. Сервер отвечает на команду кодом 0x07 Command not supported.

Вывод. Прокси реализует только CONNECT, UDP не поддерживается вовсе. WebRTC-медиапоток по UDP не проходит, отсюда молчание. Решение на уровне транспорта: требуется SOCKS5 с реальной поддержкой UDP ASSOCIATE, подтверждённой сквозным тестом.

Кейс 2: обрыв связи на паузах в мобильной сети

Ситуация. Голосовая связь через прокси в мобильной сети отлично работает в активном разговоре, но стоит собеседникам замолчать на полминуты, как связь обрывается.

Диагностика. Сквозной UDP-тест проходит успешно, датаграммы летают в обе стороны. Значит, сам прокси UDP поддерживает. Наблюдение за поведением показывает, что обрывы происходят именно в паузы без трафика.

Вывод. Виновник короткий UDP NAT-таймаут мобильного оператора. Запись в таблице NAT удаляется во время тишины. Решение на уровне транспорта: обеспечить keepalive, поддерживающий канал и управляющее TCP-соединение живыми.

Кейс 3: ложная уверенность из-за кода 0x00

Ситуация. Инженер проверил прокси, отправив команду UDP ASSOCIATE, получил код успеха 0x00 и объявил, что UDP работает. Но пользователи всё равно жалуются на неработающие звонки.

Диагностика. Повторная проверка идёт дальше кода ответа: отправляется реальная STUN-датаграмма на relay-порт. Ответ не приходит, несмотря на успешный код.

Вывод. Формальная поддержка есть, фактической пересылки нет, вероятно, из-за фильтрации между прокси и внешней сетью или ошибки обработки relay-адреса. Урок: код 0x00 недостаточен, только сквозная передача датаграммы доказывает работоспособность.

Кейс 4: скрытая деградация HTTP/3

Ситуация. Всё вроде работает, сайты открываются, жалоб нет, но команда замечает, что соединения устанавливаются медленнее, чем ожидалось, и HTTP/3 нигде не задействован.

Диагностика. Проверка показывает, что UDP через прокси не проходит, поэтому QUIC недоступен, и клиенты молча откатываются на TCP.

Вывод. Это не поломка, а скрытая потеря производительности. Понимание транспорта позволяет осознанно решить, важен ли QUIC для задачи, и при необходимости обеспечить UDP-поддержку.

FAQ: часто задаваемые вопросы

Можно ли вообще передать UDP через HTTP-прокси хоть каким-то способом?

Стандартными средствами нет. Метод CONNECT в HTTP-прокси создаёт исключительно TCP-туннель и не имеет механизма адресации и пересылки датаграмм. Любые попытки протолкнуть UDP через чистый HTTP-прокси упираются в отсутствие соответствующего протокола. Для UDP предназначен SOCKS5 с командой UDP ASSOCIATE. Это правильный и стандартизированный путь.

Если прокси называется SOCKS5, он точно поддерживает UDP?

Нет, и это важнейший нюанс. Стандарт предусматривает UDP ASSOCIATE, но не требует его обязательной реализации. Многие SOCKS5-прокси поддерживают только CONNECT. Единственный надёжный способ убедиться это провести сквозной тест с реальной передачей датаграммы, а не полагаться на название или маркетинг.

Почему curl показывает, что прокси работает, а звонок не идёт?

Потому что curl проверяет TCP через команду CONNECT, а звонок использует UDP. Это два разных транспорта. Успех TCP-проверки ничего не говорит о UDP. Чтобы проверить UDP, нужно инициировать UDP ASSOCIATE и передать датаграмму, например STUN-запрос, дождавшись ответа.

Что означает код ответа 0x07 при попытке UDP ASSOCIATE?

Это Command not supported. Прокси получил вашу команду, распознал её, но сообщает, что не выполняет UDP ASSOCIATE. Практически это означает, что прокси не умеет пересылать UDP. Вам нужен другой прокси с реальной поддержкой этой команды.

Зачем UDP ASSOCIATE использует TCP-соединение, если мы передаём UDP?

Управляющее TCP-соединение служит двум целям. Во-первых, по нему надёжно проходят аутентификация и согласование. Во-вторых, оно определяет время жизни UDP-ассоциации: пока TCP открыто, ассоциация действует, как только оно закрывается, прокси освобождает ресурсы. Это элегантный способ управления сессией и очистки.

Почему UDP-связь обрывается в мобильной сети, а TCP держится?

Из-за особенностей NAT. Для TCP у NAT есть явные сигналы начала и конца, поэтому записи живут долго. UDP не имеет понятия соединения, и NAT удаляет запись после короткого периода тишины. В мобильных сетях UDP-таймаут особенно короткий. Решение регулярный keepalive, поддерживающий канал активным.

Можно ли проверить UDP-поддержку прямо в браузере?

Надёжно нет. Браузер ходит на сайты по TCP, а при недоступности UDP тихо откатывается на TCP для QUIC. WebRTC в браузере имеет сложную логику и может задействовать обходные механизмы. Всё это маскирует реальное состояние UDP. Для чистой проверки используйте прямые сокет-тесты, STUN или DNS через UDP ASSOCIATE.

В чём разница между socks5 и socks5h на практике?

Различие в том, где резолвится доменное имя. При socks5 имя обычно резолвится локально на стороне клиента, при socks5h на стороне прокси. Это влияет и на приватность резолвинга, и на поведение в некоторых сценариях. Осознанный выбор схемы избавляет от трудноуловимых ошибок.

Обязательно ли реализовывать фрагментацию датаграмм в SOCKS5?

На практике нет. Поле FRAG предусмотрено стандартом, но подавляющее большинство реализаций работает только со значением FRAG равным нулю, то есть без фрагментации. Датаграммы должны помещаться в один пакет. Реальные протоколы, использующие UDP, обычно оперируют небольшими датаграммами, поэтому это редко создаёт проблемы.

Как отличить проблему прокси от проблемы мобильного NAT?

Проведите сквозной UDP-тест. Если он вообще не проходит, а команда возвращает 0x07 или датаграммы не доходят, проблема в прокси. Если тест успешно проходит, а обрывы случаются только на паузах в реальной эксплуатации, скорее всего виноват короткий UDP NAT-таймаут. Такой разбор точно локализует источник.

Заключение: транспорт решает всё

Мы прошли путь от базовых понятий TCP и UDP до тонкостей инкапсуляции датаграмм в SOCKS5 и коварных NAT-таймаутов мобильных сетей. Давайте закрепим главные выводы, которые превращают вас из пользователя, гадающего на кофейной гуще, в человека, точно понимающего, что происходит на транспортном уровне.

Во-первых, UDP и TCP это два разных мира. UDP несёт разрозненные датаграммы без гарантий, ради скорости, и именно на нём держатся звонки, игры, QUIC и классический DNS. Прокси, умеющий пересылать TCP, не обязан уметь UDP.

Во-вторых, только SOCKS5 через команду UDP ASSOCIATE даёт стандартный путь для UDP. Механизм красив: управляющее TCP-соединение, отдельный relay-порт и инкапсуляция каждой датаграммы в заголовок с полями RSV, FRAG, ATYP, DST.ADDR и DST.PORT.

В-третьих, HTTP и HTTPS-прокси не пропускают UDP в принципе. Метод CONNECT создаёт исключительно TCP-туннель, в его архитектуре нет ни адресации датаграмм, ни relay-порта, ни механизма пересылки UDP.

В-четвёртых, надпись SOCKS5 не гарантирует UDP. Всегда проверяйте сквозным тестом, доводя дело до реальной передачи датаграммы и получения ответа. Код 0x00 без фактического обмена ничего не доказывает, а код 0x07 честно сообщает об отсутствии поддержки.

В-пятых, в мобильных сетях UDP капризнее из-за коротких NAT-таймаутов. Keepalive и поддержание управляющего соединения живым спасают от загадочных обрывов на паузах.

Ваши следующие шаги просты. Определите, нужен ли вам UDP для конкретной задачи, опираясь на нашу таблицу сценариев. Если нужен, убедитесь, что работаете с SOCKS5, и проверьте реальную поддержку UDP ASSOCIATE своим тестом, будь то STUN, DNS или прямой сокет-скрипт. Заложите keepalive и корректно обрабатывайте relay-адрес. Сделав это, вы больше никогда не окажетесь в ситуации, когда прокси вроде работает, а звонок молчит. Теперь вы точно знаете, где искать причину и как её устранить на уровне транспорта.