
Предупреждение: все прилетевшие тапочки будут проданы, помидоры – съедены, яйца – пожарены, испорченные – выброшены. Те, кто думают, что мы маемся фигней – вы угадали, возьмите с полки пирожок. Автор не призывает бросать мешки грудью на амбразуры. Он вообще ни к чему не призывает – он же не политик и не гражданин с активной гражданской позицией. А вот желающих подискутировать – милости просим. Сегодня я буду рассказывать вам занимательную историю о замене Teamviewer на UltraVNC.
Зачем вообще нужны такие заморочки, ведь Teamviewer такой офигенный? В моем случае это обусловлено несколькими причинами. В работе была нужна система удаленного управления серверами и рабочими станциями пользователей, а их у нас на поддержке >1000. Teamviewer контролируется сторонней компанией и неизвестно, что она делает с трафиком. Teamviewer не пользуется доверием у некоторых наших клиентов. Нам нужны были уникальные ID для всех пользователей. Ну и его стоимость для достаточно большой инфраструктуры очень приличная, что тоже повлияло на решение. При этом у нас достаточно широкие каналы связи и нет жестких требований к скорости отклика, что нивелировало основной недостаток UltraVNC, а именно — более низкую скорость работы.
Как это работает
Исходная архитектура VNC протокола слабо предназначена для работы через глобальные сети. Для этого есть несколько причин.
- Отсутствие шифрования передаваемых данных.
- Короткие пароли (8 символов в современном мире? Вы серьезно?)
- Отсутствие сквозной нумерации серверов, подключение по IP.
- Невозможность работы из-за NAT.
Я, конечно, перечислил не все. Но это основные недостатки, которые мешали нам рассматривать данное решение всерьез. В итоге, все они были тем или иным образом преодолены. Текущая схема работы выглядит примерно так:

Клиентский UltraVNC сервер подключается к нашему репитеру, который одним своим портом (нестандартным) смотрит в интернет и принимает подключения. А мы подключаемся к этому же серверу по внутреннему адресу изнутри и уже оттуда — к клиенту. Соединения шифруются RSA2048/AES256. Так как серверы и клиенты цепляются на разные порты, можно гибко ограничить, у кого и откуда есть право подключения, не трогая возможность UltraVNC-серверов подключаться к репитеру.
Установка UltraVNC репитера
Так как репитер будет единственным публичным сервисом, его настройке надо уделить максимум внимания. Использовать нестандартные порты, блокировать подозрительную активность, например сканирование портов и жестко определять, откуда можно будет подключаться Viewer-ам. Но начнем с самого простого – установки и настройки. Сервер настраивается во втором режиме, третий (через SSL) требует специальных сборок просмотрщиков и серверов, поэтому его решили не использовать.
Итак, заходим на сервер, которому предначертано стать будущим репитером и начинаем колдунство. Установка будет описана для Ubuntu 16.04. Ставим необходимые зависимости.
sudo apt-get install build-essential
Создаем пользователя для запуска репитера.
sudo useradd -c 'UltraVNC Repeater User' -M -s /sbin/nologin uvncrep
Скачиваем исходники репитера.
wget http://www.wisdomsoftware.gr/download/uvncrep017-ws.tar.gz
Распаковываем репитер и заходим внутрь папки.
tar -xzvf uvncrep017-ws.tar.gz && cd uvncrep017-ws
Собираем репитер.
make
Устанавливаем репитер в систему.
sudo ./install.sh
У нас все готово к успешному запуску, но надо немного изменить файл настроек. Поэтому открываем в любимом редакторе /etc/uvnc/uvncrepeater.ini и приводим настройки к следующему виду:
viewerport = 5900
По странной прихоти автора номер порта отличается от стандартного. У себя нестандартный порт мы выставим на файрволе.
logginglevel = 2
Немного повышаем уровень логирования, чтобы видеть информацию о бинде портов и подключениях в логе.
allowedmodes = 2
Запрещаем оба режима, оставляем только 2, потому что первый работает по другому принципу и может создавать для нас уязвимость.
useeventinterface = false
Отключаем отправку сообщений. Пока мы никому ничего отправлять не будем. Может быть потом…
Сохраняем файл и тестируем корректность его настроек.
sudo uvncrepeatersvc /etc/uvnc/uvncrepeater.ini
UltraVnc Linux Repeater version 0.17
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): viewerPort : 5900
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): serverPort : 5500
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): maxSessions: 100
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): loggingLevel: 2
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): ownIpAddress (0.0.0.0 = listen all interfaces) : 0.0.0.0
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): runAsUser (if started as root) : uvncrep
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): Mode 1 connections allowed : No
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): Mode 2 connections allowed : Yes
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): Mode 1 allowed server port (0=All) : 0
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): Mode 1 requires listed addresses : No
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): Mode 2 requires listed ID numbers : No
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): useEventInterface: false
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): eventListenerHost : localhost
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): eventListenerPort : 2002
UltraVnc Sat Feb 11 16:48:29 2017 > listInitializationValues(): useHttpForEventListener : true
UltraVnc Sat Feb 11 16:48:29 2017 > dropRootPrivileges(): privileges successfully dropped, now running as user uvncrep
UltraVnc Sat Feb 11 16:48:29 2017 > routeConnections(): starting select() loop, terminate with ctrl+c
Все в порядке, можно запускать как стандартную службу. Останавливаем репитер с помощью Ctrl+C и запускаем уже как сервис.
sudo systemctl start uvncrepeater
Проверяем, что служба запустилась.
$ ps ax | grep uvnc
11168 ? S 0:00 /usr/sbin/uvncrepeatersvc /etc/uvnc/uvncrepeater.ini
11170 pts/0 S+ 0:00 grep --color=auto uvnc
Файл лога можно посмотреть по адресу /var/log/uvncrepeater.log.
Установка и настройка UltraVNC сервера
Итак, первое препятствие между нами и нирваной рухнуло с треском. Теперь мы можем подключаться к клиентам за NAT. На очереди два следующих – отсутствие сквозной нумерации и шифрования. Настраиваем тестовый UltraVNC-сервер. Так как у нас основной парк управляемых машин – это Windows, установка сервера и клиента будет расписана для них.
Скачиваем необходимые компоненты по ссылкам. Компоненты должны иметь архитектуру (x86 и x64), соответствующую архитектуре компьютера, на который происходит установка сервера.
- UltraVNC Server
- SecureVNC Plugin:
- Mirror Driver

Запускаем установщик UltraVNC сервер. Принимаем условия соглашения и нажимаем Next >.

Вчитываемся с интересом и Next >.

Выбираем папку для установки. Не рекомендуется менять без особой необходимости. Что жать, думаю, и так понятно.

Выбираем установку только UltraVNC Server и нажимаем Next >.

Жмем Next > и никаких гвоздей.

Ставим указанные галочки, чтобы установить UltraVNC сервер как системную службу и запустить его сразу после установки. Жмем Next >.

Смотрим на этот экран с умным видом, потом нажимаем Install.

Здесь есть только одна кнопка для нажима. Жмем на нее.

Снимаем галочку, чтобы не смотреть какие-то последние версии, и жмем Finish.

Кнопконажимательная часть миссии закончена. Теперь надо доустановить необходимые компоненты и настроить сервер. Копируем плагин безопасности в папку UltraVNC.

Распаковываем папку с драйвером.

Заходим в папку с соответствующим драйвером и устанавливаем его путем запуска install.bat.
Внимание! Установку драйвера надо производить с административными правами. Причем запустить от имени администратора только install.bat не получится, потому что он запускает еще одну программу и она будет работать уже не от администратора. Поэтому запускаете консоль от администратора, идете в папку установки драйвера и запускаете install.bat оттуда.
Я выполнял тестовую сборку по XP с правами администратора, потому мне это не потребовалось.

Запускаем настройки VNC сервера – uvnc_settings.exe.

Переходим на вкладку Security.
- В разделе Authentication выставляем два пароля. Пароли должны быть одинаковыми, состоять из цифр и больших и малых латинских букв, не более 8 символов длиной.
- В разделе Encryption ставим галочку Use, выбираем из выпадающего списка наш плагин, и жмем на кнопку Configuration.

Галочки должны стоять так, как показано на скриншоте. Если все правильно, закрываем окно нажатием кнопки Close.

Переходим на вкладку Connection.
- В разделе Multiple connections выбираем Keep existing connections.
- В разделе Disconnect выбираем Do Nothing.

Переходим на вкладку Screen Capture.
- В разделе Advanced выбираем Use system hookdll, Use mirror driver, Remove Aero while connected и Remove wallpaper while connected.

Переходим на вкладку Misc/logging.
- В поле Service command line вбиваем самую главную строку. Эта строка содержит ID и адрес и данные репитера для подключения. Выглядит она так:
-autoreconnect ID:XXXXXXXX -connect <repeater_external_address>:<repeater_port>
ID получается с помощью скрипта по методике приведенной ниже.


После всех проделанных действий нажимаем ОК для сохранения настроек. Потом запускаете настройки еще раз и переходите на вкладку Service. На ней нажатием соответствующих кнопок сначала останавливаете, потом запускаете сервис.
Генерация уникального ID
Скрипт получения 8-значного номера ID. Написан на php, потому что это было проще всего. В качестве источника вдохновения использовались комментарии вот к этому вопросу. Как работает, думаю, пояснять не надо. Почему именно скрипт генерации и почему именно по MAC? Потому что репитер не даст подключиться двум серверам с одинаковым ID, а вести журналы со списками ID было предельно лень. А так как MAC-адреса и так уникальны, то почти гарантированно получаем уникальный номер с достаточно низкой вероятностью коллизии.
<?php
$mac = 'B6-B6-13-18-FF-FF';
$mac = str_split(str_replace([':', '-'], '', $mac));
$sum = 0;
foreach($mac as $part) {
$number = hexdec($part);
$sum = (($sum * 16) + $number) % 99999999;
if($sum < 10000000) $sum += 10000000;
}
echo("$sum\n");
?>
Важно помнить, что коллизию можно обнаружить только по соответствующим логам репитера. Сервис будет стартовать, как ни в чем не бывало. Поэтому при добавлении номера лучше все-таки посматривать за логами.
Установка и настройка UltraVNC Viewer
Скачиваем необходимые компоненты по ссылкам. Компоненты должны иметь архитектуру (x86 и x64), соответствующую архитектуре компьютера, на который происходит установка Viewer.
- UltraVNC Viewer
- SecureVNC Plugin: x86, x64.

Начинаем установку.

Внимательно читаем странное и нажимаем Next >.

Выбираем папку установки и нажимаем Next >.

Выбираем только компонент UltraVNC Viewer и нажимаем Next >.

Оставляем здесь все как есть и просто нажимаем Next >.

Выставляем галочки так, как вам будет удобно и нажимаем Next >.

Отключаем просмотр последних версий снятием галочки и нажимаем кнопку Finish.
Теперь скачиваем файл плагина по ссылке выше и перемещаем его в папку программы. После этого запускаем Viewer.

Устанавливаем все настройки так же, как и на скрине. ID сервера для подключения вводится именно в таком формате, то есть ID:XXXXXXXX. IP и порт репитера вводятся такими, какими были назначены при установке репитера.
Все, можно подключаться и радоваться жизни.
Замечания по использованию
- Не забывайте при подключении устанавливать security плагин. Если его не будет, соединение все равно произойдет, только без шифрования. Заставить UltraVNC Server требовать шифрования мне пока не удалось.
- Донастройте сервис при установке UltraVNC сервера. В процессе использования было отмечено, что сервис сервера иногда падает. Для того, чтобы в нужный момент не потерять связь с машиной рекомендуется в настройках сервиса установить его автоматический перезапуск при падениях.
Увидимся в следующих сериях
Да, UltraVNC, это вам не это. В смысле, по функциональности проще, имеет все отличительные признаки бесплатного ПО, да и вообще, где это видано… Но я считаю, что как инструмент оно вполне имеет право на жизнь, если удовлетворяет требованиям по безопасности и предоставляемому сервису. В дальнейшем хотелось бы прикрутить к нему Single Click, но пока хватает и этого.
P.S. Надеюсь, кому-нибудь пригодится. Буду рад вашим комментариям.