HTTP туннель
Начиная с версии 0.36.0 tuna показывает в терминале полноэкранный интерфейс с лентой запросов, их деталями и повтором.
HTTP туннель открывает доступ из интернета к сайту, API, GraphQL или WebSocket-серверу, запущенному у вас локально. Туннели работают на всех тарифах без ограничения по времени. На бесплатном тарифе доступны динамический адрес и один бесплатный постоянный поддомен.
Быстрый старт
tuna http 8080
В консоли появится публичный HTTPS-адрес вида https://4l7mqf-212-49-103-2.ru.tuna.am — запросы на него попадут в приложение на localhost:8080. Рядом будет ссылка на инспектор запросов, где видно каждый запрос и ответ.
Все флаги с подсказками — в справке:
tuna http --help
У каждого флага есть переменная окружения — см. справочник флагов.
Готовые сценарии
Флаги свободно комбинируются. Несколько типовых задач:
| Задача | Команда |
|---|---|
| Показать сайт заказчику под паролем по постоянному адресу | tuna http 3000 --subdomain=brave-otter-4821 --basic-auth="client:s3cret" |
| Принимать вебхуки GitLab только с верной подписью | tuna http 8080 --subdomain=brave-otter-4821 --verify-webhook=gitlab --verify-webhook-secret=s3cret |
| Открыть API фронтендеру на другом домене | tuna http 8080 --cors --key-auth="dev-key" |
| Проверить вёрстку с телефона | tuna http 5173 --qr |
| Передать коллеге папку с файлами | tuna http --file-server ./share --basic-auth="team:s3cret" |
Открыть сервис, который проверяет заголовок Host | tuna http 11434 --request-header="host:localhost:11434" |
| Опубликовать собранный SPA (React, Vue) | tuna http --file-server-spa ./dist |
В Docker, CI и systemd удобнее передавать те же настройки переменными окружения:
TUNA_TOKEN=tt_*** TUNA_SUBDOMAIN=brave-otter-4821 TUNA_INSPECT=false tuna http 8080
Что можно опубликовать
Первый аргумент tuna http — адрес приложения, которое нужно открыть:
| Аргумент | Куда уйдёт запрос |
|---|---|
8080 | http://localhost:8080 |
localhost:8080, 10.0.0.1:8080 | указанный хост и порт, в том числе другая машина в вашей сети |
https://localhost:443 | приложение, которое само принимает HTTPS |
unix:///run/gunicorn.sock | приложение на unix-сокете |
Вместо адреса можно раздать каталог встроенным сервером: --file-server, --file-server-spa или --webdav.
Приложение на HTTPS
tuna http https://localhost:443
По умолчанию сертификат приложения не проверяется, подойдёт и самоподписанный. Включить проверку — --tls-skip-verify=false.
Unix-сокет
Если приложение принимает HTTP на unix-сокете, как, например, gunicorn, укажите путь к сокету с префиксом unix://:
tuna http unix:///run/gunicorn.sock
Инспектор, повтор запросов и политики трафика работают так же, как с портом. TLS к приложению за сокетом не поддерживается, флаг --tls-skip-verify к нему не применяется. Если приложение не отвечает, на странице ошибки 502 будет указан путь к сокету (unix:///run/gunicorn.sock), а не localhost с портом.
Требования к пути, права доступа и поведение при отсутствии сокета те же, что у TCP-туннеля.
Файловый сервер
Отдаёт файлы из каталога и показывает список файлов:
tuna http --file-server ./
Одностраничное приложение (SPA)
Для собранных одностраничных приложений (React, Vue, Angular): на любой несуществующий путь отдаётся index.html, поэтому работает клиентский роутинг.
tuna http --file-server-spa ./dist
WebDAV
Каталог можно подключить как сетевой диск по протоколу WebDAV — с чтением и записью:
tuna http --webdav ./
Адрес туннеля
| Адрес | Как получить | Тариф |
|---|---|---|
Динамический, 4l7mqf-212-49-103-2.ru.tuna.am | без флагов | любой |
Бесплатный постоянный, brave-otter-4821.ru.tuna.am | --subdomain=<ваш-поддомен> | любой, один на аккаунт |
Любой свободный поддомен, billing.ru.tuna.am | --subdomain=billing | подписка |
Собственный домен, api.example.com | --domain=api.example.com | подписка |
На бесплатном тарифе посетитель из браузера при первом заходе видит страницу-предупреждение о том, что сайт открыт через tuna. API-клиентов и вебхуки она не касается, а пропустить её можно заголовком tuna-skip-browser-warning. Зачем это нужно и как мы в целом боремся с фишингом и вредоносным контентом — на странице Злоупотребления и жалобы.
Динамический адрес
Выдаётся автоматически при каждом запуске и меняется при переподключении. Адрес строится по схеме <случайная-часть>-<ваш-IP>.<локация>.tuna.am: IP-адрес источника виден в ссылке, так что анонимно разместить вредоносный контент не получится — подробнее в разделе Анонимность. В постоянном поддомене IP-адреса нет. Подходит для разовой демонстрации или отладки. Если нужен адрес, который не изменится, — для вебхуков, колбэков платёжных систем, закладки в браузере — используйте постоянный поддомен.
Бесплатный постоянный поддомен
У каждого пользователя есть один постоянный поддомен — бесплатно и на любом тарифе. Имя выдаётся случайно в формате <прилагательное>-<существительное>-<4 цифры>, например brave-otter-4821, и одинаково во всех локациях: brave-otter-4821.ru.tuna.am и brave-otter-4821.nl.tuna.am.
Свой поддомен можно посмотреть в личном кабинете: он отмечен меткой «Бесплатный», рядом готовая команда запуска. Также его подсказывает клиент при запуске туннеля без флагов:
Your permanent free domain: brave-otter-4821.ru.tuna.am. Use it with --subdomain=brave-otter-4821
По умолчанию туннель, как и раньше, получает динамический адрес — постоянный поддомен нужно указать явно:
tuna http 8080 --subdomain=brave-otter-4821
В другой локации:
tuna http 8080 --subdomain=brave-otter-4821 --location=nl
Или полным именем:
tuna http 8080 --domain=brave-otter-4821.ru.tuna.am
Поддомен привязан к вашему аккаунту, поэтому клиент должен быть авторизован вашим токеном. Сохраните его один раз командой tuna login или tuna config save-token <ТОКЕН> (токен есть на отдельной странице), либо передавайте через переменную окружения TUNA_TOKEN — например, в Docker и CI. Без токена или с токеном другого аккаунта поддомен не заработает.
- Выбрать или сменить имя нельзя — поддомен с любым именем доступен по подписке.
- Удалить поддомен или передать его другому пользователю нельзя,
tuna domain clearего пропускает. - При смене тарифа поддомен сохраняется и не расходует лимит доменов подписки.
- Если вы зарегистрировались раньше, поддомен появится при первом открытии раздела Домены или при первом запуске туннеля без флагов.
Зарезервированный поддомен
По подписке можно занять любой свободный поддомен — после перезапуска туннеля адрес останется прежним:
tuna http 8080 --subdomain=billing
То же через переменную окружения:
TUNA_SUBDOMAIN="billing" tuna http 8080
Поддомен резервируется автоматически при первом запуске с флагом. Все ваши домены — в личном кабинете.
Ошибка Domain already reserved означает, что поддомен в этой локации уже занят другим пользователем — выберите другое имя.
Собственный домен
Добавьте свой домен следуя инструкциям в личном кабинете, после проверки DNS и выпуска Let's Encrypt сертификата можно пользоваться:
tuna http 8080 --domain=my-api-project.example.com
Пошагово — в статье Подключение своего домена.
Локация
Туннель поднимается в локации ru, если не указано иное. Выберите ближайшую к пользователям сайта:
tuna http 8080 --location=nl
QR-код
Флаг --qr печатает в консоли QR-код со ссылкой на туннель — удобно, чтобы открыть сайт на телефоне.
tuna http 5173 --qr
Защита доступа
Туннель доступен всему интернету. Проверки ниже выполняются в клиенте tuna — запрос, который их не прошёл, до приложения не дойдёт.
| Флаг | Кого пропускает |
|---|---|
--basic-auth | знающих логин и пароль |
--key-auth | запросы с ключом в заголовке X-Token |
--cidr-allow, --cidr-deny | запросы из разрешённых подсетей |
--ua-allow, --ua-deny | запросы с подходящим User-Agent |
--verify-webhook | вебхуки с верной подписью |
--rate-limit | не больше N запросов в секунду |
--https-redirect | только HTTPS, HTTP перенаправляется |
Флаги со списками (--basic-auth, --key-auth, --cidr-*, --ua-*, --*-header) можно повторять. В переменных окружения значения перечисляются через запятую.
Пароль (basic auth)
Браузер покажет окно ввода логина и пароля:
tuna http 8080 --basic-auth="login:password"
Несколько пользователей — повторите флаг:
tuna http 8080 --basic-auth="anna:pass1" --basic-auth="ivan:pass2"
Из скрипта:
curl -u login:password https://brave-otter-4821.ru.tuna.am/
Ключ в заголовке (API token)
Для API и сервисов без браузера. Запрос пройдёт, только если в заголовке X-Token передан один из ключей:
tuna http 8080 --key-auth="my-secret-key"
curl -H "X-Token: my-secret-key" https://brave-otter-4821.ru.tuna.am/
Доступ по подсетям IP
Белый список подсетей в CIDR-формате — остальным доступ закрыт:
tuna http 8080 --cidr-allow="203.0.113.0/24" --cidr-allow="198.51.100.7/32"
Или, наоборот, закрыть доступ отдельным подсетям:
tuna http 8080 --cidr-deny="10.0.0.1/32"
Доступ по User-Agent
Совпадение ищется по подстроке. Запретить curl и разрешить всех остальных:
tuna http 8080 --ua-deny=curl
Разрешить только Chrome:
tuna http 8080 --ua-allow=Chrome
User-Agent легко подделать — используйте этот фильтр против ботов и случайных сканеров, а не как защиту.
Проверка подписи вебхуков
tuna пропустит только вебхуки, подписанные секретом, который вы задали у провайдера. Остальные запросы получат 401 Unauthorized.
tuna http 8080 --verify-webhook=gitlab --verify-webhook-secret=1234
Поддерживаемые провайдеры: gitlab, github, sentry, linear. Для других сервисов и более сложной логики используйте политики трафика.
Ограничение частоты запросов (rate limit)
Защитит локальное приложение от перегрузки — не больше N запросов в секунду:
tuna http 8080 --rate-limit=2
При превышении лимита клиент получит 429 Too Many Requests.
Только HTTPS
Туннель по умолчанию отвечает и по HTTP, и по HTTPS. С флагом --https-redirect запросы по HTTP перенаправляются на HTTPS:
tuna http 8080 --https-redirect
Заголовки и CORS
Заголовки запроса
Добавить или заменить заголовок до того, как запрос попадёт в приложение. Частый случай — сервис принимает запросы только со «своим» Host, как Ollama или dev-серверы:
tuna http 11434 --request-header="host:localhost:11434"
Заголовки ответа
Добавить или заменить заголовок в ответе клиенту:
tuna http 8080 --response-header="env:test" --response-header="x-robots-tag:noindex"
CORS
Флаг --cors или переменная TUNA_CORS=true добавит CORS заголовки ко всем ответам. По умолчанию выставляются следующие заголовки:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Accept, Accept-Language, Content-Language, Origin
Access-Control-Allow-Methods: GET, HEAD, POST
Access-Control-Allow-Origin: *
Их можно переопределить с помощью флага --response-header.
Запросы типа OPTIONS обрабатываются автоматически 200 OK, не доходя до проксируемого сервера.
Если у вас возникают сложности в работе с CORS, рекомендуем ознакомиться с данной статьёй. Так же рекомендуем CORS Tester для проверки ваших CORS заголовков.
Другие возможности
Политики трафика
Когда флагов не хватает — маршрутизация по путям, условия, свои ответы — опишите правила в файле политик трафика. По умолчанию читается .tuna.yml из текущего каталога, другой путь — --policy-file. Флаг --policy-url загружает правила по ссылке. Ошибка в политике останавливает запуск туннеля, подробнее — в разделе Ошибки политики.
Инспектор запросов
Включён по умолчанию и доступен на http://127.0.0.1:4040. Инспектор хранит запросы в памяти, поэтому на серверах и встраиваемых устройствах его лучше выключать: --inspect=false. Подробнее — на странице инспектора.
Отчёты об ошибках
Флаг --capture-key встраивает в HTML-страницы виджет отчётов: тестировщик отправляет баг со скриншотом, не меняя код сайта.
tuna http 3000 --capture-key=YOUR_CAPTURE_KEY
Токен
Обычно токен сохраняется один раз командой tuna login. Указать другой токен можно флагом --token или переменной TUNA_TOKEN, переопределение идёт по очерёдности конфигурации:
tuna http 8080 --token=tt_***
Справочник флагов
| Флаг | Переменная окружения | Описание |
|---|---|---|
-s, --subdomain | TUNA_SUBDOMAIN | Поддомен в зоне tuna.am |
-d, --domain | TUNA_DOMAIN | Полное имя домена |
-l, --location | TUNA_LOCATION | Локация: ru (по умолчанию), nl |
-f, --file-server | TUNA_FILE_SERVER | Раздать каталог |
-F, --file-server-spa | TUNA_FILE_SERVER_SPA | Раздать SPA |
--webdav | TUNA_WEBDAV | WebDAV-сервер для каталога |
--basic-auth | TUNA_BASIC_AUTH | Логин и пароль, login:password |
--key-auth | TUNA_KEY_AUTH | Ключ в заголовке X-Token |
--cidr-allow | TUNA_CIDR_ALLOW | Разрешённые подсети |
--cidr-deny | TUNA_CIDR_DENY | Запрещённые подсети |
--ua-allow | TUNA_UA_ALLOW | Разрешённые User-Agent |
--ua-deny | TUNA_UA_DENY | Запрещённые User-Agent |
--verify-webhook | TUNA_VERIFY_WEBHOOK | Провайдер вебхуков |
--verify-webhook-secret | TUNA_VERIFY_WEBHOOK_SECRET | Секрет подписи вебхуков |
--rate-limit | TUNA_RATE_LIMIT | Запросов в секунду |
--https-redirect | TUNA_HTTPS_REDIRECT | Перенаправлять HTTP на HTTPS |
--request-header | TUNA_REQUEST_HEADER | Заголовок запроса, key:value |
--response-header | TUNA_RESPONSE_HEADER | Заголовок ответа, key:value |
--cors | TUNA_CORS | CORS-заголовки и ответ на OPTIONS |
--policy-file | TUNA_POLICY_FILE | Файл политик, по умолчанию .tuna.yml |
--policy-url | TUNA_POLICY_URL | Ссылка на политики, только https |
--inspect | TUNA_INSPECT | Инспектор, по умолчанию включён |
--tls-skip-verify | TUNA_TLS_SKIP_VERIFY | Не проверять сертификат приложения, по умолчанию true |
--qr | TUNA_QR_CODE | QR-код со ссылкой |
--capture-key | TUNA_CAPTURE_KEY | Виджет отчётов |
--token | TUNA_TOKEN | Токен авторизации |
Поведение
Hop-by-hop
НЕ поддерживаются hop-by-hop заголовки за исключением заголовка Connection: upgrade, необходимого для работы Websocket соединений.
WebSocket
Поддерживается протокол с двусторонним соединением между клиентом (например, браузером) и сервером, дополнительные настройки не требуются. Передаваемые данные НЕ будут отображены в инспекторе.
Server-sent events
Поддерживается технология отправки уведомлений от сервера к веб-браузеру, никакие дополнительные настройки не требуются. Передаваемые данные НЕ будут отображены в инспекторе.
При включенном инспекторе важно, что бы клиент отправлял заголовок Accept: text/event-stream, иначе инспектор будет пытаться перехватить запрос и это вызовет задержки. Браузер передаёт этот заголовок по умолчанию.
HTTP и HTTPS
При старте туннеля отображается ссылка на HTTPS, но обращаться можно и по HTTP. Запретить обращение по HTTP можно добавив флаг --https-redirect.
Порядок обработки флагов и правил
Флаги влияющие на поведение обработки трафика всегда выполняются в определённой последовательности, вне зависимости от того в какой очерёдности они переданы в аргументах.
- https-redirect
- cors
- cidr-allow
- cidr-deny
- ua-allow
- ua-deny
- rate-limit
- key-auth
- basic-auth
- policy-file / policy-url
- verify-webhook
- request-header
- response-header
Самостоятельное управление CORS заголовками
Если вы хотите управлять CORS заголовками самостоятельно на нижестоящем сервере и при этом используете авторизацию в tuna при помощи --basic-auth или --key-auth.
То Preflight запросы - не будут работать, так как эти OPTIONS запросы не содержат Authorization, X-Token и любые другие специфичные заголовки.
Решение на выбор:
- Не использовать авторизацию в tuna.
- Управлять CORS заголовками в tuna, а не самостоятельно.
- Обрабатывать
OPTIONSи авторизацию отдельно при помощи более гибких политик трафика.


