Перейти к содержимому

Архитектура

Общая схема работы

По умолчанию (локальная tmux + туннель):

Код
Browser (phone)
  |
  | HTTPS
  v
Cloudflare Quick Tunnel
  |
  | HTTP/WS
  v
Local Termbridge server
  |
  | PTY
  v
Tmux session

Прямой режим песочницы (Daytona, без туннеля):

Код
Browser (phone)
  |
  | HTTPS
  v
Daytona preview link
  |
  | HTTP/WS
  v
Termbridge server (sandbox)
  |
  | PTY
  v
Tmux session (sandbox)

Если задана --no-tunnel, Termbridge пропускает Cloudflare и использует указанный вами публичный URL.

Компоненты

Процесс CLI

  • Запускает сервер HTTP, который обслуживает ресурсы UI.
  • Запускает сервер WebSocket для ввода-вывода терминала.
  • Создает один или несколько сеансов tmux (или PTY Daytona).
  • Выдает одноразовые токены для входа.
  • Запускает туннель и следит за ним, если он включен (сейчас Cloudflare).
  • В прямом режиме песочницы запускает Termbridge внутри песочницы и ожидает общий ресурс URL.

Серверная часть терминала

  • Серверная часть tmux: использует node-pty для подключения к tmux и передачи реального ввода с клавиатуры и вывода.
  • Серверная часть Daytona: использует PTY Daytona внутри песочницы.
  • Устанавливает TERM=xterm-256color и COLORTERM=truecolor для полной поддержки цвета.
  • Для tmux отключает строку состояния tmux, чтобы интерфейс UI оставался чистым.

Реестр терминалов

  • Отслеживает доступные сеансы терминала.
  • Предоставляет список для UI и проверяет выбранные идентификаторы терминалов.

Аутентификация и сеанс

  • Одноразовый токен выводится в виде URL и кодируется в коде QR.
  • GET /__tb/s/:token принимает токен и устанавливает сеанс cookie.
  • Для соединений WebSocket требуются действительные cookie сеанса и токен CSRF.
  • Токен CSRF запрашивается через GET /__tb/api/csrf и передается в параметре запроса WebSocket.

Режим прокси

При передаче --proxy <port>:

  • Все маршруты termbridge находятся в префиксе /__tb/
  • Запросы, не относящиеся к /__tb/, проксируются к целевому приложению
  • UI открывает представления Terminal/Preview через переключатель Views
  • В представлении Preview загружается iframe, указывающий на /
  • Соединения WebSocket для HMR перенаправляются к целевому приложению

Безопасность

  • Защита CSRF: для обновления соединений WebSocket требуется токен CSRF, предотвращающий межсайтовый перехват.
  • Ограничения ввода: тело HTTP размером 64KB, сообщение WebSocket размером 1MB, ввод в терминал размером 64KB на сообщение.
  • Ограничение частоты запросов: лимиты для каждого IP при погашении токенов и подключении WebSocket.

Конечные точки API

Все маршруты находятся в префиксе /__tb/, чтобы избежать конфликтов с проксируемыми приложениями:

  • GET /__tb/healthz — проверка работоспособности
  • GET /__tb/s/:token — погашение токена → cookie → перенаправление
  • GET /__tb/api/terminals — список терминалов
  • GET /__tb/api/csrf — получение токена CSRF для WebSocket
  • GET /__tb/api/config — получение конфигурации (proxyPort, devProxyUrl)
  • POST /__tb/api/terminals — создание нового сеанса tmux
  • GET /__tb/app/* — резервный маршрут SPA
  • WS /__tb/ws/terminal/:terminalId?csrf=<token> — потоковая передача ввода-вывода терминала

Когда включен режим прокси:

  • GET / — перенаправляет в проксируемое приложение (или /__tb/app, если отключено)
  • * /* — проксируется к целевому приложению

Протокол WebSocket

Клиент → сервер:

JSON
{ "type": "input", "data": "ls -la" }
{ "type": "resize", "cols": 120, "rows": 32 }
{ "type": "control", "key": "ctrl_c" }

Сервер → клиент:

JSON
{ "type": "output", "data": "..." }
{ "type": "status", "state": "connected" }

Стек UI

  • Vite + TanStack Router
  • xterm.js + дополнение Fit + рендерер WebGL
  • Интерфейс с приоритетом для мобильных устройств и закрепленной панелью ввода
  • Автоматическое переподключение с экспоненциальным увеличением интервала (до 10 попыток)
  • Индикатор состояния соединения