Графическое исполнение.

См. Часть 1

Введение

Клиент RDP — это программное обеспечение, которое позволяет подключиться к терминальному серверу с использованием протокола удалённого рабочего стола (Remote Desktop Protocol).

Технология RDP позволяет применять малопроизводительные компьютеры в качестве терминалов (так называемых тонких клиентов). Все необходимые функции, включая рабочую систему, офисные программы и современный браузер, будут выполняться на сервере.

Поэтому создаём свой легковесный образ на на основе Debian 12, используя проверенные пакеты. Готовый образ можно будет записать как на USB-флешку, так и на жесткий диск. А в перспективе такой образ можно будет загружать на тонкий клиент через сеть.

Постановка задачи

В предыдущей части было дана инструкция, как сделать загрузочный образ. В этой части установим и настроим пакеты для подключения к удаленному рабочему столу.

План действий:

  • установить необходимые пакеты

  • настроить разрешения для учётной записи user

  • настроить графическую среду

  • организовать диалоговое окно для авторизации

  • настроить автозагрузку графической системы

  • записать образ на USB-носитель.

В статье приведены примеры консольных команд, которые необходимо выполнять в зависимости от задачи в хостовой или гостевой системе. Чтобы различать эти команды, перед ними будет отображаться приглашение:

$ — команды, выполняемые в хостовой системе.
root> — команды, выполняемые в гостевой системе от имени root.
user> — команды, выполняемые в гостевой системе от имени user.

Хостовая система — система, на которой запускаются виртуальные машины.
Гостевая система — система, которая работает внутри виртуальной машины.

Допустим, что RDP-сервер настроен по адресу 192.168.10.2. К нему будем подключаться для проверки системы.

Запуск виртуальной машины

Перед началом работы с виртуальной машиной рекомендуется создать резервную копию образа.

Скрипт запуска виртуальной машины:

#!/bin/bash

qemu-system-x86_64 \
-name "usb-debian" \
-m 2048M \
-enable-kvm \
-cpu host \
-smp 2 \
-machine type=q35 \
-bios OVMF.fd \
-net nic -net user,hostfwd=tcp::2222-:22 \
-drive file=image.qcow2 \
&

После старта виртуальной машины рекомендую подключиться к гостевой системе по SSH:

$ ssh -p 2222 root@localhost

Работа по SSH позволяет использовать буфер обмена, что облегчает набор команд.

Установка необходимых пакетов

Гостевая система была настроена так, что после каждого её выключения обнуляется кеш доступных пакетов. Поэтому обновите кеш:

root> apt update

1. Установка и настройка sudo

Для управления системой от имени обычного пользователя установите пакет:

root> apt install -y sudo

Теперь предоставим пользователю user возможность выполнять команды управления питанием без ввода пароля. В конец файла /etc/sudoers необходимо добавить строку:

user ALL=NOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroff

Это позволит пользователю user выполнять команды без ввода пароля:

user> sudo halt      # выключение
user> sudo reboot    # перезагрузка
user> sudo poweroff  # выключение

2. Установка netcat для диагностики сети

В виртуальной среде QEMU по умолчанию не поддерживается ICMP-трафик, поэтому команда ping не работает или возвращает ошибку, даже если сеть функционирует корректно.

Для проверки доступности серверов вместо ping рекомендуется использовать netcat — утилиту для тестирования TCP/UDP-портов.

Установите netcat (OpenBSD-версия):

root> apt install netcat-openbsd

RDP по умолчанию использует порт 3389. Проверим его на нашем сервере:

root> nc -zv -w 1 192.168.10.2 3389
  • -z — режим проверки порта (без передачи данных)

  • -v — подробный вывод

  • -w 1 — таймаут в 1 секунду

Ожидаемый результат:

Connection to 192.168.10.2 3389 port [tcp/ms-wbt-server] succeeded!

3. Установка графической подсистемы X.Org

Для запуска графического RDP-клиента установим минимальную реализацию X-сервера:

root> apt install -y --no-install-recommends xorg
  • Объём занимаемого дискового пространства 275 МБ

  • Флаг --no-install-recommends предотвращает установку рекомендуемых пакетов, экономя около 10 МБ.

В интернете встречаются советы по установке более урезанных конфигураций X.Org. Лучше всё же использовать стандартный xorg. Это обеспечивает максимальную совместимость с различным оборудованием и предотвращает проблемы с разрешением экрана или драйверами на чужих компьютерах.

4. Установка RDP-клиента на базе FreeRDP

Рекомендую установить стабильную и проверенную версию FreeRDP 2:

root> apt install -y --no-install-recommends freerdp2-x11

Занимаемый объем: 147 МБ

Если требуется более новая версия с улучшенной поддержкой протокола FreeRDP 3, добавьте репозиторий unstable в файл /etc/apt/sources.list:

deb https://deb.debian.org/debian/ unstable main

Установите freerdp3-x11:

root> apt update
root> apt install -y --no-install-recommends freerdp3-x11

Графический режим

1. Отключение автологина в консоль

Если ранее был настроен автоматический вход в систему от имени root, то сейчас его надо отключить. Он будет нам мешать тестированию графического режима от имени user.

В файле сервиса /usr/lib/systemd/system/getty@.service необходимо вернуть старое значение ExecStart:

ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear - $TERM

Примените изменения, перезагрузив гостевую систему:

root> reboot

2. Тестирование графического режима

Ниже — несколько способов запуска и отладки GUI-приложений.

Рекомендуемая схема работы:

  • В окне QEMU входите под пользователем user

  • Параллельно подключайтесь по SSH (под root или user) для выполнения административных команд и копирования файлов

Способ 1: X11-перенаправление через SSH

SSH поддерживает перенаправление графического интерфейса (X11 forwarding). Это позволяет запускать графические приложения на гостевой системе, но отображать их на хосте.

Подключитесь с флагом -X:

$ ssh -X -p 2222 root@localhost

Теперь любое GUI-приложение будет отображаться на экране хостовой системы:

user> xcalc

Калькулятор откроется на вашем основном рабочем столе, не в окне QEMU.

Способ 2: Запуск графической среды в окне QEMU

Самый наглядный способ — запустить X-сервер непосредственно в окне QEMU.
После входа в консоль гостевой системы выполните:

user> startx

Будет запущена графическая среда с xterm. Вы увидите её в окне QEMU. Этот способ полезен для:

  • Проверки разрешения экрана

  • Тестирования отображения шрифтов и интерфейса

  • Отладки проблем с драйверами или окружением

Способ 3: Ручное перенаправление в запущенный X-сессию

Если графическая среда уже запущена (через startx), вы можете отправлять в неё GUI-приложения из SSH-сессии. Установите переменную окружения DISPLAY:

root> export DISPLAY=:0

Теперь любое графическое приложение будет отображаться в сессии X-сервера в QEMU:

user> xclock
user> xeyes

Попробуйте все три варианта — они дополняют друг друга и облегчат отладить графическую среду на разных этапах настройки.

3. Тестирование RDP-клиента

Теперь можно протестировать подключение к RDP-серверу:

user> startx
user> xfreerdp /u:user /p:12345678 /v:192.168.10.2 /cert:ignore
  • /u:user — Учётная запись пользователя на RDP-сервере

  • /p:12345678 — Пароль для аутентификации

  • /v:192.168.10.2 — IP-адрес RDP-сервера

  • /cert:ignore — Игнорирует предупреждения о самоподписанных или недоверенных сертификатах

Окно отображения удалённого рабочего стола
Окно отображения удалённого рабочего стола

Настройка графического режима для пользователя user

Задача портативного RDP-клиента проста: отобразить интерфейс подключения к удалённому рабочему столу и обеспечить доступ к терминалу.

Установка полноценного графического менеджера окон (например, XFCE, LXDE или GNOME) избыточна — он добавит ненужные компоненты: шрифты, панели, рабочие столы, горячие клавиши, которые не только увеличат размер образа, но и будут мешать автоматизации.

Если же вы хотите более гибкий интерфейс, можно рассмотреть лёгкие менеджеры, такие как BlackBox или Openbox. А для портативного RDP-клиента проще и надёжнее обойтись без них.

1. Настройка внешнего вида терминала xterm

Создайте файл конфигурации графических параметров /home/user/.Xresources:

! Открытие терминала в полноэкранном режиме
xterm*maximized: true

! Цветовая схема: тёмный фон, светлый текст
xterm*background: #111111
xterm*foreground: #dddddd

! Шрифт и размер
xterm*faceName: Monospace
xterm*faceSize: 12

! Прокрутка: сохранять до 10 000 строк, прокрутка по клавише
xterm*saveLines: 10000
xterm*scrollKey: true

2. Автозапуск графической среды .xinitrc

Файл /home/user/.xinitrc определяет, что запускается при старте X-сервера.

# Загрузить пользовательские настройки из .Xresources
xrdb -merge ~/.Xresources

# Установить стандартный курсор (стрелка)
xsetroot -cursor_name left_ptr

# Запустить xterm вместе с Midnight Commander
exec xterm -e mc

3. Настройка приглашения командной строки

Для удобства измените приглашение в терминале. В конце файла /home/user/.bashrc необходимо добавить:

PS1='user> '

Теперь приглашение будет выглядеть как:

user>

4. Права доступа к файлам

Чтобы пользователь user владел своими файлами:

root> chown -R user:user /home/user

5. Тестирование графического режима

Теперь можно запустить X-сервер:

user> startx
Ожидаемый результат
Ожидаемый результат

Создание скрипта запуска RDP-клиента

Чтобы превратить систему в удобный терминал, необходимо создать надёжный и понятный интерфейс подключения к RDP-серверу. Ниже — пошаговое построение скрипта, от простого подключения до полноценного меню.

Этап 1: Базовое подключение

Начнём с минимальной команды для подключения:

xfreerdp /u:user /p:12345678 /v:192.168.10.10 \
/f /bpp:16 /network:auto /sec:rdp /cert:ignore \
/sound +clipboard

Пояснение параметров:

  • /f — полноэкранный режим

  • /bpp:16 — 16-битная глубина цвета (экономия трафика)

  • /network:auto — автоматическая настройка под сеть

  • /sec:rdp — использование стандартного шифрования RDP

  • /cert:ignore — игнорировать предупреждения сертификатов (для тестов)

  • +clipboard — общий буфер обмена

Этап 2: Простой скрипт

Создайте файл rdp.sh:

#!/bin/bash

# Конфигурация подключения
XAPP='xfreerdp'
XSERVER='192.168.10.10'
XPORT='3389'
XPARAMS='/f /bpp:16 /network:auto /sec:rdp /cert:ignore /sound +clipboard'
XUSER='user'
XPASS='12345678'
XTIMEOUT=10

# Подключение
cmd="$XAPP /u:$XUSER /p:$XPASS /v:$XSERVER:$XPORT $XPARAMS"
$cmd > /dev/null 2>&1

Сделайте скрипт исполняемым:

chmod +x rdp.sh

Рекомендуется сначала тестировать скрипт на хостовой системе, а затем переносить в гостевую.

Удалённый рабочий стол в полноэкранном режиме
Удалённый рабочий стол в полноэкранном режиме

Этап 3: Проверка доступности сервера

Добавим проверку, включён ли RDP-сервер:

do_wait_server() {
  local sec=0
  while (( sec <= XTIMEOUT )); do
    if nc -z -w 1 $XSERVER $XPORT > /dev/null 2>&1; then
      return 0
    fi
    ((sec++))
    sleep 1
  done
  return 1
}

Интеграция в скрипт:

do_wait_server
if (( $? == 0 )); then
  $cmd > /dev/null 2>&1
else
  echo "Сервер не доступен!"
fi

Этап 4: Ввод логина и пароля

Чтобы не хранить пароль в открытом виде, добавим ввод с клавиатуры и сохранение логина:

# Загрузка сохранённого логина
if [[ -f ./rdp.usr ]]; then
  XUSER=$(cat ./rdp.usr)
fi

# Ввод
read -p "Логин ($XUSER): " input; [[ "$input" ]] && XUSER=$input
read -p "Пароль: " XPASS

# Сохранение
echo "$XUSER" > ./rdp.usr

5: Графическое меню с whiptail

Для удобства пользователя внедрим диалоговое меню на базе whiptail — утилиты, входящей в стандартные дистрибутивы.

Финальный скрипт: rdp.sh:

Скрытый текст
#!/bin/bash

#========================================
# Конфигурация
#========================================
# RDP-сервер
XSERVER='172.16.4.230'
XPORT='3389'
# Таймаут проверки сервера (сек)
XTIMEOUT=5
# програма для подключения
XAPP='xfreerdp'
# параметры для подключения к RDP-серверу
XPARAMS='/f /bpp:16 /network:auto /sec:rdp /cert:ignore /sound +clipboard'
# файл для сохранения настроек
XCONFIG='./rdp.usr'

# Оперативные данные
XUSER='user'
XPASS=''
XEXEC=0

# Команды
cmd_set_pass=1
cmd_set_name=2
cmd_poweroff=3
cmd_terminal=4
cmd_exit=5
cmd_menu=100
cmd_connect=101

#========================================
# Функции
#========================================

#----------------------------------------
# Загрузить сохраненные параметры
do_load() {
  if [[ -f $XCONFIG ]]; then
    XUSER=`<"$XCONFIG"`
    XEXEC=$cmd_set_pass
  else
    XUSER='user'
    XEXEC=$cmd_set_name
  fi
}

#----------------------------------------
# Сохранить параметры
do_save() {
  printf "%s\n" $XUSER > $XCONFIG
}

#----------------------------------------
# Вывести сообщение
do_message() {
  whiptail --msgbox "$1" 8 40 \
  --backtitle "RDP-клиент" \
  --ok-button "Принял" 
}

#----------------------------------------
# Показать главное меню
do_menu() {
  local data
  data=$(whiptail \
  --title "RDP-клиент: $XUSER" \
  --backtitle "RDP-клиент" \
  --nocancel \
  --ok-button "Выбрать" \
  --menu "" 12 45 4 \
  "$cmd_set_pass" "Подключится к серверу" \
  "$cmd_set_name" "Новое имя пользователя" \
  "$cmd_poweroff" "Выключить компьютер" \
  "$cmd_terminal" "Открыть Терминал" \
  3>&1 1>&2 2>&3)
  if (( $? == 0 )); then
    XEXEC=$data
  else
    XEXEC=$cmd_menu
  fi
}

#----------------------------------------
# Показать окно для ввода имени пользователя
do_set_user() {
  local data
  data=$(whiptail --title "Авторизация: $XUSER" \
  --backtitle "RDP-клиент" \
  --ok-button "Далее" \
  --inputbox "Имя:" 8 30 "$XUSER" \
  3>&1 1>&2 2>&3)
  if (( $? == 0 )); then
    XUSER=$data
    XEXEC=$cmd_set_pass
  else
    XEXEC=$cmd_menu
  fi
}

#----------------------------------------
# Показать окно для ввода пароля
do_set_pass() {
  data=$(whiptail \
  --title "Авторизация: $XUSER" \
  --backtitle "RDP-клиент" \
  --ok-button "Вход" \
  --cancel-button "Омена" \
  --passwordbox "Пароль:" 8 40 \
  3>&1 1>&2 2>&3)
  if (( $? == 0 )); then
    if [[ "$data" != "" ]]; then
      XPASS=$data
      XEXEC=$cmd_connect
    else
      XEXEC=$cmd_set_pass
    fi
  else  
    XEXEC=$cmd_menu
  fi
}

#----------------------------------------
# Ожидать доступности сервера
do_wait_server() {
  local step=$((10/$XTIMEOUT))
  local value=0

  # из-за использования pipe во временном файле буду хранить статус
  local ftemp=$(mktemp)
  echo 1 > $ftemp

  while (($value<100)); 
  do
    ((value+=step))
    echo $value
    # проверка порта
    if timeout 0.1 nc -z $XSERVER $XPORT>/dev/null 2>&1; then
      echo 0 > $ftemp
      break
    fi
  done | whiptail --gauge "Ожидание сервера" 6 60 0

  read -r result <$ftemp
  rm $ftemp
  return $result
}

#----------------------------------------
# Подключиться к серверу
do_connect() {
  echo 'Подключение...'
  # сохранить данные
  do_save
  # ожидать доступности сервера
  do_wait_server
  if (( $? == 0 )); then
    local cmd="$XAPP /u:$XUSER /p:$XPASS /v:$XSERVER:$XPORT $XPARAMS"
    $cmd > /dev/null 2>&1
  else
    do_message "❌ Сервер не доступен!"
  fi
  # следующая команда
  XEXEC=$cmd_set_pass
}

#----------------------------------------
# Выключить компьютер
do_poweroff() {
  echo 'Выключение компьютера...'
  sudo poweroff
  exit
}

#----------------------------------------
# Запустить терминал
do_terminal() {
  local pass
  pass=$(whiptail \
  --title "Терминал: root" \
  --backtitle "RDP-клиент" \
  --ok-button "Вход" \
  --cancel-button "Омена" \
  --passwordbox "Пароль:" 8 40 \
  3>&1 1>&2 2>&3)
  if (( $? == 0 )) && [[ "$pass" != "" ]]; then
     echo "$pass" | su -c 'uxterm -e bash /root/.profile'
  fi
  # следующая команда
  XEXEC=$cmd_menu
}


#========================================
# Основной цикл
#========================================

clear
do_load
while true; do

  case $XEXEC in
    $cmd_menu)     do_menu ;;
    $cmd_connect)  do_connect ;;
    $cmd_set_pass) do_set_pass ;;
    $cmd_set_name) do_set_user ;;
    $cmd_poweroff) do_poweroff ;;
    $cmd_terminal) do_terminal ;;
    $cmd_exit)     exit ;;
  esac
  
done

Итоговое поведение:

  1. При запуске появляется окно авторизации

  2. При отмене авторизации пользователь в меню может:

    • Подключиться к RDP-серверу

    • Сменить имя пользователя

    • Открыть терминал (с правами root)

    • Выключить компьютер

  3. Логин сохраняется для следующего сеанса

  4. Перед подключением проверяется доступность сервера

Авторизация для подключения к RDP-серверу
Авторизация для подключения к RDP-серверу
Меню пользователя
Меню пользователя

6. Интеграция в автозапуск

Чтобы скрипт запускался автоматически при старте X-сервера, обновите файл /home/user/.xinitrc:

xrdb -merge ~/.Xresources
xsetroot -cursor_name left_ptr
exec xterm -e '/bin/bash ~/rdp.sh'

7. Выбор утилит для создания диалоговых окон

Помимо Whiptail, реализующей псевдо-графику также есть графические утилиты для отображения диалоговых окон: Zenity и Yad. Основной недостаток графических утилит - установка дополнительных библиотек, утяжеляющих систему. Если уж сильно хочется их использовать, то в /home/user/.xinitrcможно запускать скрипт rdp.sh без терминала xterm.

xrdb -merge ~/.Xresources
xsetroot -cursor_name left_ptr
/bin/bash ~/rdp.sh

Автозагрузка графического режима

Теперь, когда графическая подсистема и RDP-клиент настроены, пора автоматизировать запуск. Чтобы при загрузке с USB-носителя система автоматически переходила в графический режим и запускала интерфейс подключения к RDP-серверу.

Для этого воспользуемся systemd — менеджером служб в Linux.

1. Создание сервиса автозапуска X-сервера

Создайте файл сервиса /etc/systemd/system/xuser@.service с содержимым:

[Unit]
Description=X11 server on %I
After=graphical.target

[Service]
User=user
PAMName=login
WorkingDirectory=~

StandardOutput=tty
StandardInput=tty-fail

ExecStart=/usr/bin/xinit -- /usr/bin/Xorg -nolisten tcp :0 vt${XDG_VTNR}

Type=simple
Restart=always
RestartSec=0
UtmpIdentifier=:0
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
IgnoreSIGPIPE=no

[Install]
WantedBy=graphical.target

Пояснение ключевых параметров:

  • User=user — запускает сессию от имени пользователя user

  • ExecStart=... — команда запуска X-сервера

  • Type=simple + Restart=always — гарантирует перезапуск X-сервера при падении

  • %I — подставляет имя экземпляра (например, tty1)

2. Включение графического режима по умолчанию

По умолчанию Debian загружается в multi-user.target (консольный режим). Нам нужно переключиться на graphical.target:

root> systemctl enable graphical.target --force
root> systemctl set-default graphical.target

3. Включение автозапуска X-сессии

Активируйте сервис для первой виртуальной консоли:

root> systemctl enable xuser@tty1.service

За ненадобностью отключить приглашение входа getty:

root> systemctl disable getty@tty1.service

4. Перезагрузка и проверка

Перезагрузите гостевую систему:

root> reboot

Если появилось окно авторизации — значит, система готова к использованию на реальном оборудовании.

Поддержка звука

FreeRDP поддерживает передачу звука с сервера на клиент. Для этого:

  • На RDP-сервере с xrdp должен быть установлен pulseaudio-module-xrdp

  • На клиенте необходимо установить базовую аудиосистему

Выполните в гостевой системе:

root> apt update
root> apt install -y --no-install-recommends alsa-utils

Этого достаточно для воспроизведения звука через локальные устройства.

? Важно: в среде QEMU проверить звук не удастся. Необходимо проверять на физическом оборудовании.

Сжатие образа и запись на USB-носитель

После завершения настройки системы можно создать финальный образ и записать его на USB-носитель для использования в реальных условиях. Выполняем те же действия, как и в предыдущей части. И обязательно делаем резервную копию образа.

1. Обнуление свободного места (в гостевой системе)

Чтобы добиться максимального сжатия qcow2, заполните нулями всё свободное пространство на диске:

root> dd if=/dev/zero of=/root/zero ; rm -f /root/zero ; shutdown -h now

2. Сжатие образа (на хосте)

После выключения виртуальной машины выполните сжатие:

$ qemu-img convert -p -O qcow2 -c image.qcow2 new.qcow2
$ mv new.qcow2 image.qcow2

Итоговый размер: 522 МБ — компактный и готовый к развёртыванию.

3. Запись на USB-носитель

Определить носитель:

$ sudo fdisk -l

Записать на флешку /dev/sdb:

$ sudo qemu-img convert -p image.qcow2 -O raw /dev/sdb

Для загрузки системы с USB-носителя необходимо в биосе компьютера отключить Secure Boot.

4. Запись на жесткий диск

Если вы хотите установить RDP-клиент на жёсткий диск вместо использования флешки:

  1. Загрузитесь с USB

  2. Перейдите в меню «Открыть терминал»

  3. Выполните клонирование:

root> dd if=/dev/sda of=/dev/sdb bs=4M status=progress && sync

Старые данные на жёстком диске будут уничтожены. После этого можно извлечь флешку и загружаться напрямую с жёсткого диска.

Итог

Создан универсальный загрузочный образ RDP-клиента на базе Debian 12
Образ занимает всего 522 МБ и подходит для USB-флешек 4 ГБ
Поддерживается автоматическая загрузка, авторизация и подключение к RDP-серверу
Доступны:

  • Меню пользователя

  • Ввод логина/пароля

  • Выключение и доступ к терминалу

  • Передача звука

Перспективы развития

Для массового развёртывания можно организовать сетевую загрузку через PXE, что полностью исключит необходимость в USB-носителях. Для этого предназначен проект LTSP (Linux Terminal Server Project). Последняя версия позволяет грузить на клиентскую машину как тяжелое ядро системы, на которой установлен, так и малые образы. Предстоит развернуть систему и проверить различные варианты чтобы выбрать самый оптимальный.

Комментарии (0)