Публикация через WAF и AntiDDoS¶
Публикация через WAF и AntiDDoS — публикация клиентского порта сервера RuDesktop наружу через средства веб-защиты (WAF, AntiDDoS и подобные узлы очистки трафика). Раздел описывает рекомендуемые режимы работы защитного решения (TCP passthrough / L7), требования к публикуемым эндпоинтам, типичные ошибки разделения портов, пример конфигурации Nginx на бэкенде и приёмы диагностики
Важно
Раздел применим только при работе с локальным сервером RuDesktop, развёрнутым внутри периметра организации с внешним защитным узлом перед ним
Общий принцип¶
Клиент RuDesktop использует один клиентский адрес и порт не только для WebSocket, но и для служебных HTTPS API-запросов. Через клиентский порт должны проходить:
/v1/— WebSocket/WSS, основной клиентский канал/api/login/— авторизация пользователя/api/logout/— выход из учётной записи/api/ssolist/— получение списка SSO-доменов/api/user/— информация об авторизованном пользователе/api/client-settings/— клиентские настройки/api/banner/— баннер в клиенте/api/ab/load/— загрузка адресной книги/root.pem— публичный CA-сертификат сервера RuDesktop/download/— загрузка дистрибутива клиента, если используется
Важно
Нельзя публиковать наружу только /v1/ как отдельный WebSocket-порт, если остальные API остаются на другом порту. Клиент RuDesktop не разделяет автоматически «API-порт» и «WSS-порт»: если в клиенте указан server.example.ru:8443, то и /v1/, и /api/..., и /root.pem будут запрашиваться через 8443
Рекомендуемый вариант — TCP passthrough¶
Если WAF/AntiDDoS некорректно обрабатывает WebSocket или смешанный трафик HTTP + WebSocket, рекомендуется публиковать весь клиентский порт RuDesktop в одном из режимов TCP proxy / RAW / L4 passthrough / TLS passthrough
Защитное решение в этом режиме не должно:
разбирать HTTP- и WebSocket-протоколы;
менять методы, заголовки или тело запроса;
инспектировать трафик как обычный короткий HTTP-запрос.
Оно должно передавать TCP-трафик до backend как есть
Рабочая схема:
Клиент RuDesktop
↓
WAF, AntiDDoS (TCP proxy / RAW / L4 passthrough)
↓
Reverse proxy (Nginx, UserGate, HAProxy)
↓
Сервер RuDesktop
Подсказка
В этом режиме TLS обычно завершается уже на backend-стороне — на встроенном Nginx сервера RuDesktop или на собственном обратном прокси
Когда можно использовать L7¶
L7-режим допустим только если WAF/AntiDDoS умеет на одном listener (порту) корректно пропускать одновременно:
обычные HTTPS API-запросы (
/api/...,/root.pemи другие);WebSocket Upgrade на
/v1/.
Для /v1/ клиент отправляет:
GET /v1/ HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Успешный ответ сервера:
101 Switching Protocols
Примечание
HAProxy в штатной схеме умеет переводить HTTP-соединение в WebSocket-туннель после upgrade, но для таких соединений критичны корректные заголовки и таймауты. Готовый пример конфигурации — в разделе Развёртывание за обратным прокси
При работе через L7 защитное решение обязательно должно:
не менять HTTP-метод для
/v1/— серверный компонентrudeпринимает на этом пути толькоGETсUpgrade: websocket, прочие методы (POST,HEAD,OPTIONS) возвращают404 Not Found;не делать healthcheck на
/v1/— обычныйGETбез WebSocket-заголовков возвращает400 Bad Request. Для health-проб используйтеGET /на бэкендеrude(отдаётOK) илиGET /root.pemна nginx-vhost;не инспектировать
/v1/как короткий HTTP-запрос — WebSocket-сессия может жить часами;увеличить таймауты для долгоживущих WebSocket-сессий (рекомендуемые значения —
proxy_send_timeout 600s,proxy_read_timeout 600s);передавать без модификации заголовки
UpgradeиConnection;передавать заголовки
Host,X-Real-Ip(в формате$remote_addr:$remote_port),X-Forwarded-For,X-Forwarded-Proto.
Важно
Если L7-решение не умеет корректно пропускать WebSocket — его нужно переводить в режим TCP/L4. Это типовой подход: не все reverse proxy корректно поддерживают WebSocket, и в таких случаях TCP mode — рабочая альтернатива
Разделение портов RuDesktop¶
Разделение портов между админкой и клиентским трафиком — поддерживаемый сценарий (см. Разделение портов), но критически важно правильно распределить эндпоинты по портам
Правильно:
443— веб-интерфейс администратора, доступен только внутри сети или через VPN;8443— клиентский порт RuDesktop, публикуется наружу через WAF/AntiDDoS.
На клиентском порту 8443 обязательно должны быть доступны:
/v1//api/login//api/logout//api/ssolist//api/user//api/client-settings//api/banner//api/ab/load//root.pem/download/— если используется загрузка дистрибутивов через клиентский порт
Неправильно:
443— API;8443— только/v1/WebSocket.
Такой вариант приведёт к ошибкам авторизации, получения настроек, адресной книги и SSO: клиент запросит /api/login/ через 8443, не получит ответа и не сможет залогиниться
Пример backend Nginx для клиентского порта¶
Условный пример, который можно адаптировать под конкретную установку:
server {
listen 8443 ssl;
server_name rd.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/private.key;
client_max_body_size 1000G;
location /v1/ {
proxy_pass http://unix:/run/rudesktop/rude.sock;
proxy_connect_timeout 120s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-Ip $remote_addr:$remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api/ {
include proxy_params;
# Для сценария «двойной прокси» (WAF/AntiDDoS перед nginx) переопределяем
# X-Forwarded-For, чтобы сохранить цепочку IP, добавленную защитным узлом
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://unix:/run/rudesktop-web.sock;
}
location /root.pem {
expires -1;
alias /var/lib/rudesktop/ca/CA.pem;
}
location /download/ {
alias /usr/share/rudesktop/public/download/;
}
include rudesktop_params;
}
Важно
Для /v1/ заголовок X-Real-Ip должен передаваться в формате $remote_addr:$remote_port — с указанием порта источника. Серверный компонент rude парсит это значение как SocketAddr и при отсутствии порта отбивает соединение с ошибкой Failed to parse X-Real-IP. Для остальных эндпоинтов (/api/, обслуживается Django через proxy_params) достаточно стандартного $remote_addr
Важно
Если WAF/AntiDDoS работает в режиме TCP RAW и не передаёт X-Forwarded-For, backend будет видеть IP защитного узла, а не реальный IP пользователя. Если нужен реальный IP клиента — отдельно согласовывайте поддержку PROXY protocol на стороне защитного решения. Включать proxy_protocol на принимающей стороне можно только если защитный узел действительно его передаёт, иначе все соединения будут разрываться
Диагностика¶
Проверка TLS-уровня¶
openssl s_client -connect rd.example.com:8443 -servername rd.example.com -showcerts
Нормально — возвращается сертификат сервера
Плохо — ошибки вида:
wrong version number
packet length too long
no peer certificate available
Обычно это означает путаницу режимов (HTTP, HTTPS, TCP) на стороне защитного узла или включённый PROXY protocol без поддержки на backend
Проверка HTTP API¶
curl -vk https://rd.example.com:8443/root.pem
curl -vk -X POST https://rd.example.com:8443/api/ssolist/ \
-H "Content-Type: application/json" \
-d '{}'
Подсказка
Даже если сервер вернул 401, 403 или 405 — это лучше, чем обрыв соединения: запрос дошёл до HTTP-приложения, и проблема не в публикации
Плохо — следующие симптомы означают, что трафик до приложения не доходит:
503 Service Unavailable
connection closed before message completed
empty reply from server
Связанные страницы¶
Развёртывание за обратным прокси — общая схема и примеры конфигураций HAProxy и Nginx
Разделение портов — разделение административного и клиентского трафика по разным портам
Ограничение доступа к веб — как закрыть админ-панель от внешнего доступа
Добавление собственных SSL-сертификатов — замена встроенных самоподписанных сертификатов на доверенные для клиентского порта