Развёртывание за обратным прокси¶
Развёртывание за обратным прокси — установка сервера RuDesktop во внутренней сети с внешним HAProxy или Nginx перед ним, который принимает подключения снаружи и пересылает их на сервер. Раздел описывает, какой трафик можно проксировать и каким способом, готовые примеры конфигураций и список типовых проблем
Важно
По умолчанию сервер RuDesktop уже разворачивает у себя локальный Nginx, который терминирует TLS на 443 и проксирует запросы к веб-части и к нативному компоненту relay / rz через unix-сокеты /run/rudesktop-web.sock и /run/rudesktop/rude.sock (см. Архитектура). Эта страница описывает внешний обратный прокси, который ставится перед сервером RuDesktop
Зачем нужен обратный прокси перед RuDesktop¶
Типовые сценарии:
TLS-терминация на единой точке — сертификаты обслуживаются одним фронтом, не на каждом узле
Единая точка входа для нескольких внутренних сервисов организации
Балансировка между несколькими узлами отказоустойчивого кластера
Ограничение доступа — фильтрация по IP, ACL, аутентификация заголовка
Публикация веб-части наружу, при том что прямой TCP-доступ к
relay/rzостаётся внутри периметра
Какой трафик принимает сервер RuDesktop¶
По умолчанию весь трафик клиентов и веб-интерфейса идёт через единый порт ``443/TCP`` на встроенный Nginx сервера, который терминирует TLS и проксирует запросы к веб-части и компоненту relay / rz через unix-сокеты. Снаружи это выглядит как обычный HTTPS-сайт с дополнительным WebSocket-эндпоинтом
Эндпоинты на 443/TCP:
/— административная веб-панель и API (/api/,/portal/,/media/)/v1/— WebSocket-канал к нативному компонентуrelay/rzчерез unix-сокет/run/rudesktop/rude.sock. Используется десктопным и мобильным клиентами для управляющего канала и сессионного трафика/ws/— WebSocket-канал к веб-части (/run/rudesktop-web.sock). Используется браузерным интерфейсом для live-обновлений и для обратной совместимости при разделении портов/analytics/— встроенный модуль аналитики (Apache Superset), проксируется на unix-сокет/run/rudesktop-web-superset.sock/static/— статика веб-интерфейса (alias/usr/share/rudesktop/public/)/download/— установочные пакеты клиентов (alias/usr/share/rudesktop/public/download/)/tftp/— файлы для PXE-установки (alias/var/lib/rudesktop/pxe/tftp/); единственный путь, доступный по HTTP на80/TCPбез редиректа на HTTPS/root.pem— публичный CA-сертификат сервера, отдаваемый клиентам
Дополнительно при Разделении портов клиентский трафик можно вынести на отдельный HTTPS-порт (например, 8443) с набором эндпоинтов /api/, /media/, /portal/, /v1/, /ws/ — это всё тот же L7 HTTPS, не отдельный TCP-поток
Важно
Большая часть путей выше (/analytics/, /ws/, /tftp/, защищённые медиа и др.) объявлена в файле /etc/nginx/rudesktop_params, который подключается во встроенный vhost директивой include rudesktop_params;. При ручной правке /etc/nginx/sites-enabled/rudesktop не удаляйте этот include — иначе перечисленные эндпоинты перестанут работать
Подсказка
Весь трафик RuDesktop — это HTTP(S) с поддержкой WebSocket. Достаточно одного L7-прокси (HAProxy mode http или Nginx). Отдельный TCP-passthrough для какого-либо нестандартного порта не требуется
Что можно проксировать и каким способом¶
Что |
Режим прокси |
Особенности |
|---|---|---|
|
L7 HTTP(S) |
Стандартное HTTPS-проксирование. Передавать |
|
L7 HTTP(S) с upgrade |
Обязательны заголовки |
|
L7 HTTP(S) с upgrade |
Те же требования, что и для |
|
L7 HTTP(S) |
Проксируется как |
|
L7 HTTP(S) |
Ничего особенного, проксируется как |
|
L7 HTTP |
Раздаётся также по HTTP без TLS (порт |
Важно
Что нельзя: проксировать /v1/ без upgrade-заголовков WebSocket. Если фронтальный прокси настроен только на HTTP без upgrade — управляющий канал клиента не установится, в десктопном клиенте будет вечный «Подключение…», в веб-интерфейсе пропадут live-обновления
Подсказка
Дефолты встроенного nginx (см. /etc/nginx/sites-enabled/rudesktop), которые имеет смысл воспроизвести и на внешнем фронте: proxy_connect_timeout 120s, proxy_send_timeout 600s, proxy_read_timeout 600s для /v1/ и client_max_body_size 1000G (загрузка пакетов и обновлений может превышать стандартные ограничения)
Подготовка сервера RuDesktop¶
Перед включением фронтального прокси:
Убедитесь, что встроенный сервер работает на
127.0.0.1или unix-сокете и не выставлен наружу напрямую — см. Смена и установка IP, Ограничение доступа к вебЕсли фронт будет терминировать TLS — на самом сервере RuDesktop можно оставить самоподписанный сертификат (он используется только во внутренней сети). Для прямого подключения клиентов к серверу без фронта см. Добавление собственных SSL-сертификатов
Зафиксируйте публичный FQDN, по которому клиенты будут обращаться к фронту, и задайте его в качестве адреса сервера командой
rude install(илиrude reinstall, если требуется сброс конфигурации, см. Смена и установка IP):rude install rd.example.comКоманда формирует
/etc/default/rudesktopс переменными окруженияPUBLIC_HOST='rd.example.com'иPUBLIC_PORT='443'. ИзPUBLIC_HOST/PUBLIC_PORTвеб-часть сервера формируетCSRF_TRUSTED_ORIGINS, и от них же зависят ссылки, которые сервер отдаёт клиентам. Список адресов вALLOWED_HOSTSиserver_nameвстроенного Nginx формируются из списка хостов сервера и обновляются той же командой
Подсказка
Подробнее о смене адреса сервера и о работе с двумя адресами одновременно — Смена и установка IP
Пример конфигурации HAProxy¶
Универсальный вариант — единый фронтенд на 443/TCP с TLS-терминацией, проксирование веба и WebSocket к одному backend-серверу RuDesktop на адресе 10.0.0.10:443
# /etc/haproxy/haproxy.cfg
global
maxconn 50000
log /dev/log local0
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 10s
timeout client 600s
timeout server 600s
timeout tunnel 1h
frontend rudesktop_https
bind *:443 ssl crt /etc/haproxy/certs/rudesktop.pem alpn h2,http/1.1
http-request set-header X-Forwarded-Proto https
http-request set-header X-Forwarded-Port %[dst_port]
# FQDN, по которому ходят клиенты
http-request set-header X-Forwarded-Host %[req.hdr(host)]
default_backend rudesktop_web
backend rudesktop_web
balance roundrobin
option forwardfor
option http-server-close
# Проброс WebSocket-апгрейда
http-request set-header Connection upgrade if { hdr(Upgrade) -i websocket }
server rd1 10.0.0.10:443 ssl verify none check
Важно
timeout tunnel 1hобязателен — иначе HAProxy будет рвать длинные WebSocket-соединения по таймаутуssl verify noneподходит для встроенного самоподписанного сертификата сервера. Для строгой проверки замените наverify required ca-file /etc/haproxy/ca/rudesktop_ca.pemПри наличии нескольких узлов кластера добавьте ещё
server rd2 ..., но подключения должны быть sticky по cookie или source IP, чтобы один клиент попадал на один и тот же узел в рамках сессии
Если веб и клиентский трафик разнесены по разным портам¶
При использовании Разделения портов на стороне сервера клиентский трафик слушает на отдельном HTTPS-порту (например, 8443). На фронте это можно отразить вторым HTTPS-frontend’ом с тем же набором заголовков и таймаутов:
frontend rudesktop_client_https
bind *:8443 ssl crt /etc/haproxy/certs/rudesktop.pem
http-request set-header X-Forwarded-Proto https
default_backend rudesktop_client_backend
backend rudesktop_client_backend
option forwardfor
http-request set-header Connection upgrade if { hdr(Upgrade) -i websocket }
server rd1 10.0.0.10:8443 ssl verify none check
Пример конфигурации Nginx¶
Универсальный вариант — фронтальный Nginx, терминирующий TLS на 443 и проксирующий весь трафик на сервер RuDesktop (адрес 10.0.0.10)
# /etc/nginx/sites-available/rudesktop-front
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream rudesktop_backend {
server 10.0.0.10:443;
keepalive 32;
}
server {
listen 80;
server_name rd.example.com;
# PXE через фронт не пробрасывается — обращения к /tftp/ возвращаем 404,
# PXE-клиенты должны ходить к серверу RuDesktop напрямую внутри сети.
# Если PXE нужно публиковать через фронт — замените блок /tftp/ на proxy_pass http://10.0.0.10/tftp/;
location /tftp/ { return 404; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
server_name rd.example.com;
ssl_certificate /etc/ssl/private/rd.example.com.pem;
ssl_certificate_key /etc/ssl/private/rd.example.com.key;
# Размер тела для загрузки больших файлов и обновлений
client_max_body_size 1000G;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
# WebSocket-канал /v1/ — увеличенные таймауты + upgrade
location /v1/ {
proxy_pass https://rudesktop_backend;
proxy_ssl_verify off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 120s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
}
# WebSocket-канал /ws/ для браузерного интерфейса — те же требования к upgrade
location /ws/ {
proxy_pass https://rudesktop_backend;
proxy_ssl_verify off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 600s;
}
# Весь остальной трафик веб-панели и API
location / {
proxy_pass https://rudesktop_backend;
proxy_ssl_verify off;
add_header Cache-Control 'no-cache';
}
}
Важно
Блок
map $http_upgrade $connection_upgradeдолжен находиться вhttp {}— например, в отдельном файле в/etc/nginx/conf.d/proxy_ssl_verify offнужно для встроенного самоподписанного сертификата. Если на сервере RuDesktop установлен доверенный сертификат, переключите наproxy_ssl_verify onи пропишитеproxy_ssl_trusted_certificateДлинные таймауты в
location /v1/обязательны — иначе будет регулярный обрыв WebSocket с ошибкойupstream timed outWebSocket-апгрейд должен быть прописан в обоих WebSocket-локациях (
/v1/и/ws/). Если оставить их безUpgrade/Connection— у клиентов отвалится управляющий канал, а в браузере пропадут live-обновления и аналитика
Решение проблем¶
Mixed content / CSRF Origin checking failed¶
Причина: клиент обращается по IP или домену, который не был указан при
rude install, из-за чего этот адрес отсутствует вCSRF_TRUSTED_ORIGINSи Django отклоняет запросРешение: проверить, что фронт всегда добавляет
X-Forwarded-Proto: httpsиX-Forwarded-Host: <FQDN>.PUBLIC_HOSTиPUBLIC_PORTсервера должны совпадать с FQDN и портом фронта — поправляются командойrude install <FQDN>[:порт]. Из них Django формируетCSRF_TRUSTED_ORIGINSвидаhttps://<PUBLIC_HOST>(илиhttps://<PUBLIC_HOST>:<PUBLIC_PORT>при нестандартном порте)