VDI-профили для TRS-проектов:¶
Данное расширение позволяет управлять подключением пользователей к ВМ в контексте одного TRS-проекта. Теперь Администратор с помощью Dashboard может гибко ограничивать проброс устройств и некоторые другие сервисы, предоставляемые пользователю в рамках сессии RSclient. Такой набор правил называется VDI-профиль. Получаемый VDI-профиль напрямую зависит от RSserver, который обрабатывает запрос. Используя балансировщик между Пользователем и RSserver можно отдавать разные VDI-профили, например если установить правило для подключения из разных сетей. Именно такой кейс рассматривается в данной документации.
Как и в случае стандартной конфигурации TRS-проектов основу системы составляют три ключевых компонента: RSserver, RSclient и Dashboard.
С данным расширением у Администратора появляется возможность настроить TRS-проект таким образом, что Пользователь будет получать определенный VDI-профиль, в зависимости от RSserver к которому подключается.
- После подключения, запрос обрабатывается балансировщиком (Balancer).
- Balancer перенаправляет запрос на один из доступных RSserver.
- RSserver, отдаёт профиль указанный в
/etc/aos/rsserver.conf
, если же профиль не указан, RSserver отдаёт профиль по-умолчанию. - Перед подключением ВМ получает VDI-профиль пользователя в зависимости от его source ip.
- Пользователи подключаются к ВМ через RSclient установленный на тонкий клиент.
Схема работы расширения:

Установка компонентов TRS-проекта:¶
Установка RSserver:¶
Установка deb-пакета:¶
Установите RSserver следуя документации.
Установка pip-пакета поверх deb-пакета:¶
Получите права суперпользователя:
sudo -i
Остановите все запущенные службы на всех хостах:
systemctl -a stop aos-rs-* && systemctl -a status aos-rs-*
Перед началом установки сохраните список установленных ранее пакетов:
pip3 freeze > pip.lock
Перенос старой версии RSserver:
mv /usr/lib/python3/dist-packages/rs_server ~/rs_server_old
Установите новый pip-пакет (если начнётся установка зависимостей, не кэшированных в локальном окружении, немедленно прервите процесс):
pip3 install rs_server-1.16.*-cp37-cp37m-linux_x86_64.whl
Убедитесь, используется новая версия:
python3 -c "from rs_server.core.helpers import check; print(check())" # > no err python3 -c "from rs_server.settings import CONF; print(CONF.broker_api.vdi_profiles_enabled)" # > False python3 -c "from rs_server.settings import CONF; print(CONF.broker.default_vdi_profile)" # > python3 -c "from rs_server.settings import CONF; print(CONF.broker.default_vdi_profile)" # no error VDIProfiles.PROFILE_1 python3 -c "from rs_server.core.helpers import parse; print(parse())" # no err
Примените миграции (только один раз на одном контроллере):
openstack aos db migrate -n rs_server
Измените версию в bin-файлах:
sed -i "s/1.16.*/1.16.*/g" /usr/bin/aos-rs-*
Перезапустите все связанные сервисы:
systemctl -a restart aos-rs-* && systemctl -a status aos-rs-*
Настройка:¶
В файле
/etc/aos/rs_server.conf
включите VDI-профили, а также указан профиль по умолчанию:vdi_profiles_enabled = True default_vdi_profile = 1..8
Установка RSclient:¶
Установите пакет:
apt-get install ~/vncm-client_0.5.6-7-agent_amd64.deb
Запустите скрипт настройки:
configure-vncm-client.sh
Введите имя существующего пользователя, с которого будет идти подключение (для новых пользователей настройки по умолчанию уже установлены).
Дождитесь завершения настройки.
Установка Dashboard:¶
Установка deb-пакета:¶
Установите Dashboard следуя документации.
Установка pip-пакета поверх deb-пакета:¶
Важно
Данная процедура установки применима только в случае, если Dashboard уже установлен как часть пакетов системы (dist-packages). Убедитесь, что это условие выполнено, прежде чем продолжить.
Получите права суперпользователя:
sudo -i
Перед началом установки сохраните список установленных ранее пакетов:
mkdir -p /tmp/rollback/dashboard pip3 freeze > /tmp/rollback/dashboard/pip_before.txt
Остановите все связанные сервисы с сервисами Horizon:
systemctl stop apache2 nginx dashboard-uwsgi memcached systemctl status apache2 nginx dashboard-uwsgi memcached
Перенесите deb-версию Dashboard:
sudo mv /usr/lib/python3/dist-packages/dashboard /usr/lib/python3/dist-packages/dashboard-old
Установите новый pip-пакет (если начнётся установка зависимостей, не кэшированных в локальном окружении, немедленно прервите процесс):
pip3 install /tmp/dashboard-1.16.*.tar.gz
Убедитесь, что python будет использовать новый Dashboard:
python3 -c "import dashboard; print(dashboard.__file__)"
Сохраните список установленных пакетов после установки для возможности отката изменений:
pip3 freeze > /tmp/rollback/dashboard/pip_after.txt
Соберите статические файлы:
python3 /usr/share/openstack-dashboard/manage.py collectstatic -c
Выполните сжатие файлов:
python3 /usr/share/openstack-dashboard/manage.py compress
Перезапустите все связанные сервисы:
systemctl restart apache2 nginx dashboard-uwsgi memcached systemctl status apache2 nginx dashboard-uwsgi memcached
Настройка:¶
Добавьте в конфигурационный файл /etc/aos/dashboard.conf
поле (для отображения вкладки RSclient settings):
group_policies_enabled = True
Создание TRS-проекта и TRS-машины через Dashboard:¶
- Перейдите в раздел
TRS/TRS Projects
, создайте и настройте проект, назначьте пользователей. - Заполните VDI-профили. По умолчанию используется Профиль 1.
- Перейдите в раздел
TRS/TRS Instances
, создайте виртуальную машину и назначьте security group.
Образец скрипта подключения:
#!/bin/bash
set -x
exec 2> ~/.rsclient/connect_error.log
exec 1> ~/.rsclient/connect.log
connect_timeout=30
ipraw=$RSC_VM_IP
user=$RSC_USER
pass=$RSC_PASSWORD
vncm_admx=$RSC_GROUP_POLICY_TEMP_PATH
web_admx=$RSC_ALLOWED_URLS_TEMP_PATH
echo 1 > ~/.vnc/.vncm_progress
echo "# Запуск подключения ..." > ~/.vnc/.vncm_status
connect() {
echo 20 > ~/.vnc/.vncm_progress
echo "# Запуск подключения к виртуальной машине" > ~/.vnc/.vncm_status
if [[ ! -z $(ps -aux | grep vncviewer | grep -v grep) ]]; then
/bin/sh -c "zenity --info --text='vnc уже запущен'"
exit 0
fi
ip=$(nslookup "$ipraw" | grep "name = " | sed 's|.name = ||g')
if [[ ! "$@" =~ 'magic_number_for_sso_mode' ]]; then
ip=$ipraw
# check if pass need change
passexp=$(sshpass -v -p "$pass" ssh -o StrictHostKeyChecking=no "$user@$ip" 'whoami' 2>&1)
if [[ $passexp =~ expired ]]; then
zenity --error \
--text="Необходимо сменить пароль"
echo 100 > ~/.vnc/.vncm_progress
echo "# Завершение подключения" > ~/.vnc/.vncm_status
off-client.sh
exit 0
fi
ssh_con="sshpass -p '$pass' ssh -tt -o StrictHostKeyChecking=no"
else
ssh_con="ssh -tt -o StrictHostKeyChecking=no"
fi
myip=$(sshpass -p "$pass" ssh -o StrictHostKeyChecking=no "$user@$ip" "echo \$SSH_CLIENT | sed 's| .||g'")
userhome=$(eval $ssh_con "$user@$ip" env | grep HOME | sed 's|HOME=||g')
userhome=$(echo "$userhome" | rev | cut -c 2- | rev)
echo 50 > ~/.vnc/.vncm_progress
echo "# Запуск vnc подключения" > ~/.vnc/.vncm_status
eval $ssh_con "$user@$ip" "loginctl enable-linger $user"
eval $ssh_con "$user@$ip" "systemctl --user daemon-reload"
if [[ $(cat $HOME/.vnc/default.tigervnc | grep LocalhostForSSH=1 | grep -v -E "^ *#") ]]
then
eval $ssh_con $user@$ip "systemctl --user stop vncserver"
eval $ssh_con $user@$ip "systemctl --user start vncserver_sock"
else
eval $ssh_con $user@$ip "systemctl --user stop vncserver_sock"
eval $ssh_con $user@$ip "systemctl --user start vncserver"
fi
try=0
while [[ ! $ok ]]; do
ok=$(eval $ssh_con "$user@$ip" 'ps -aux | grep /usr/bin/Xvnc | grep -v grep')
sleep 1
try=$(expr $try + 1)
if [ "$try" = $connect_timeout ]; then
zenity --error \
--text="Не удалось подключиться к виртуальной машине. Повторите попытку подключения или обратитесь к системному администратору"
echo 100 > ~/.vnc/.vncm_progress
echo "# Завершение подключения" > ~/.vnc/.vncm_status
off-client.sh
exit 0
fi
done
loginctl enable-linger "$USER"
systemctl --user daemon-reload
sshpass -p $pass scp -o StrictHostKeyChecking=no $vncm_admx $user@$ip:/var/tmp/.vncm/VNCm.admx
sshpass -p $pass scp -o StrictHostKeyChecking=no $web_admx $user@$ip:/var/tmp/.vncm/WEBfwd.admx
eval $ssh_con $user@$ip 'chmod 666 /var/tmp/.vncm/*.admx'
eval $ssh_con $user@$ip 'mkdir -p /tmp/share/'
eval $ssh_con $user@$ip 'chmod 777 /tmp/share/'
# wait for agent to start
unset ok
while [[ ! $ok =~ "OK" ]]
do
eval $ssh_con -q $user@$ip [[ -S /tmp/vnc.sock ]] && ok="OK" || ok="NO";
sleep 1
done
if [[ $(cat $HOME/.vnc/default.tigervnc | grep LocalhostForSSH=1 | grep -v -E "^ *#") ]]
then
passes=$passes" -L 127.0.0.1:33333:$userhome/.vnc/vncm.sock"
fi
eval $ssh_con -R $userhome/.pcscd.comm:/var/run/pcscd/pcscd.comm $user@$ip &
eval $ssh_con -R $userhome/.cups.sock:/var/run/cups/cups.sock $user@$ip &
echo 100 > ~/.vnc/.vncm_progress
echo "# vnc подключено ..." > ~/.vnc/.vncm_status
if [[ "$@" =~ '--use-quictun' ]]; then
if [[ $(cat "$HOME/.vnc/default.tigervnc" | grep LocalhostForSSH=1 | grep -v -E "^ *#") ]]; then
systemctl --user start vncm-quic-server@$myip.service
systemctl --user start vncm-socat-client.service
eval $ssh_con "$user@$ip" "systemctl --user start vncm-quic-client@$myip.service"
eval $ssh_con "$user@$ip" "systemctl --user start vncm-socat-server.service"
unset ok
while [[ ! $ok ]]; do
ok=$(eval $ssh_con "$user@$ip" 'ps -aux | grep tcp:localhost:2322 | grep -v grep')
sleep 1
done
eval $ssh_con "$passes" "$user@$ip" &
unset ok
while [[ ! $ok =~ '127.0.0.1:33333' ]]
do
ok=$(ps -aux | grep 127.0.0.1:33333 | grep -v grep)
sleep 1
done
/usr/bin/vncviewer $HOME/.vnc/default.tigervnc localhost:33333
else
echo "ERROR: --use-quictun need LocalhostForSSH=1"
fi
else
if [[ $(cat "$HOME/.vnc/default.tigervnc" | grep LocalhostForSSH=1 | grep -v -E "^ *#") ]]; then
systemctl --user start vncm-socat-client.service
passes="$passes -R 3240:localhost:3240 -R 5005:localhost:5005 -R 5007:localhost:5007 -R 5008:localhost:5008 -R 6566:localhost:6566 -R 2322:localhost:22"
eval $ssh_con "$passes" "$user@$ip" &
eval $ssh_con "$user@$ip" 'systemctl --user start vncm-socat-server.service'
unset ok
while [[ ! $ok =~ '2322:localhost:22' ]]; do
ok=$(ps -aux | grep 2322:localhost:22 | grep -v grep)
sleep 1
done
/usr/bin/vncviewer $HOME/.vnc/default.tigervnc localhost:33333
else
/usr/bin/vncviewer "$HOME/.vnc/default.tigervnc" "$ip:1"
fi
fi
}
(
(
while [[ $progress != 100 ]]; do
progress=$(cat ~/.vnc/.vncm_progress)
status=$(cat ~/.vnc/.vncm_status)
echo "$progress"
echo "$status"
sleep 1
done
) | zenity --progress \
--title="VNCM" \
--text="Запуск подключения ..." \
--percentage=0 \
--auto-close \
--no-cancel || pkill connect.sh
) & connect "$@"
Важно
В скрипте подключения могут быть использованы переменные, которые в процессе будут автоматически изменены на реальные значения:
$RSC_VM_IP
– адрес ВМ.$RSC_USER
– Имя пользователя для аутентификации.$RSC_PASSWORD
– Пароль для аутентификации пользователя.$RSC_GROUP_POLICY_TEMP_PATH
– Локальный путь к временному файлу с групповыми политиками.$RSC_ALLOWED_URLS_TEMP_PATH
– Локальный путь к временному файлу с разрешёнными URL.
Образец групповых политик:
---
# политики
policy:
scanner: true
printer: false
netfs: false
webcam: true
audio: true
microphone: true
smartcard: false
usb:
- device_1:
vid: 0
pid: 0
...
Образец разрешённых URL:
$RSC_CLIENT_IP|{
"rules": [
{
"active": true,
"conditions": [
{
"id": 1739955810043,
"request": {
"redirect": "http://$RSC_CLIENT_IP/v1/urls/[example.com$1]",
"search": "REGEX",
"value": "https?://example.com(.*)"
}
}
],
"description": "Redirect с example.com",
"enableNotifications": true,
"id": 1739955654113,
"name": "example.com"
}
]
}
Важно
В разрешённых URL может быть использована переменная, которая в процессе будет автоматически изменена на реальное значение:
$RSC_CLIENT_IP
– IP-адрес клиентской машины.
Установка и настройка балансировщика:¶
Для обеспечения отказоустойчивости и распределения нагрузки в системе TRS-проектов используется балансировщик на основе HAProxy.
Требования к виртуальной машине (ВМ):¶
- ВМ должна иметь два сетевых интерфейса.
- Настройте маршрутизацию для доступа к ВМ из других сетей. Рекомендуется избегать ситуации с двумя default шлюзами или использовать routing policy.
Установка HAProxy:¶
Установите HAProxy с помощью пакетного менеджера:
apt install haproxy
Если доступ к репозиториям ограничен, используйте предварительно подготовленный образ с уже установленным пакетом HAProxy.
Настройка:¶
Образец конфигурационного файла:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
timeout connect 5s
timeout client 50s
timeout server 50s
frontend trs_proxy
bind 10.40.14.151:9365
acl from_vm src 10.40.15.0/24
acl from_tk src 10.40.251.0/24
use_backend backend_vm if from_vm
use_backend backend_tk if from_tk
http-request deny if !from_tk !from_vm
backend backend_vm
balance roundrobin
server srv1 10.40.13.11:9365 check
server srv2 10.40.13.12:9365 check
backend backend_tk
balance roundrobin
server srv3 10.40.13.13:9365 check
После настройки конфигурации перезапустите HAProxy для применения изменений:
systemctl restart haproxy
Важно
Убедитесь, что для всех RSserver из одной группы используется один и тот же ключ /etc/aos/.rs_server_secret_key
.
URL-plugin:¶
URL-plugin — расширение для браузеров на движке Chromium, которое обеспечивает контроль за переходами по URL-адресам.
Когда пользователь пытается перейти по URL, плагин проверяет, находится ли этот адрес в списке разрешённых. Если URL разрешён, плагин автоматически закрывает вкладку на ВМ и открывает её на тонком клиенте в локальном браузере.
Это позволяет перенаправлять трафик на устройство пользователя, обеспечивая безопасность и контроль за доступом к внешним ресурсам.

Установка URL-plugin:¶
Важно
Убедитесь, что на тонком клиенте и на ВМ установлен браузер на движке Chromium.
Файл WEBfwd.admx:¶
Важно
Убедитесь, что в разделе настроек RSclient settings вашего TRS-проекта указаны разрешённые URL.
Разрешённые URL передаются на ВМ с помощью скрипта подключения:
#sshpass -p "$pass" scp "$RSC_ALLOWED_URLS_TEMP_PATH" "$user@$ipraw:/var/tmp/.vncm/WEBfwd.admx"
Установка расширения URL-plugin:¶
На ВМ откройте браузер, включите Developer Mode и установите расширение, указав путь к нему.