Skip to content
This repository was archived by the owner on Jun 21, 2026. It is now read-only.

Kavun-Sama/jazztun

Repository files navigation

jazztun

CI License: GPL v3 Telegram

A proxy tunnel that routes TCP traffic through Salute Jazz WebRTC infrastructure. It is meant for cases where classic VPN protocols are easy to detect or block, while browser-based video traffic is still allowed.

EN English | RU Русский

English

Description

jazztun runs a local SOCKS5 proxy and sends TCP traffic through a Salute Jazz room to a remote server. Your browser or app talks to 127.0.0.1:1080; the remote host becomes the exit point.

Why this works in places where regular VPNs do not: the transport path looks like a normal browser video session built on Jazz signaling, TURN, and WebRTC DataChannels, not a conventional VPN tunnel.

To reach resources blocked in Russia, the remote server must be outside Russia. When Salute Jazz itself is allowed or explicitly whitelisted in a network, jazztun benefits from that allowance.

Protocol Flow

┌────────────────┐     SOCKS5      ┌────────────────┐
│ Browser / App  ├────────────────►│ jazztun client │
└────────────────┘                 └──────┬─────────┘
                                          │
                                          │ AES-256-GCM encrypted mux frames
                                          ▼
                           Salute Jazz signaling + WebRTC DataChannel
                                          │
                                          ▼
                                   ┌──────┴─────────┐
                                   │ jazztun server │
                                   └──────┬─────────┘
                                          │
                                          ▼
                                  Remote TCP destination

Features

  • TCP tunneling over a Salute Jazz room
  • Local SOCKS5 proxy on the client
  • Optional RFC 1929 username/password auth for the local SOCKS5 proxy
  • AES-256-GCM encryption for tunnel frames
  • Multiple parallel transport peers with -peers N
  • Session-scoped transport pairing with -session
  • Multiple independent tunnel pairs can share one Jazz room
  • Per-stream affinity to preserve TCP byte order
  • Credit-based mux flow control
  • Optional custom DNS resolver on the server side
  • Optional upstream SOCKS5 proxy for server egress

Limitations

  • No UDP associate
  • No bind support
  • Access control is effectively the room URL, the shared key, and the matching session namespace
  • Full peer teardown and rebuild through WatchConnection is covered by tests; the live reconnect run recovered on the same WebRTC session

Download

Pre-built binaries for Linux, Windows, and macOS (Apple Silicon) are published on the Releases page.

The container image for the server is published to GitHub Container Registry:

docker run --rm -it ghcr.io/kavun-sama/jazztun-server:latest -room new

Each release includes checksums.txt. Verify it before running the binaries:

sha256sum -c checksums.txt

Build

Requirements:

  • Go 1.25 or newer
  • Network access to Salute Jazz signaling and ICE/TURN endpoints
  • A remote host outside Russia if you need access to resources blocked from within Russia
  • The remote host must be able to reach the TCP targets you want to proxy

Linux or macOS:

go build -o server ./cmd/server
go build -o client ./cmd/client

Windows PowerShell:

go build -o server.exe .\cmd\server
go build -o client.exe .\cmd\client

Print the binary version:

./server -version
./client -version

Containerized Server

Build the server image locally:

docker build -t jazztun-server:local .

Or pull the published image:

docker pull ghcr.io/kavun-sama/jazztun-server:latest

Run it directly:

docker run --rm -it jazztun-server:local -room new -peers 4

Run the published image directly:

docker run --rm -it ghcr.io/kavun-sama/jazztun-server:latest -room new -peers 4

Or use the provided compose file:

docker compose -f docker-compose.server.yml up --build

The compose file accepts these environment variables:

  • JAZZTUN_ROOM, default new
  • JAZZTUN_KEY
  • JAZZTUN_SESSION
  • JAZZTUN_PEERS, default 4
  • JAZZTUN_DNS, default 1.1.1.1:53
  • JAZZTUN_SOCKS
  • JAZZTUN_VERBOSE, set to any non-empty value to enable -v

Step-by-Step Setup

  1. Prepare a remote host outside Russia.
  2. Copy jazztun there.
  3. Start server on the remote host.
  4. Copy the printed room URL and key.
  5. Start client on your local machine with the same room URL and key.
  6. Point your browser or app to the local SOCKS5 proxy.
  7. Verify that the exit IP is the remote server IP.

If one room is only used by one server/client pair, you can ignore -session. If you want several independent pairs inside the same Jazz room, give each pair its own -session value and use the same value on both sides of that pair.

Example remote host setup:

mkdir -p ~/jazztun
cd ~/jazztun
chmod +x ./server
./server -room new -peers 4 -v

Example local client start:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4 -listen 127.0.0.1:1080 -v

If you want the local SOCKS5 proxy to be usable by other devices in your LAN:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -listen 0.0.0.0:1080 -socks-user demo -socks-pass strongpass

Shared Room Sessions

One Jazz room can now carry several independent jazztun pairs at once.

  • Same room URL + same key + same -session value: same tunnel pair
  • Same room URL + same key + different -session value: separate tunnel pair
  • Same room URL + same key + same -session value on two clients at once: conflict, the extra client is ignored

Example:

./server -room new -peers 2 -session alpha
./client -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 2 -session alpha

Second independent pair in the same room:

./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 2 -session beta
./client -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 2 -session beta

Quick Start

Option 1: Let the server create a room

Start the server first:

./server -room new -peers 4 -v

The server will print the room URL and the generated key.

Start the client with the same room URL and key:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4 -v

By default, the local SOCKS5 proxy listens on 127.0.0.1:1080.

Option 2: Join an existing room

./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4
./client -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4

Flags

Typical server commands:

./server -room new -peers 4 -v
./server -room new -peers 4 -session alpha
./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -dns 8.8.8.8:53
./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -socks 127.0.0.1:9050

Typical client commands:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4 -v
.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -session alpha -peers 4
.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -listen 127.0.0.1:1081
.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -listen 0.0.0.0:1080 -socks-user demo -socks-pass strongpass

Server:

  • -room: room URL or new
  • -key: 64-character hex key; autogenerated if omitted on the server
  • -session: optional namespace for sharing one Jazz room across multiple independent tunnel pairs
  • -duo: shorthand for two transport peers
  • -peers: number of transport peers to open; overrides -duo; use this to tune throughput
  • -dns: DNS resolver for remote lookups, default 1.1.1.1:53
  • -socks: upstream SOCKS5 proxy used by the server for outbound dialing
  • -v: verbose logging
  • -version: print the binary version and exit

Client:

  • -room: room URL
  • -key: same 64-character hex key as the server
  • -session: optional namespace that must match the server when sharing one Jazz room
  • -listen: local SOCKS5 listen address, default 127.0.0.1:1080
  • -socks-user: enable RFC 1929 username/password auth for the local SOCKS5 proxy
  • -socks-pass: password paired with -socks-user
  • -duo: shorthand for two transport peers
  • -peers: number of transport peers to open; overrides -duo; use this to tune throughput
  • -v: verbose logging
  • -version: print the binary version and exit

Testing

Run the full validation set:

go test ./...
go vet ./...

Package-level examples:

go test ./internal/crypto -v
go test ./internal/mux -v
go test ./internal/transport/jazz -v

Manual Check

  1. Start server.
  2. Start client with the same room URL and key.
  3. Check the exit IP through the local SOCKS5 proxy:
curl.exe --socks5-hostname 127.0.0.1:1080 https://ifconfig.me/ip

If the tunnel is working, the returned IP should be the remote server IP.

Bandwidth Test

On the remote server:

mkdir -p /root/bench
dd if=/dev/zero of=/root/bench/100m.bin bs=1M count=100 status=none
python3 -m http.server 8088 --directory /root/bench

On the client machine:

curl.exe --max-time 15 --socks5-hostname 127.0.0.1:1080 -o NUL -w "speed=%{speed_download} bytes/s time=%{time_total}s code=%{http_code}`n" http://SERVER_IP:8088/100m.bin

Observed throughput on the current codebase:

  • single stream: roughly 33-43 Mbit/s
  • aggregate throughput with -peers 6 and eight parallel downloads: about 110 Mbit/s

Troubleshooting

Room URL rejected:

  • use the full invite link, including ?psw=...

Tunnel connects but traffic does not pass:

  • verify that the key matches on both sides
  • verify that -session matches on both sides when you use it
  • verify that the client is using SOCKS5, not HTTP proxy mode
  • verify that the server can resolve and reach the target host

Another client unexpectedly does not connect in the same room:

  • check whether both clients are using the same -session
  • same session means same logical tunnel pair; use a different -session for each independent pair

Frequent reconnects:

  • active streams resume across the tested blackout/reconnect path
  • a full peer teardown and rebuild through WatchConnection is covered by tests; the live reconnect run recovered on the same WebRTC session

Server-side DNS issues:

./server -room new -dns 8.8.8.8:53

Server egress through another SOCKS5 proxy:

./server -room new -socks 127.0.0.1:9050

Russian

Описание

jazztun поднимает локальный SOCKS5-прокси и отправляет TCP-трафик через комнату Salute Jazz на удалённый сервер. Приложение или браузер подключается к 127.0.0.1:1080, а удалённая машина становится точкой выхода трафика.

Почему это работает там, где обычный VPN режут: транспорт выглядит как обычная browser-сессия видеозвонка на Jazz signaling, TURN и WebRTC DataChannels, а не как классический VPN-туннель.

Чтобы получать доступ к ресурсам, заблокированным в РФ, удалённый сервер должен находиться за пределами РФ. Если сам Salute Jazz в сети доступен или внесён в белый список, jazztun получает это преимущество вместе с ним.

Схема Протокола

┌────────────────────┐    SOCKS5     ┌────────────────┐
│ Браузер / программа├──────────────►│ jazztun client │
└────────────────────┘               └──────┬─────────┘
                                            │
                                            │ mux-кадры, зашифрованные AES-256-GCM
                                            ▼
                         Salute Jazz signaling + WebRTC DataChannel
                                            │
                                            ▼
                                     ┌──────┴─────────┐
                                     │ jazztun server │
                                     └──────┬─────────┘
                                            │
                                            ▼
                                   Удалённый TCP-сервис

Возможности

  • TCP-туннель поверх комнаты Salute Jazz
  • локальный SOCKS5-прокси на клиенте
  • опциональная RFC 1929 username/password auth для локального SOCKS5-прокси
  • AES-256-GCM для кадров туннеля
  • несколько параллельных transport peer-ов через -peers N
  • session-scoped pairing через -session
  • несколько независимых пар могут делить одну Jazz-комнату
  • привязка каждого stream к одному peer-у для сохранения порядка TCP-байтов
  • credit-based flow control в mux
  • кастомный DNS-резолвер на стороне сервера
  • опциональный upstream SOCKS5-прокси для исходящих подключений сервера

Ограничения

  • нет UDP associate
  • нет bind
  • контроль доступа фактически держится на room URL, общем ключе и совпадающем -session
  • полный teardown и rebuild peer-а через WatchConnection покрыт тестами; в живом reconnect-тесте восстановление произошло на той же WebRTC-сессии

Скачивание

Готовые бинарники для Linux, Windows и macOS (Apple Silicon) публикуются на странице релизов.

Контейнерный образ сервера публикуется в GitHub Container Registry:

docker run --rm -it ghcr.io/kavun-sama/jazztun-server:latest -room new

В каждом релизе есть checksums.txt. Перед запуском лучше проверить контрольные суммы:

sha256sum -c checksums.txt

Сборка

Требования:

  • Go 1.25 или новее
  • сетевой доступ к сигналингу Salute Jazz и ICE/TURN-инфраструктуре
  • удалённая машина за пределами РФ, с которой можно достучаться до целевых TCP-хостов, если нужен доступ к заблокированным в РФ ресурсам

Linux или macOS:

go build -o server ./cmd/server
go build -o client ./cmd/client

Windows PowerShell:

go build -o server.exe .\cmd\server
go build -o client.exe .\cmd\client

Вывести версию бинарника:

./server -version
./client -version

Сервер В Контейнере

Собрать образ локально:

docker build -t jazztun-server:local .

Или скачать уже опубликованный образ:

docker pull ghcr.io/kavun-sama/jazztun-server:latest

Запустить напрямую:

docker run --rm -it jazztun-server:local -room new -peers 4

Запустить опубликованный образ напрямую:

docker run --rm -it ghcr.io/kavun-sama/jazztun-server:latest -room new -peers 4

Или использовать готовый compose-файл:

docker compose -f docker-compose.server.yml up --build

Переменные окружения для compose:

  • JAZZTUN_ROOM, по умолчанию new
  • JAZZTUN_KEY
  • JAZZTUN_SESSION
  • JAZZTUN_PEERS, по умолчанию 4
  • JAZZTUN_DNS, по умолчанию 1.1.1.1:53
  • JAZZTUN_SOCKS
  • JAZZTUN_VERBOSE, любое непустое значение включает -v

Пошаговый Запуск

  1. Подготовьте удалённый сервер за пределами РФ.
  2. Скопируйте туда jazztun.
  3. Запустите server на удалённой машине.
  4. Скопируйте из вывода room URL и ключ.
  5. Запустите client локально с тем же room URL и ключом.
  6. Укажите в браузере или приложении локальный SOCKS5-прокси.
  7. Проверьте, что внешний IP совпадает с IP удалённого сервера.

Если комнату использует только одна пара server/client, флаг -session можно не указывать. Если в одной и той же Jazz-комнате должны жить несколько независимых пар, каждой паре нужно своё значение -session, одинаковое на обеих сторонах.

Пример запуска на удалённой машине:

mkdir -p ~/jazztun
cd ~/jazztun
chmod +x ./server
./server -room new -peers 4 -v

Пример запуска клиента локально:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4 -listen 127.0.0.1:1080 -v

Если локальный SOCKS5 должен быть доступен другим устройствам в локальной сети:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -listen 0.0.0.0:1080 -socks-user demo -socks-pass strongpass

Несколько Пар В Одной Комнате

Теперь одна Jazz-комната может нести несколько независимых пар jazztun.

  • один room URL + один ключ + одинаковый -session: одна и та же пара туннеля
  • один room URL + один ключ + разный -session: разные независимые пары
  • один room URL + один ключ + одинаковый -session у двух клиентов одновременно: конфликт, лишний клиент игнорируется

Пример:

./server -room new -peers 2 -session alpha
./client -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 2 -session alpha

Вторая независимая пара в той же комнате:

./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 2 -session beta
./client -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 2 -session beta

Быстрый Старт

Вариант 1: сервер сам создаёт комнату

Сначала запускается сервер:

./server -room new -peers 4 -v

Сервер выведет room URL и сгенерированный ключ.

Потом запускается клиент с тем же room URL и ключом:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4 -v

По умолчанию локальный SOCKS5 слушает 127.0.0.1:1080.

Вариант 2: вход в уже существующую комнату

./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4
./client -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4

Флаги

Типовые команды сервера:

./server -room new -peers 4 -v
./server -room new -peers 4 -session alpha
./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -dns 8.8.8.8:53
./server -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -socks 127.0.0.1:9050

Типовые команды клиента:

.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -peers 4 -v
.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -session alpha -peers 4
.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -listen 127.0.0.1:1081
.\client.exe -room "https://salutejazz.ru/ROOM?psw=..." -key YOUR_KEY -listen 0.0.0.0:1080 -socks-user demo -socks-pass strongpass

Сервер:

  • -room: room URL или new
  • -key: 64-символьный hex-ключ; на сервере может быть сгенерирован автоматически
  • -session: опциональный namespace, если одна Jazz-комната делится между несколькими независимыми парами
  • -duo: быстрый режим на два transport peer-а
  • -peers: количество transport peer-ов; перекрывает -duo; этим флагом обычно настраивается пропускная способность
  • -dns: DNS-резолвер для удалённых lookup, по умолчанию 1.1.1.1:53
  • -socks: upstream SOCKS5-прокси для исходящих подключений сервера
  • -v: подробные логи
  • -version: вывести версию и завершиться

Клиент:

  • -room: один room URL
  • -key: тот же 64-символьный hex-ключ, что и у сервера
  • -session: опциональный namespace; при общем room URL должен совпадать с сервером
  • -listen: адрес локального SOCKS5, по умолчанию 127.0.0.1:1080
  • -socks-user: включает RFC 1929 username/password auth для локального SOCKS5-прокси
  • -socks-pass: пароль для -socks-user
  • -duo: быстрый режим на два transport peer-а
  • -peers: количество transport peer-ов; перекрывает -duo; этим флагом обычно настраивается пропускная способность
  • -v: подробные логи
  • -version: вывести версию и завершиться

Тестирование

Полная проверка:

go test ./...
go vet ./...

Проверка по пакетам:

go test ./internal/crypto -v
go test ./internal/mux -v
go test ./internal/transport/jazz -v

Ручная Проверка

  1. Запустите server.
  2. Запустите client с тем же room URL и ключом.
  3. Проверьте внешний IP через локальный SOCKS5:
curl.exe --socks5-hostname 127.0.0.1:1080 https://ifconfig.me/ip

Если туннель работает, вернётся IP удалённого сервера.

Тест Пропускной Способности

На удалённом сервере:

mkdir -p /root/bench
dd if=/dev/zero of=/root/bench/100m.bin bs=1M count=100 status=none
python3 -m http.server 8088 --directory /root/bench

На клиентской машине:

curl.exe --max-time 15 --socks5-hostname 127.0.0.1:1080 -o NUL -w "speed=%{speed_download} bytes/s time=%{time_total}s code=%{http_code}`n" http://SERVER_IP:8088/100m.bin

Наблюдаемые значения на текущем коде:

  • один поток: примерно 33-43 Mbit/s
  • aggregate throughput на -peers 6 и восьми параллельных загрузках: около 110 Mbit/s

Диагностика

Не принимается room URL:

  • нужен полный invite link, включая ?psw=...

Туннель поднялся, но трафик не идёт:

  • проверьте, что ключ на обеих сторонах одинаковый
  • проверьте, что -session совпадает на обеих сторонах, если вы его используете
  • проверьте, что приложение использует именно SOCKS5, а не HTTP proxy
  • проверьте, что сервер может резолвить и открывать целевой хост

В той же комнате второй клиент не подключается:

  • проверьте, не используют ли оба клиента один и тот же -session
  • один -session соответствует одной логической паре; для независимой второй пары задайте другое значение

Частые reconnect:

  • активные потоки переживают протестированный blackout/reconnect сценарий
  • полный teardown и rebuild peer-а через WatchConnection покрыт тестами; в живом reconnect-тесте восстановление произошло на той же WebRTC-сессии

Проблемы с DNS на сервере:

./server -room new -dns 8.8.8.8:53

Нужно выпускать трафик сервера через другой SOCKS5:

./server -room new -socks 127.0.0.1:9050

About

TCP tunnel over Salute Jazz WebRTC. Routes traffic through video-call infrastructure to bypass VPN blocking. SOCKS5 proxy, AES-256-GCM.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors