unProxy / Документация
От исходников
до первого запроса.
unProxy — самостоятельный HTTP, HTTP/3 и SOCKS5 прокси на Go. Начните с локального запуска, затем подключите нужный следующий узел. unPreSock понадобится только для прозрачной маршрутизации на Linux-шлюзе.
01 / Начало работы
Сборка и запуск
Нужны исходники проекта и Go 1.26 или новее. Команды ниже рассчитаны на Linux и Bash. Первый блок выполняйте из корня репозитория; после него вы окажетесь в каталоге unProxy/.
cd unProxy
go build -o unproxy .
UNPROXY_LISTENTO=127.0.0.1:8585 \
SOCKS5_LISTENTO=127.0.0.1:1080 \
./unproxy
Оставьте процесс работающим. HTTP прокси доступен на 127.0.0.1:8585, SOCKS5 — на 127.0.0.1:1080. Оба адреса принимают подключения только с этого компьютера. Для остановки нажмите Ctrl + C.
В другом терминале отправьте запрос через один из протоколов. Для этих примеров нужен curl и доступ к example.com.
curl --proxy http://127.0.0.1:8585 https://example.com
curl --proxy socks5h://127.0.0.1:1080 https://example.com
В браузере укажите HTTP прокси 127.0.0.1:8585 или SOCKS5 127.0.0.1:1080. При SOCKS5 включите разрешение DNS-имён через прокси, если клиент предлагает такую настройку.
Windows / PowerShell
Из корня репозитория, в новом окне PowerShell с установленным Go:
cd unProxy
go build -o unproxy.exe .
$env:UNPROXY_LISTENTO = '127.0.0.1:8585'
$env:SOCKS5_LISTENTO = '127.0.0.1:1080'
.\unproxy.exe
Для проверки из другого окна PowerShell используйте curl.exe --proxy http://127.0.0.1:8585 https://example.com. В Windows переменные из примера сохраняются до закрытия окна PowerShell.
02 / Основной вход
HTTP и HTTPS через CONNECT
Для HTTP unProxy пересылает запросы к серверу назначения. Для HTTPS клиент открывает CONNECT-туннель, после чего unProxy передаёт байты между клиентом и сервером. Отдельный сертификат на клиенте для такого подключения не нужен.
HTTP listener включён по умолчанию. Если UNPROXY_LISTENTO не задан, используется 127.0.0.1:8585. Изменения переменных окружения применяются при следующем запуске процесса.
| Переменная | Назначение | По умолчанию |
|---|---|---|
UNPROXY_LISTENTO | Адрес и порт HTTP listener | 127.0.0.1:8585 |
UNPROXY_SECRET | Проверка заголовка X-Proxy-Secret у прокси-запросов | Не задан |
UNPROXY_PERIODIC_STATS | Интервал вывода статистики в секундах | Без периодического вывода |
HTTP_MAX_IDLE_CONNS | Максимум простаивающих HTTP-соединений | 100 |
HTTP_MAX_IDLE_CONNS_PER_HOST | Простаивающие соединения на один хост | 10 |
HTTP_IDLE_TIMEOUT | Таймаут простаивающего соединения, секунды | 90 |
HTTP_RESPONSE_HEADER_TIMEOUT | Ожидание заголовков ответа, секунды | 60 |
SHUTDOWN_TIMEOUT_SECONDS | Время завершения активных HTTP-запросов при остановке | 30 |
UNPROXY_SECRET использует собственный заголовок, а не стандартное поле пароля HTTP прокси в браузере. Клиент должен уметь отправлять X-Proxy-Secret. Не считайте этот заголовок шифрованием соединения.
Краткая статистика доступна на том же локальном порту:
curl http://127.0.0.1:8585/statusline
03 / Отдельный порт
SOCKS5 для приложений
SOCKS5 работает рядом с HTTP прокси и включается переменной SOCKS5_LISTENTO. Поддерживаются TCP CONNECT и UDP ASSOCIATE, адреса IPv4, IPv6 и доменные имена. Команда BIND не поддерживается.
| Переменная | Назначение | По умолчанию |
|---|---|---|
SOCKS5_LISTENTO | Адрес и порт SOCKS5 listener | SOCKS5 выключен |
SOCKS5_AUTH | Имя и пароль в формате user:password | Не задан |
SOCKS5_ALLOW_FROM | Разрешённые IP-адреса или CIDR через запятую | Без списка ограничений |
SOCKS5_MAX_CONNS | Ограничение одновременных подключений | Без ограничения |
SOCKS5_AUTH_FAIL_LIMIT | Число ошибок авторизации до блокировки IP | 5; 0 отключает блокировку |
SOCKS5_AUTH_BAN_SECONDS | Продолжительность блокировки, секунды | 300 |
Если SOCKS5_AUTH пуст, но задан UNPROXY_SECRET, этот секрет используется как SOCKS5 пароль; имя пользователя может быть любым. Без обоих параметров локальный SOCKS5 работает без авторизации. По умолчанию запуск SOCKS5 без авторизации на адресе вне loopback отклоняется.
FRAG=0, до 64 получателей на сессию; таймаут бездействия — 120 секунд. Доступность UDP зависит также от клиента, NAT и межсетевого экрана.04 / Вход через QUIC
HTTP/3 и CONNECT-UDP
unProxy принимает HTTP/3 на отдельном UDP-порту с TLS. Совместимый клиент может отправлять HTTP-запросы и открывать TCP CONNECT-туннели. Для передачи UDP через HTTP/3 отдельно включается расширение CONNECT-UDP (MASQUE).
Обычные HTTP и SOCKS5 входы сохраняют свои адреса. Наличие HTTP/3 listener не переключает браузер автоматически: клиент должен поддерживать HTTP/3-прокси и явно использовать этот вход. Для прозрачного доступа устройств к HTTP/3-сайтам см. QUIC relay на шлюзе.
| Переменная | Назначение |
|---|---|
UNPROXY_HTTP3_LISTENTO | UDP адрес и порт, например 127.0.0.1:8443. |
UNPROXY_HTTP3_CERT | Путь к PEM-сертификату с цепочкой. Обязателен. |
UNPROXY_HTTP3_KEY | Путь к соответствующему PEM-ключу. Обязателен. |
UNPROXY_SECRET | Секрет в заголовке X-Proxy-Secret. Для адреса вне loopback обязателен. |
UNPROXY_HTTP3_CONNECT_UDP_URI_TEMPLATE | HTTPS URI template с переменными target_host и target_port. Без него CONNECT-UDP выключен. |
Сначала локальный listener
Остановите предыдущий unProxy. В каталоге unProxy/ выполните пример, заменив пути на свой сертификат и ключ. Для локального клиента сертификат должен соответствовать имени или IP, по которому он обращается к прокси, и быть доверенным этому клиенту.
UNPROXY_LISTENTO=127.0.0.1:8585 \
UNPROXY_HTTP3_LISTENTO=127.0.0.1:8443 \
UNPROXY_HTTP3_CERT=/path/to/proxy-fullchain.pem \
UNPROXY_HTTP3_KEY=/path/to/proxy-key.pem \
./unproxy
Для подключения с других машин задайте подходящий внешний адрес, откройте выбранный UDP-порт и установите UNPROXY_SECRET. Используйте сертификат для DNS-имени прокси от доверенного клиенту центра сертификации. Клиент должен уметь передавать X-Proxy-Secret; стандартное поле пароля HTTP-прокси не заменяет этот заголовок.
UDP через MASQUE
Добавьте к конфигурации URI template своего HTTP/3-прокси, например:
export UNPROXY_HTTP3_CONNECT_UDP_URI_TEMPLATE='https://proxy.example.com:8443/.well-known/masque/udp/{target_host}/{target_port}/'
Замените proxy.example.com:8443 на доступное клиенту имя и порт с подходящим сертификатом. Передайте тот же template MASQUE-клиенту с поддержкой HTTP/3 Datagrams (H3_DATAGRAM). Передача полезной нагрузки через надёжные DATAGRAM capsules не предусмотрена. CONNECT-UDP передаёт UDP-датаграммы; обычный CONNECT остаётся TCP-туннелем. HTTP-запросы к конечным серверам обслуживаются существующим HTTP-транспортом, без автоматического выбора HTTP/3 на выходе.
Размер UDP-пакета ограничен MTU пути и накладными расходами туннеля. Слишком большие датаграммы и PMTU-пробы отбрасываются без закрытия сессии; IPv4-фрагментация исходящего UDP отключена на Linux и Windows. Для QUIC внутри CONNECT-UDP клиенту может потребоваться начальный размер пакета 1200 байт и отключение внутреннего поиска MTU. Эти значения не гарантируют работоспособность любого сетевого пути.
NEXT_SOCKS5_ADDR, TUNNEL_MODE или slave-режимом. NEXT_UNPROXY_ADDR поддерживается для HTTP-запросов и TCP CONNECT, но отвергается при включённом CONNECT-UDP. Неподдерживаемая цепочка не заменяется прямым подключением.SOCKS5 UDP и прозрачный QUIC relay могут работать без HTTP/3 listener. Поэтому для цепочки SOCKS5 с UDP используйте отдельный обычный экземпляр unProxy.
05 / Следующий узел
Цепочки прокси
Следующий узел может быть HTTP или SOCKS5 прокси. Таблица относится к обычным TCP-входам HTTP и SOCKS5; ограничения отдельного HTTP/3 listener описаны выше.
| Настройка | HTTP / CONNECT на TCP-входе | SOCKS5 CONNECT | SOCKS5 UDP |
|---|---|---|---|
NEXT_UNPROXY_ADDR | Через HTTP upstream | Через HTTP CONNECT | Не поддерживается |
NEXT_SOCKS5_ADDR | Эта настройка не применяется | Через SOCKS5 upstream | Через SOCKS5 upstream |
Пример HTTP цепочки: upstream уже должен работать на 127.0.0.1:9585. Остановите предыдущий unProxy и выполните этот блок из каталога unProxy/.
UNPROXY_LISTENTO=127.0.0.1:8585 \
NEXT_UNPROXY_ADDR=127.0.0.1:9585 \
./unproxy
Для upstream unProxy с секретом добавьте NEXT_UNPROXY_SECRET. Значение передаётся в заголовке X-Proxy-Secret.
Пример SOCKS5 цепочки: upstream должен работать на 127.0.0.1:2080. Локальный вход здесь — SOCKS5 на порту 1080; HTTP listener остаётся отдельным.
UNPROXY_LISTENTO=127.0.0.1:8585 \
SOCKS5_LISTENTO=127.0.0.1:1080 \
NEXT_SOCKS5_ADDR=127.0.0.1:2080 \
./unproxy
Если upstream требует авторизацию, задайте NEXT_SOCKS5_AUTH=user:password со своими значениями. Для SOCKS5 входа NEXT_SOCKS5_ADDR имеет приоритет над NEXT_UNPROXY_ADDR. Не смешивайте настройки разных примеров без явной необходимости.
Для UDP-цепочки возвращённый upstream-сервером адрес UDP relay должен быть доступен с машины unProxy. Закрытие любого управляющего TCP-соединения завершает UDP-сессию.
06 / Вспомогательный модуль · Linux
Когда нужен unPreSock
unPreSock нужен на Linux-шлюзе, если устройства не настраивают прокси сами. Он принимает перенаправленный TCP-трафик и выбирает прямой путь или upstream по HTTP Host и TLS SNI. Сам unProxy работает без этого модуля.
Для сборки модуля достаточно Go 1.25.4 или новее. Следующий блок выполняйте из корня репозитория. Просмотр справки не настраивает межсетевой экран.
cd unPreSock
go build -o unpresock2 .
./unpresock2 -h
| Параметр | Назначение |
|---|---|
-http-proxy | HTTP upstream. Для локального unProxy укажите 127.0.0.1:8585; собственное значение по умолчанию у модуля — 127.0.0.1:8989. |
-socks | SOCKS5 upstream. Для выбора этого пути также задайте -http-proxy="". |
-client | IP или CIDR устройств, для которых создаются правила перенаправления. |
-host-redirect-list | Домены и шаблоны для TCP через запятую, например example.com,*.example.com. Не применяется к QUIC. |
-host-redirect-file | Файл правил TCP: одно имя, IP или шаблон в строке; # начинает комментарий, !example.com принудительно выбирает direct. Файл позволяет сохранять переключения из monitor. |
-ssh-uplink-user | Запускает только дочерний SSH-процесс от указанного пользователя и использует его домашний каталог и ключи. Нужен, если QUIC оставляет сам unPreSock с правами root. |
-set-fw | Создаёт правила TCP 80/443; также устанавливает выбранную QUIC-политику через iptables. Нужны права root. |
-set-fw-dns | Включает перенаправление DNS и встроенный DNS proxy; -dns-upstream задаёт DNS-сервер. |
-dns-listen | Отдельный DNS-вход, например 192.168.2.12:53, для явно направленных к серверу запросов. Принимает источники из -client; используется вместо -set-fw-dns. Upstream задаётся через -dns-upstream. |
-block-quic | Совместимый с прежней конфигурацией вариант -quic-mode block; несовместим с явно выбранным relay или passthrough. |
Перед включением -set-fw настройте шлюз и явно задайте -client для своей сети: этот режим изменяет системные правила маршрутизации трафика. Примеры доменов выше служат шаблонами для вашей конфигурации.
unPreSock передаёт TLS-трафик без расшифровки. Для TCP, если SNI недоступен, модуль пытается найти домен по ранее наблюдавшемуся DNS-ответу; при отсутствии соответствия выбирает безопасный путь через прокси и передаёт ему исходный IP назначения. Это не гарантирует точную фильтрацию доменов на общих CDN-адресах.
07 / HTTP/3 для устройств за шлюзом
Прозрачная передача QUIC
В режиме relay unPreSock принимает IPv4 UDP 443 через Linux TPROXY, передаёт целые датаграммы в SOCKS5 UDP ASSOCIATE и возвращает ответы с исходным IP и портом сервера. TLS остаётся между клиентом и сайтом. Для этого пути не требуется HTTP/3 listener unProxy.
| Параметр | Назначение |
|---|---|
-quic-mode | passthrough по умолчанию оставляет QUIC внешней маршрутизации; block отклоняет выбранный UDP 443 через ICMP, чтобы клиент мог сразу перейти на TCP; relay передаёт его через SOCKS5. |
-quic-socks | Адрес SOCKS5-сервера с UDP ASSOCIATE; если пуст, используется -socks. HTTP upstream для TCP задаётся отдельно. |
-quic-socks-auth | SOCKS5 имя и пароль в формате user:password. |
-quic-targets | IPv4 адреса/CIDR назначения через запятую. Пустое значение охватывает все внешние IPv4 назначения на UDP 443. |
-quic-port | Локальный прозрачный UDP-порт; по умолчанию 10443. |
-quic-idle-timeout | Таймаут сессии без трафика, по умолчанию 2m. |
-quic-max-sessions | Предел сессий клиент/назначение, по умолчанию 1024. |
-quic-cleanup | Удаляет принадлежащие модулю runtime-правила QUIC и policy routing после аварийной остановки, затем завершает процесс. |
Пример с локальным unProxy
На подготовленном Linux-шлюзе запустите обычный unProxy с HTTP на 127.0.0.1:8585 и SOCKS5 на 127.0.0.1:1080, как в быстром старте. Затем из каталога собранного unPreSock/ выполните:
sudo ./unpresock2 \
-client 192.168.50.0/24 -set-fw \
-http-proxy 127.0.0.1:8585 \
-quic-mode relay -quic-socks 127.0.0.1:1080
Устройства из указанной сети должны уже использовать эту машину как шлюз. Для удалённого unProxy замените адреса, настройте авторизацию SOCKS5 и доступ к управляющему TCP-порту и динамическим UDP relay-портам. При необходимости ограничьте назначения через -quic-targets. Ошибка SOCKS5 завершает сессию без прямого UDP-обхода.
Нужны root, поддержка TPROXY в ядре, ip и iptables. Правила QUIC действуют только во время работы процесса и удаляются при штатной остановке. Режимы relay/block несовместимы с -firewall-permanent и -drop-privileges-to; relay также несовместим с -direct. Без -set-fw правила захвата настраивает администратор отдельно.
-host-redirect-list, -host-redirect-file и DNS/SNI fallback не применяются к QUIC. Relay выбирает трафик по IP/CIDR и не расшифровывает QUIC ClientHello или ECH. Автоматический захват IPv6 и UDP-портов, отличных от 443, не реализован.После SIGKILL или аварии выполните sudo ./unpresock2 -quic-cleanup перед повторным запуском. Эта команда очищает только правила модуля. Старые правила DROP от прежнего -block-quic, правила firewalld и сторонние ограничения не удаляются автоматически: устраните конфликт вручную по сообщению запуска.
В управляемом режиме QUIC файл .EXIT запрашивает штатную остановку через SIGTERM с очисткой правил. Автоматическая замена из .UPDATE откладывается: остановите процесс, установите обновление и запустите его с прежними параметрами. Предупреждение выводится один раз для неизменившегося файла обновления.
Проверка реализации
Из корня исходников можно запустить локальные Go-тесты и отдельный сетевой сценарий:
(cd unProxy && go test -race ./...)
(cd unPreSock && go test -race ./...)
bash tests/http3-netns.sh
Сетевой сценарий требует доступных Linux user/network namespaces, unshare, ip, iptables, mount и Python 3. Он создаёт изолированную сеть для проверки HTTP/3 через unPreSock и unProxy, TCP и очистки правил. Это проверка протокольного пути, а не совместимости всех браузеров или публичных видеосервисов.
08 / Наблюдение
Состояние и маршруты
У запущенного unProxy откройте 127.0.0.1:8585/monitor/, подставив свой адрес HTTP-входа при необходимости. Это рабочая страница, встроенная в бинарник; она обновляет снимок каждые 5 секунд и позволяет приостановить обновление.
В плотной таблице видны источник, назначение, известное имя хоста, протокол, маршрут и состояние подключения. Фильтры разделяют перенаправленные, прямые и ещё ожидающие решения соединения. После закрытия прямого подключения его адрес остаётся в отчёте: с числом попыток, ошибками и временем последнего обращения.
Подключить данные шлюза
Добавьте к своей существующей команде запуска unPreSock параметр -monitor-listen 127.0.0.1:8586. Затем добавьте к переменным окружения unProxy адрес монитора шлюза:
export UNPROXY_GATEWAY_MONITOR_URL=http://127.0.0.1:8586
./unproxy
На странице выберите unPreSock, чтобы увидеть настройки перехвата, адреса клиентов, назначения и доменные правила. Отдельная панель шлюза доступна по http://127.0.0.1:8586/monitor/. При размещении компонентов на разных машинах используйте доступный адрес и ключ доступа.
Для работы сервера как DNS включите, например, -dns-listen 192.168.2.12:53 -dns-upstream 192.168.2.1:53. DNS-клиенты появятся среди исходных хостов, а запросы и ответы — в счётчиках DNS. Одна настройка DNS на клиенте не направляет веб-трафик через прокси: для этого нужен также шлюз через unPreSock или явная настройка прокси.
Нажмите на счётчик «Исходные хосты», «Назначения proxy» или «Назначения direct», чтобы открыть соответствующий список имён и IP без портов. В нём есть поиск, страницы по 100 адресов и кнопка «Обновить список»; повторный клик по счётчику сворачивает список. Учитываются наблюдения с запуска выбранного компонента, включая завершённые подключения, максимум 16 384 уникальных хоста в каждой группе. Знак «+» сообщает о неполном учёте из-за защитного предела. Списки загружаются по запросу; после перезапуска сбор начинается заново.
Раздел фактического состояния содержит снимок iptables/ip6tables, маршрутов, firewalld и nftables, включая сторонние правила. Он читается по запросу и кэшируется на 30 секунд. Конфигурация процесса и правила ядра показаны отдельно: внешние правила, порядок цепочек или отсутствие прав могут менять результат.
Доступ и границы наблюдения
| Параметр | Назначение |
|---|---|
UNPROXY_MONITOR_SECRET | Ключ страницы unProxy. Если не задан, используется UNPROXY_SECRET. Без обоих ключей API доступен только через loopback. |
-monitor-listen | Включает отдельный HTTP-вход мониторинга unPreSock; по умолчанию выключен. |
-host-redirect-file | Включает сохраняемые переключатели «через прокси / direct» на отдельной странице unPreSock. |
UNPRESOCK_MONITOR_SECRET | Ключ шлюза; обязателен для его внешнего адреса. |
UNPROXY_GATEWAY_MONITOR_URL | Адрес монитора unPreSock для общей страницы, например http://127.0.0.1:8586. |
UNPROXY_GATEWAY_MONITOR_SECRET | Ключ шлюза, который unProxy использует при чтении его данных. |
Ключ вводится на странице и хранится в sessionStorage этой вкладки: он переживает перезагрузку страницы. Кнопка «Выйти» удаляет ключ; браузер также удаляет его при закрытии вкладки. API /monitor/api/state принимает ключ в Authorization: Bearer … или X-Monitor-Secret. Для удалённого доступа используйте защищённый транспорт, например SSH-туннель или HTTPS reverse proxy.
Изменение маршрута доступно только на отдельной панели unPreSock, всегда требует ключ и атомарно записывает правило в -host-redirect-file; текущие соединения не переключаются. В режиме -quic-mode block с -set-fw в строке QUIC доступна кнопка временной разблокировки и повторной блокировки. После перезапуска действует режим из командной строки.
Если пользователи прокси не должны видеть мониторинг, задайте ключи обеих панелей: доступ к localhost через прокси тоже приходит с loopback-адреса.
Сохраняются последние 16 384 сочетаний источника и прямого назначения. При заполнении удаляется запись с самым давним последним обращением; после перезапуска история начинается заново. Трафик вне правил перехвата, QUIC passthrough и заблокированные пакеты в этот отчёт не попадают. SOCKS5 UDP отображается как ассоциация с возможными несколькими назначениями.
Счётчики объёма работают прежним способом, иногда обновляясь после завершения передачи. Точная скорость и объём по каждому протоколу не вычисляются; в циклах передачи новый подсчёт не добавлен. Для HTTP строка обозначает активный запрос, для CONNECT — туннель, для UDP — ассоциацию или поток шлюза.
09 / Перед расширением схемы
Границы возможностей
- Локальный запуск — начальная конфигурация. HTTP listener не запрещает внешний адрес без авторизации автоматически. Доступ с других компьютеров требует отдельно настроить доступ к порту и подходящую авторизацию.
- CONNECT и шифрование — разные уровни. HTTPS сохраняет TLS-соединение клиента с конечным сервером. Обычный HTTP listener и SOCKS5 username/password сами по себе не шифруют соединение с прокси.
- UDP зависит от пути. SOCKS5 UDP работает напрямую или через SOCKS5 upstream, но не через HTTP upstream. Это не обещание совместимости с каждым приложением или каждой сетью.
- HTTP/3 требует подходящего пути. Native listener требует сертификат и совместимый клиент; прозрачный QUIC relay ограничен IPv4 UDP 443. Туннелирование не раскрывает ECH и не делает скрытый SNI видимым.
- Mux и TUNNEL — расширенные экспериментальные режимы. В коде есть hub/slave-схема с
MODE,MODE_LABEL,LINK_ADDRи отдельная подсистемаTUNNEL_*. Их покрытие протоколов отличается от обычного прокси; не предполагается, что любой трафик автоматически проходит через туннель.
Mux hub запускается только при явно заданном LINK_ADDR или -link. Параметры MUX_SECRET, MUX_TLS и MUX_AES_KEY относятся именно к mux-каналу и не меняют HTTP listener из быстрого старта.