Архитектура dix.su¶
Стек¶
| Контейнер | Технология | Роль |
|---|---|---|
| nginx | nginx:alpine | TLS-терминация, маршрутизация по поддоменам, единственная точка входа на 80/443 |
| dixu_proxy | Elixir / Phoenix 1.7 | WebSocket-туннель, HTTP- и TCP-проксирование к устройствам, анти-абуз защита |
| modulauth | Java 22 / Spring Boot 3 WebFlux | Авторизация, профили, биллинг, каталог, админка, весь веб-UI |
| postgres | PostgreSQL 17 | Основная БД, общая для modulauth и dixu_proxy (внешний порт 5433) |
| redis | Redis 7 | Сессии Spring Security |
| screenshotter | Node + Playwright | Headless-скриншоты для карточек туннелей на интерстициале |
Все контейнеры — в одной Docker-сети dixsu-net. nginx — единственный сервис, слушающий внешние порты 80/443; dixu_proxy дополнительно слушает напрямую 7 TCP-портов для прямого проксирования протоколов (SSH/RDP/VNC/БД, см. ниже) — это сделано намеренно, не через nginx (см. «Почему TCP не через nginx»).
Репозиторий¶
Единый монорепо gitlab.com:dixsu/infra, ветка prod для всего (включая вложенные modulauth/ и dixu_proxy/ — раньше это были отдельные git-репозитории с разными ветками, сейчас все три — один репозиторий, одна ветка). Деплоится напрямую на прод по SSH, без CI/CD.
dixsu-infra/
├── docker-compose.yml
├── Makefile
├── .env ← секреты, не в git, живёт только на VPS
├── .env.example
├── docs/ ← эта документация
├── nginx/ ← конфиг nginx (шаблоны + entrypoint)
├── modulauth/ ← Java/Spring Boot
├── dixu_proxy/ ← Elixir/Phoenix
├── screenshotter/ ← Node/Playwright
└── INCIDENT/logs/ ← журнал банов (volume, см. SECURITY.md)
Подробности по деплою — DEPLOYMENT.md. Разбор каждого модуля — MODULES.md.
Три публичных сервиса на одном домене¶
| Сервис | URL | Описание |
|---|---|---|
| Прокси-туннель | slug.dix.su |
Локальный сервер пользователя в интернете через WebSocket-туннель |
| Личная визитка | dix.su/p/slug |
Публичная страница с аватаром, ссылками, соцсетями |
| Короткие ссылки | dix.su/код |
Сокращатель URL с авторством и счётчиком кликов |
Поток данных: HTTP-туннель¶
Браузер → nginx:443 → dixu_proxy:4000 (HTTP)
│
├─ InterstitialPlug — анти-абуз гейт + страница "вы переходите на ресурс пользователя"
├─ ProxyController — ищет устройство в DeviceRegistry по slug (поддомен)
│
▼
ProxyChannel (Phoenix Channel "proxy:{slug}")
│ push http_request_start / http_request_chunk* / http_request_end
▼
device_client (на оборудовании пользователя, отдельный проект,
не входит в этот монорепо — устанавливается
как готовый бинарь, см. ARCHITECTURE.md → Device client)
│ Req.request! к локальному серверу устройства
│ http_response_start / http_response_chunk* / http_response_end (стримингом)
▼
ProxyChannel → RequestRegistry → ProxyController → Plug.Conn.chunk → Браузер
Тело запроса/ответа base64-кодируется (Phoenix Channels — JSON, бинарные данные напрямую не передать) и стримится чанками — ни сервер, ни устройство не накапливают тело целиком в памяти (кроме request body на устройстве — намеренный компромисс, устройство контролируется пользователем).
Поток данных: TCP-туннель¶
Помимо HTTP, dixu_proxy проксирует TCP-трафик семи фиксированных протоколов (SSH/2222, RDP/3389, VNC/4900, PostgreSQL/4432, MySQL/4306, Redis/4379, MongoDB/4017) через то же WebSocket-соединение device_client, терминируя TLS самостоятельно (устройству не нужен SSL ни для одного протокола кроме VNC). Подробный протокол по каждому из 7 портов — в dixu_proxy/README.md (разделы «TCP-туннели: порты и роли» и «Протокол TCP-туннеля»).
Что не поддерживается и почему:
- UDP — в принципе. WebSocket работает поверх TCP; UDP-датаграммы не передаются через relay. Это затрагивает Minecraft Bedrock Edition (порт 19132/UDP), многие игровые серверы, DNS и VoIP.
- Произвольные TCP-порты (например, игровые серверы, Minecraft Java/25565) — маршрутизация к конкретному устройству возможна только через TLS SNI: прокси читает
slugиз поля SNI в ClientHello. Протоколы без встроенного TLS (Minecraft, большинство игровых движков) не посылают SNI → прокси не может определить назначение → соединение отклоняется. Добавить новый порт технически несложно, но клиент обязан говорить TLS. - HTTP-панели управления игровым сервером (Pterodactyl и аналоги) — работают через обычный HTTP-туннель без ограничений.
Почему TCP не через nginx¶
dixu_proxy слушает TCP-порты (2222, 3389, 4900, 4432, 4306, 4379, 4017) напрямую через Docker port-forwarding, не через nginx stream-proxy. Раньше было наоборот — nginx терминировал TCP и открывал новое соединение к dixu_proxy, из-за чего прокси видел IP nginx, а не реального клиента, и rate-limiter считал всех клиентов одним IP. См. docs/SECURITY.md и dixu_proxy/README.md раздел 3.
Device client¶
Клиент, который устанавливается на оборудование пользователя (Raspberry Pi, домашний сервер, VPS) и держит WebSocket-соединение с dixu_proxy. Не входит в этот монорепо — отдельный компонент, распространяется как готовый бинарь (Burrito-сборка) через личный кабинет пользователя. Если потребуется работать с его исходниками — уточнить у пользователя расположение репозитория, в dixsu-infra его нет.
Роли и тарифы¶
Иерархия ролей (по возрастанию): SIMPLE → VIP → PRO → PERS → GLAVA (GLAVA — административная роль). Роль определяет доступ к TCP-портам (см. таблицу в dixu_proxy/README.md), доступ к аналитике (PRO/PERS), и сейчас управляется через систему "умного биллинга" — см. BILLING.md.
Текущее состояние и куда смотреть дальше¶
- Полный разбор каждого модуля — MODULES.md
- Деплой и workflow — DEPLOYMENT.md
- Защита от абуза (TCP+HTTP rate-limiting, журнал банов) — SECURITY.md
- Биллинг/тарифы — BILLING.md
- Полная карта фич + известные пробелы (что сделано, что нет) — FEATURES_AND_GAPS.md
- Гайды по типовым задачам — guides/
- Архив устаревших проектных документов (исторические брифы, уже реализованные дизайн-документы) — history/