HTTP- и HTTPS-туннели
HTTP- и HTTPS-туннели принимают запросы по публичному адресу ForTunnels и направляют их на локальный хост и порт, указанные при создании туннеля.
Описание
Общее описание функционала
Функциональность отвечает за публичный доступ к вашим HTTP- и HTTPS-приложениям через туннель: внешний клиент обращается к поддомену URL туннеля на домене сервиса (например label.fortunnels.ru), а запрос перенаправляется на целевой хост и порт, который вы указали при создании туннеля. Для одноуровневого поддомена URL туннеля на домене сервиса для туннелей зарегистрированных пользователей нужен владелец, администратор или гостевой туннель; сессия или токен должны позволять сервису определить пользователя (cookie сессии на родительском домене или Authorization: Bearer). Для привязанного пользовательского домена по-прежнему допускается публичный доступ по знанию имени хоста — без проверки владения сессией, как «ссылка-возможность»; после этого по-прежнему применяются списки доступа по IP, лимиты и тариф. Проверка владельца, гостевого режима и администратора для поддомена на домене сервиса выполняется до списков доступа по IP и лимитов. Сервис проверяет, существует ли туннель и разрешён ли запрос. Дополнительно могут применяться ограничения по IP, частоте запросов и условиям тарифа (квоты и включённые возможности). При недоступности целевого приложения или срабатывании ограничений клиент получает понятный по смыслу ответ об ошибке вместо успешного ответа от вашего приложения.
Если обязательный скрипт, стиль, сетевое соединение или другой критичный ресурс заблокирован политикой Content Security Policy (CSP) самого приложения, Fortunnels может показать в этом браузере отдельную страницу с объяснением. Политика приложения при этом остаётся неизменной: исправлять её нужно в самом приложении.
Как пользователь может использовать
- Разработчик поднимает API или веб-интерфейс локально и открывает его коллегам или тестовой среде по выданному URL туннеля, не выставляя машину в интернет напрямую.
- Интегратор проверяет вебхуки или OAuth-редиректы: внешний сервис шлёт запросы на адрес туннеля, а трафик доходит до локального стенда.
- Владелец туннеля делится URL туннеля на поддомене сервиса с коллегами и интеграциями.
- Владелец на платном тарифе в дашборде туннелей переключает колонку «Публичный», чтобы скрыть HTTP/HTTPS-туннель от анонимных посетителей или снова открыть его; подробнее — приватные HTTP-туннели.
- Для приложений на Next.js и похожих SPA URL туннеля на поддомене обычно работает прозрачно для типовых запросов, включая загрузку
_next-ресурсов,fetch,WebSocket,EventSourceиsendBeacon. - Пользователь с гостевым туннелем (доступный всем) демонстрирует прототип заказчикам без входа в аккаунт у них; при этом приватные туннели остаются доступны только владельцу и уполномоченным ролям.
- Администратор в личном кабинете (
/dashboard/tunnels) видит в списке только свои туннели; полный обзор всех пользователей — в админ-консоли на выделенном админ-хосте. Отладка чужого туннеля через Inspector по прямой ссылке из админ-консоли по-прежнему доступна. - Клиент API или скрипт автоматизации дергает те же URL туннелей, что и браузер, для проверки поведения за прокси (заголовки, редиректы, тело ответа).
- Разработчик видит пустую или неполную страницу из-за CSP, перезагружает её после отправки отчёта браузером и получает понятную диагностику. После исправления политики кнопка Try again возвращает его на тот же адрес туннеля.
- Пользователь сталкивается с временной приостановкой туннеля и видит, что сервис недоступен до возобновления, вместо устаревшего ответа.
- Владелец плана с лимитами отслеживает, что при исчерпании квоты или отключённой возможности запросы к туннелю отклоняются с явным сигналом, а не проксируются «в никуда».
- Пользователь с ограничениями по IP или частоте запросов понимает по ответу сервиса, что доступ временно или постоянно ограничён политикой безопасности или защитой от злоупотреблений.
- Посетитель основного сайта сервиса и посетитель URL туннеля получают согласованное поведение по протоколу (например, ожидаемые редиректы на HTTPS там, где это задумано продуктом).
- Поддерживаются долгоживущие соединения WebSocket через тот же обратный прокси, при условии корректных таймаутов на публичном входе.
- Если приложение критически зависит от service worker, офлайн-кэша или фонового перехвата запросов, убедитесь, что оно корректно обслуживается с корневого пути на выданном публичном хосте.
- Нужны формализованные истории уровня продукта — см. пользовательские истории HTTP/HTTPS.
Как это реализовано в сервисе
Входящий HTTP-запрос сначала попадает на публичную точку входа: по заголовку Host определяется, к какому туннелю относится запрос; затем проверяется, что туннель существует и находится в состоянии, допускающем обработку. Для одноуровневого поддомена на домене сервиса (URL туннеля вида label.<домен_сервиса>) для туннелей с владельцем выполняется проверка доступа (владелец, гость, администратор) до списков доступа по IP. Для хоста, привязанного как пользовательский домен, публичный доступ по знанию имени хоста сохраняется; затем по-прежнему применяются списки доступа по IP, лимиты и тарифные проверки владельца. В API списков и чтения туннелей для гостей может использоваться скрытие факта существования чужих туннелей (404), что не отменяет описанную модель прокси. После этого учитываются сетевые списки доступа, ограничение интенсивности запросов и условия тарифа владельца. Если все проверки пройдены, сервис пересылает запрос на целевой адрес туннеля и возвращает ответ приложения. При ошибке маршрутизации, доступа, лимита, подключения или тайм-ауте ответ формирует Fortunnels.
Для CSP-диагностики сервис добавляет к подходящему HTML-ответу отдельную политику только для отчётов и не меняет политику, которую применяет браузер. После критичного нарушения браузер асинхронно отправляет отчёт. Следующая перезагрузка или переход верхнего уровня в том же браузере может получить диагностическую страницу. Другие браузеры продолжают получать исходный ответ приложения, даже если его CSP мешает отображению; запросы к API, ресурсам и WebSocket также не заменяются этой страницей.
Как использовать через CLI-клиент
HTTP- или HTTPS-туннель запускается из CLI с указанием локального адреса приложения. Краткая форма — порт как позиционный аргумент; для неё клиент использует localhost:<порт>. Явный адрес через -local сохраняется без изменений.
Пример для локального веб-сервера на порту 8080:
fortunnels http 8080
или:
fortunnels -protocol http -local 127.0.0.1:8080
Если приложение слушает только IPv6, подойдут ./bin/client http localhost:4321 или ./bin/client -protocol http -local '[::1]:4321'.
После успешного создания клиент выводит URL туннеля; процесс остаётся активным, пока вы его не остановите. Для доступа от имени аккаунта передайте токен (-token), логин и пароль (-login) или заранее сохраните CLI-токен (fortunnels config add-authtoken …). Режим отслеживания состояния туннеля — флаг -watch. Полный перечень флагов транспорта и протоколов — в документации CLI-клиента.
Справочник API
Публичное проксирование
GET https://{subdomain}.{domain}/*— проксирование HTTP-запросов к целевому туннелю по поддомену из URL туннеля (в ответе API — полеpublic_url)GET https://{custom_domain}/*— маршрутизация по привязанному пользовательскому домену
Поддерживаются все HTTP-методы (GET, POST, PUT, DELETE и др.). Заголовки, тело и параметры запроса сохраняются при пересылке.
Управление туннелями (API)
POST /api/tunnels— создание туннеля с протоколом HTTP/HTTPSGET /api/tunnels?id=<id>— получение информации о туннеле (илиGET /api/tunnelsсо списком)PATCH /api/tunnels— обновление конфигурации туннеля; в теле JSON укажитеidи действие (пауза, транспорт, TLS, регенерация URL, редиректы и т.д.)DELETE /api/tunnels?id=<id>— удаление туннеля
Для HTTP/HTTPS-туннелей поддерживается действие set_public_subdomain: в теле JSON указываются id, action: "set_public_subdomain" и поле public_subdomain (метка поддомена). Ограничения: валидация метки, уникальность хоста, зарезервированные имена, при включённых тарифах — возможность custom-public-subdomain, отдельный лимит частоты смены метки, максимальный размер тела PATCH. Коды ответов: см. раздел Ошибки возможности «Свой поддомен» в документации.
Для зарегистрированных пользователей с тарифными планами при создании туннеля возможны ответы 403 с JSON-кодами: user_suspended (аккаунт заблокирован) или quota_exceeded с полем quota: max_concurrent_tunnels (превышен лимит одновременных туннелей). Поле expires_at в ответе может отражать ограничение срока жизни туннеля по плану.
Запрос создания туннеля
{
"protocol": "http",
"target_addr": "127.0.0.1:8000"
}
Владелец определяется сессией или Bearer-токеном; идентификатор владельца не передаётся клиентом в теле запроса.
Ответ создания туннеля
{
"id": "a1b2c3d4e5f6g7h8",
"protocol": "http",
"target_addr": "127.0.0.1:8000",
"public_url": "http://xyz789.fortunnels.ru",
"created_at": "2024-01-01T12:00:00Z",
"expires_at": "2024-01-01T14:00:00Z"
}
Поддомен URL туннеля генерируется независимо от id туннеля для повышения безопасности (в ответе API — поле public_url).
Список и детали туннеля (GET /api/tunnels, GET /api/tunnels?id=<id>)
Ответ списка и одиночного туннеля включает поля created_at, expires_at, bytes_used, traffic_limit_bytes и объект limit_indicators — компактные индикаторы лимитов для интерфейса (без отдельного запроса на строку).
limit_indicators
| Поле | Описание |
|------|----------|
| as_of | Момент расчёта на сервере (RFC3339) |
| lifetime | Оставшееся время жизни туннеля из created_at / expires_at |
| traffic | Per-tunnel трафик из bytes_used / traffic_limit_bytes (для гостевых туннелей); для зарегистрированных владельцев — unavailable (месячный egress аккаунта не показывается как per-tunnel cap) |
| http_rpm | Оставшаяся ёмкость HTTP-запросов в минуту по плану в текущем окне |
Состояния каждого индикатора: limited, unlimited, unavailable, zero_limit, exhausted, expired.
Снимок http_rpm носит информационный характер и не расходует лимит запросов при чтении; фактическое ограничение применяется при обработке HTTP-запросов к туннелю.
Для не-админов поля user_id и owner_login по-прежнему опускаются в теле туннеля; limit_indicators не содержит owner/account/plan идентификаторов.
Область списка для администратора
Один и тот же endpoint GET /api/tunnels возвращает разный набор туннелей в зависимости от того, откуда администратор открыл интерфейс:
| Контекст | Где в продукте | Что в списке |
|----------|----------------|--------------|
| Личный кабинет | /dashboard/tunnels на основном домене | Только туннели, принадлежащие этому администратору (как у обычного пользователя) |
| Админ-консоль | /tunnels на выделенном админ-хосте (например admin.fortunnels.ru; в локальной разработке — /admin/tunnels) | Все туннели всех пользователей |
В личном кабинете администратор не видит чужие туннели в списке, счётчиках и пагинации. В админ-консоли по-прежнему доступен полный обзор флота; в списке для чужих туннелей могут отображаться поля владельца (owner_login, user_id).
Исключение: открытие конкретного туннеля или Inspector по прямой ссылке (в том числе переход из админ-консоли на /dashboard/tunnels/{id}/inspector для чужого туннеля) по-прежнему разрешено администратору — это не расширяет список в личном кабинете.
CLI и прочие API-клиенты без контекста админ-консоли получают лично-кабинетный список (только свои туннели).
Пример фрагмента:
{
"limit_indicators": {
"as_of": "2026-06-05T12:00:00Z",
"lifetime": {
"state": "limited",
"used_seconds": 120,
"remaining_seconds": 480,
"total_seconds": 600,
"reset_at": "2026-06-05T14:00:00Z"
},
"traffic": {
"state": "limited",
"used_bytes": 256,
"remaining_bytes": 768,
"total_bytes": 1024
},
"http_rpm": {
"state": "limited",
"used_requests": 3,
"remaining_requests": 7,
"total_requests": 10,
"reset_at": "2026-06-05T12:01:00Z"
}
}
}
Поле remaining_requests в http_rpm — оставшаяся ёмкость HTTP requests/min в текущем окне (не current_http_requests_per_minute).
Ошибки
413 Payload Too Large
Когда возникает: Тело запроса PATCH /api/tunnels/{id} превышает лимит размера (внутренний порог для JSON-действий с туннелем).
Что делать: Уменьшить тело запроса; для set_public_subdomain достаточно компактного JSON с полями id, action, public_subdomain.
400 Bad Request
Когда возникает: Невалидный формат ID туннеля, некорректный запрос, попытки path traversal (../ в путях), невалидная метка public_subdomain, зарезервированное имя поддомена, действие только для HTTP/HTTPS.
Что делать: Проверить корректность URL и ID туннеля. Убедиться, что путь не содержит недопустимых последовательностей.
403 Forbidden
Когда возникает: ACL запретил доступ, требуется аутентификация, пользователь обращается к чужому туннелю.
Что делать: Проверить права доступа и настройки ACL туннеля. Убедиться, что аутентификация валидна и пользователь имеет право доступа к туннелю.
404 Not Found
Когда возникает: Туннель не найден, невалидный путь или ID туннеля.
Что делать: Проверить корректность ID туннеля и URL. Убедиться, что туннель существует и не истёк.
429 Too Many Requests
Когда возникает: Превышен лимит запросов (глобальный, на пользователя или на туннель).
Что делать: Снизить частоту запросов. Заголовок Retry-After указывает, когда можно повторить запрос.
502 Bad Gateway
Когда возникает: Целевой сервис недоступен, подключение не удалось или истёк таймаут. Сообщение connection refused часто означает, что адрес выбран не для той версии IP: приложение может слушать ::1, но не 127.0.0.1. Ещё один случай — диагностическая страница после того, как этот браузер сообщил о критичном нарушении CSP приложения.
Что делать: Убедиться, что локальный сервис запущен и доступен по адресу туннеля. Сравните:
curl -I http://localhost:<порт>/
curl -I http://127.0.0.1:<порт>/
Если первый запрос успешен, а второй нет, создайте HTTP-, HTTPS- или TCP-туннель с localhost:<порт> либо явно укажите [::1]:<порт>. Туннель остаётся активным; ответ 502 временный, и следующий публичный запрос повторит подключение после восстановления приложения.
Если на странице указана CSP-ошибка, проверьте названную директиву и разрешённый источник в настройках самого приложения. Затем нажмите Try again. Кнопка сбрасывает отметку только для текущего браузера и возвращает на тот же адрес туннеля. Если политика исправлена, приложение загрузится; Fortunnels не отключает и не ослабляет CSP. Другой браузер эта отметка не затрагивает.
503 Service Unavailable
Когда возникает: Туннель приостановлен; туннель возобновлён в панели, но клиент ещё не переподключился («Туннель возобновляется»); или временные проблемы на стороне сервера.
Что делать: Проверить статус туннеля через API. Если туннель возобновлён — подождать несколько секунд (клиент переподключается после паузы). Возобновить туннель при необходимости.
504 Gateway Timeout
Когда возникает: Превышен таймаут запроса к целевому сервису.
Что делать: Проверить доступность и нагрузку локального сервиса. Увеличить таймаут в конфигурации туннеля при необходимости.
Ограничения
- Доступность туннеля зависит от состояния локального приложения и сетевого соединения клиента.
- Долгоживущие WebSocket-соединения зависят от таймаутов клиента, сервиса и целевого приложения.
- Приложения, которые жёстко ожидают корневой путь исходного домена или используют service worker, могут требовать отдельной настройки; для таких случаев предпочтительнее отдельный публичный хост.
- Ограничения тарифа, частоты запросов, размера запроса и IP-доступа применяются до передачи запроса в локальное приложение.
- CSP-диагностика работает по принципу «сначала отчёт, затем перезагрузка». Отчёт отправляется асинхронно, поэтому первый показ страницы может остаться пустым или неполным. Диагностика появляется при следующей перезагрузке или другом переходе верхнего уровня в том же браузере.
- В текущей версии учитывается только применяемая браузером CSP из заголовка ответа подходящей HTML-страницы. Политика, заданная только через HTML-метатег, и отдельная политика только для отчётов сами по себе не включают диагностику.
- Диагностическая страница предназначена только для переходов верхнего уровня. Фреймы, скачивания, перенаправления, API-запросы, ресурсы страницы и WebSocket-соединения продолжают обрабатываться как обычно.
- Диагностика поддерживает директивы скриптов
script-src,script-src-elemиscript-src-attr; стилейstyle-src,style-src-elemиstyle-src-attr; соединенийconnect-src; фоновых процессовworker-src; а такжеrequire-trusted-types-forиtrusted-types. Резервная директиваchild-srcучитывается только тогда, когда браузер связывает нарушение сworker-src. Другие нарушения, например блокировка необязательного изображения или шрифта, не включают диагностическую страницу. - Состояние диагностики хранится только в браузере, который отправил отчёт. Оно не отключает туннель для остальных посетителей и не меняет CSP приложения.