Модули¶
dixu_proxy (Elixir / Phoenix)¶
~950 строк, 22 файла. Не использует HEEx/EEx-шаблоны — весь HTML, который рендерит сам прокси (страницы заморозки, офлайн), встроен прямо в строки в коде контроллера (это намеренно: страниц всего несколько, выносить в файлы избыточно).
lib/dixu_proxy/
├── accounts/{user,profile_link}.ex ← Ecto-схемы (read-only с точки зрения прокси, пишет modulauth)
├── application.ex ← supervision tree, порядок старта см. ниже
├── repo.ex ← Ecto.Repo, общая БД с modulauth
├── cache_body_reader.ex ← кэширует тело запроса для повторного чтения (нужно где-то в плагах)
├── catalog_registry.ex ← ETS-кэш slug'ов каталога (status='approved'), обновляется раз в 2 мин
├── frozen_registry.ex ← ETS-кэш замороженных туннелей, грузится из modulauth при старте
├── geo_ip.ex / geo_ip_updater.ex ← офлайн geo-IP (MaxMind), периодическое обновление базы
├── incident_log.ex ← общий журнал банов (TCP + HTTP), см. SECURITY.md
├── metrics_collector.ex ← трафик/визиты/гео по туннелям, флаш в Postgres раз в 60с
├── mailer.ex ← Swoosh, используется по минимуму
└── tcp/tcp_config.ex ← роли/разрешённые TCP-порты на устройство, из БД
lib/dixu_proxy_web/
├── channels/{device_socket,proxy_channel}.ex ← WS-канал устройства, "proxy:{slug}"
├── client_ip.ex ← единая точка доверия X-Forwarded-For (см. SECURITY.md)
├── controllers/
│ ├── proxy_controller.ex ← основной HTTP relay браузер↔устройство
│ ├── internal_controller.ex ← internal API для modulauth (см. ниже)
│ └── error_json.ex
├── http/visit_guard.ex ← анти-скрейпинг/анти-перебор для HTTP-интерстициала
├── plugs/interstitial_plug.ex ← страница "вы переходите на ресурс пользователя" + анти-абуз гейт
├── tcp/{tcp_listener,rate_limiter}.ex ← TCP-relay (7 портов) + защита от перебора/флуда
│ tcp/e2e_raw_listener.ex ← E2E blind-relay (порт 9443): PROXY protocol v1 → SNI → WS-канал без терминации TLS
├── router.ex / endpoint.ex
└── telemetry.ex
Порядок старта (application.ex)¶
Repo → MetricsCollector → GeoIpUpdater → CatalogRegistry → DNSCluster → PubSub → 3×Registry (Device/Request/TcpSession) → Endpoint → Tcp.RateLimiter → Tcp.TcpListener → Tcp.E2eRawListener → Http.VisitGuard, плюс два ETS для кулдауна офлайн-уведомлений и FrozenRegistry.init() создаются вручную в start/2 (не GenServer).
Internal API (вызывается modulauth)¶
internal_controller.ex — без SSL-редиректа, обслуживает запросы от modulauth внутри Docker-сети (не публичный путь). Используется для уведомлений (офлайн/service-down) и аналогичных server-to-server вызовов.
modulauth (Java 22 / Spring Boot 3 WebFlux)¶
~85 Java-файлов. Полностью реактивный стек (WebFlux + R2DBC), сервер-рендеринг через Thymeleaf — никакого отдельного фронтенд-проекта/SPA, весь UI — это шаблоны + статический JS/CSS внутри самого modulauth.
src/main/java/com/dixsu/server/
├── devices/
│ ├── controller/ ← 27 контроллеров: auth, профиль, каталог, короткие ссылки, TCP-порты, верификация соцсетей, админка...
│ ├── service/ ← 17 сервисов: бизнес-логика (auth, email, captcha, OG-парсинг, верификации соцсетей...)
│ ├── model/ ← User, ProfileLink, ShortLink, CatalogEntry, ReservedSlug, UserAuthProvider
│ └── repository/
├── billing/ ← BillingController, TariffService, TinkoffService (платёжный провайдер), SmartBillingScheduler
├── analytics/ ← AnalyticsController (трафик/визиты, PRO/PERS), AnalyticsCleanupScheduler, экспорт данных
├── security/ ← OAuth2-хендлеры, VK custom-filter (Spring OAuth2 для VK "из коробки" не работает)
├── config/ ← SecurityConfig, OAuth2ClientConfig, RedisConfig, WebConfig
├── global/controller/ ← GlobalErrorHandler
└── utils/
Контроллеры — основные группы¶
- Auth:
AuthController,AuthApiController,SmsAuthController,CryptoAuthController(MetaMask),MetamaskAuthController,OAuthUnlinkController - Верификация соцсетей:
GithubVerifyController,TwitterVerifyController,YoutubeVerifyController,RutubeVerifyController— каждая своя цепочка подтверждения владения аккаунтом - Профиль/визитка:
ProfileApiController,PublicProfileController,AvatarController - Туннели:
TunnelController,TunnelCheckController,TcpPortController - Каталог:
CatalogController(подача заявки пользователем),AdminCatalogController(модерация) - Короткие ссылки:
ShortLinkController,LinkInfoController - Отзывы и репутация:
ReviewController(/api/reviews/*— submit, summary, comments, complaints, avg-rating, owner dashboard, approve-owner),OtzovikApiController(агрегированная лента и страницы ресурсов Otzovik). Бизнес-логика —ReviewService(submit с highTrust-флагом, upsert без даунгрейда статуса, publicComments/publicComplaints с LEFT JOIN для анонимных, approveAsOwner, scoreForSlug, summary). - Прочее:
AccountDeletionController,FacebookDataDeletionController(GDPR/комплаенс),ClarityController,LandingController,AdminListsController,AdminReservedSlugController,InternalController
52 Flyway-миграций¶
src/main/resources/db/migration/V1...V52. Ключевые этапы: V19 — каталог (catalog_entries/catalog_categories), V21-V22 — заморозка/роли туннелей, V23-V25 — TCP-порты и reserved slugs, V26/V28 — биллинг (включая Smart Billing Phase 2), V29-V31 — аналитика трафика/визитов/гео, V34-V35 — нормализация email + функциональный индекс на lower(email), V36 — tunnel_incidents, V37 — private_tunnel_invites, V38-V39 — приватный режим (Фаза 1/2), V39 — private_e2e_tokens, V40 — E2E трафик-статистика, V41 — tunnel compression, V42 — npd_settings, V43-V44 — custom domains, V45 — ls_payments (Lemon Squeezy), V46 — email_subscribers, V47-V52 — система отзывов (resource_reviews с анонимными, комментариями, moderation_status; otzovik_* таблицы, звёздный рейтинг).
Шаблоны (Thymeleaf)¶
src/main/resources/templates/ — 29 страниц, общий layout-фрагмент fragments/site-layout.html (шапка/футер/мобильное меню). Подробно про добавление страниц/пунктов меню — guides/editing-frontend.md.
nginx¶
nginx/
├── Dockerfile
├── dixu.conf.template ← HTTP-роутинг по поддоменам, envsubst при старте контейнера
├── stream.conf.template ← TCP stream: ssl_preread + SNI routing для E2E (Фаза 2)
└── docker-entrypoint.sh
stream.conf.template — TCP L4-прокси с ssl_preread on: читает SNI из TLS
ClientHello без терминации и маршрутизирует:
- ~^e2e- → dixu_proxy:9443 (E2eRawListener, blind-relay без терминации TLS)
- всё остальное → 127.0.0.1:8443 (nginx HTTP-блок, обычная TLS-терминация)
Добавляет PROXY protocol v1 (proxy_protocol on) на оба апстрима — восстанавливает
реальный IP клиента через хоп (иначе $remote_addr был бы 127.0.0.1).
TCP-туннели (SSH/RDP/VNC/БД) через stream{} не идут — это маскировало бы
реальный IP от dixu_proxy; они слушаются dixu_proxy напрямую через Docker
port-forwarding (см. SECURITY.md).
dixu.conf.template ставит X-Real-IP/X-Forwarded-For через proxy_set_header ... $proxy_add_x_forwarded_for — важно: эта директива дописывает реальный IP в конец цепочки, а не заменяет заголовок (см. SECURITY.md про связанную с этим уязвимость и её фикс).
device_client (Elixir / OTP — отдельный репозиторий)¶
websocket-client/device_client_app/ — не часть dixsu-infra. Самодостаточный
бинарник (Burrito, 5 платформ) для установки на оборудование пользователя.
Документация — README.md в том репозитории.
lib/
├── device_client.ex ← основной WS-клиент + HTTP-прокси + TCP-relay
└── device_client/
├── application.ex ← OTP Application, парсит аргументы, запускает E2eListener если задан E2E_TOKEN
├── e2e_listener.ex ← локальный TLS-терминатор (127.0.0.1:8443), ACME-driven cert
├── acme.ex ← оркестрация ACME v2 (RFC 8555) flow
└── acme/{jws,csr,dns_api}.ex ← JWK/thumbprint/JWS-подпись ES256, CSR с SAN, DNS-01 helper
Ключевые переменные: SERVER_HOST, SERVER_PORT, CA_CERT_PATH,
E2E_TOKEN, MODULAUTH_URL, ACME_DIRECTORY_URL, E2E_DATA_DIR,
E2E_LOCAL_TLS_PORT.
screenshotter (Node + Playwright)¶
screenshotter/
├── index.js ← Express + headless Chromium, рендерит и сохраняет скриншот лендинга устройства
├── Dockerfile
└── package.json
Делает скриншот лендинга каждого активного туннеля для карточки на интерстициальной странице (InterstitialPlug в dixu_proxy её показывает). Хранит файлы в общем volume modulauth_uploads (SCREENSHOTS_DIR=/uploads/screenshots), обновляет раз в сутки + 10 минут после старта контейнера.
Прочие каталоги в репозитории¶
| Путь | Назначение |
|---|---|
INCIDENT/logs/ |
Журнал банов (volume на прод), см. SECURITY.md. INCIDENT/incident1.md — отдельный, вручную написанный пост-мортем одного инцидента, не связан с автоматическим журналом |
certs/ |
Локальные сертификаты для разработки (в .gitignore, кроме шаблонов) |
TEST/web-server/ |
Тестовая фикстура — простой веб-сервер с загрузками для проверки туннеля локально, не часть прод-системы |
docs/ |
Эта документация |